Strange behavior on XML2DCM

All other questions regarding DCMTK

Moderator: Moderator Team

Post Reply
Message
Author
NDT
Posts: 7
Joined: Mon, 2006-10-16, 10:08

Strange behavior on XML2DCM

#1 Post by NDT »

Hi,
We have an application managing Dicom files.
one Job of this application is to receive some XML Files and converts them to dicom for further processing.
To avoid re-inviting the wheel we spawn a process and use xml2dcm to do the conversion.
Generally that works fine and fast.
But sometimes after our application was started the first time when we try to import a XML file we have a strange behavior.
There is a private tag inside the XML file specified as unlimited text (EVR_UT)
and the conversion of that tag to DICOM only does happen if the text size is <= 4096. If the text is larger XML2DCM determines the right size and everything else seems to be converted correctly but it leaves the text empty and does not copy the text to the dcm file.
here is the element that failes

Code: Select all

            <element tag="3215,0056" vr="LO" vm="1" len="25" name="PrivateCreator">SomeNameToIdentifyPrivate</element>

            <element tag="3215,5622" vr="UT" vm="1" len="200000" name="Parameters">
              [BasicEngine.AbstractParams]
              AcquisitionWidth      =    50.00:50.00 #dddd
              AmpRulerStart         =     0
              AmpRulerStop          =   100
              AmpRulerVisible       = "Show"
              AOFDepthBegin         =     0.00      # mm
              AOFDepthEnd           =    60.00      # mm
              AOFHorizontalBegin    =   -15.00      # mm
              AOFHorizontalEnd      =    45.00      # mm
              AOFVerticalBegin      =    -1.00      # mm
              AOFVerticalEnd        =     1.00      # mm
              AOIDepthBegin         =     0.00      # mm
              AOIDepthEnd           =    50.00      # mm
              AOIHorizontalBegin    =     0.00      # mm
              AOIHorizontalEnd      =    27.67      # mm
              AOIVerticalBegin      =   -12.84      # mm
              AOIVerticalEnd        =    25.05      # mm                # calculated!
              AScanRectification    = "FULL WAVE"
              AScanVisible          = "Show"
              BeamCursorShape       = "Off"
              BGateLogic            =     0:0 # 0 ~ Off, 1 ~ Coi, 2 ~ AntiCoi
              ColorbarPalette       = "AMP"
              ColorbarVisible       = "Show"
              CpColorsAmp           =   100:100:100 : 255:255:255 : 000:255:000 : 000:255:000 : 255:000:000 : 255:000:000 : 255:000:000 : 0
              CpCompressAmp         =     0
              CpCursorAmpColor      =     0:255:255
              CpNoUltraSoundColorAmp=     0:0:0
              CpNumColorsAmp        =     5
              CpRejectAmp           =     0
              CpShadingAmp          = "Linear"
              CpThresholdAmp        =     0:65:65:75:75:100
              DataCursorFV_Visible  = "Hide"
              DataCursorTSEV_Visible= "Hide"
              DigitalGain           =    30.0:30.0       # dB
              DisplayStart          =     0.00      # mm
              DisplayWidth          =    50.00      # mm
              DualMode              = "OFF"
              FillMode              = "Full Space"
              FrameViewCorrection   = "AngleCorrected"
              FrequencySelect       =     0 # 0 ~ 50MHz, 1 ~ 100MHz sampling rate
              FrameCursorVisible    = "Hide"
              FrameViewCorrection   = "AngleCorrected"
              GateResultCurveVisible= "Show"
              GateResultEnvelopeVisible= "Show"
              GateMarkers           = "Hide"
              IFGateLogic           =     0 # 0 ~ Off, 1 ~ Coi, 2 ~ AntiCoi
              Layout                = "PaScan"
              MagnifyCursorFV_Visible= "Hide"
              MagnifyCursorTSEV_Visible= "Hide"
              MaterialThickness     = 12
              MaterialVelocity      = 3250
              MeasurementCursorFV_Visible = "Hide"
              MeasurementCursorTSEV_Visible = "Hide"
              MeasureMode           = "PA"
              PRF                   = 460
              PulserVoltage         = 40
              PulserWidth           = 80.000000:80.000000
              ReadoutsVertical      = false
              ScanAxisVertical      = "True"
              Shape                 = "Flat"
              SoundPathRuler        = "Material SP"
              TCGEnable             = 0:0
              TOFCompression = "Maximum"
              TOFRange = "Acquisition"
              TSEViewCorrection = "AngleCorrected"
              TTLAlarmPolarity = "Active HIGH"
              TopReadout1 = "Amplitude"
              TopReadout2 = "DataCursorPos"
              TopReadout3 = "BeamIndex"
              TopReadout4 = "ProbePos"
              TopReadout5 = "BeamSelect"
              [BasicEngine.DerivedParams]
              ReceiveDelay        = 610 :  570 :  530 :  495 :  455 :  415 :  375 :  335 :  290 :  250 :  210 :  170 :  130 :   85 :   45 :    0
              
              ReceiveEnable       = 1:1
              TransmitDelay       = 610 :  570 :  530 :  495 :  455 :  415 :  375 :  335 :  290 :  250 :  210 :  170 :  130 :   85 :   45 :    0
              TransmitEnable      = 1:1

            </element>

The most strange thing is that it only happens the First time we try to import the file.
Our application checks if the dicom file is already imported and only imports if not available. So a delete of the converted file and again an import and it will work correctly.
Does anyone have an idea what happens here?

Below is the code I use to spawn the process:

Code: Select all

		if(DoesFileExist(TargetFile.c_str())==false)
		{

			STARTUPINFO StartupInfo;
			PROCESS_INFORMATION ProcessInformation;
			std::wstring CommandLine=L"xml2dcm.exe ";
			memset(&StartupInfo,0,sizeof(StartupInfo));
			StartupInfo.cb=sizeof(StartupInfo);
			memset(&ProcessInformation,0,sizeof(ProcessInformation));
			CommandLine+= L"--verbose --debug --write-xfer-little \"";
			CommandLine+=Source.c_str();
			CommandLine+=L"\" \"";
			CommandLine+=TargetFile.c_str();
			CommandLine+=L"\"";
			memset(&StartupInfo,0,sizeof(StartupInfo));
			StartupInfo.cb=sizeof(StartupInfo);
			memset(&ProcessInformation,0,sizeof(ProcessInformation));
			StartupInfo.lpDesktop=L"";
			StartupInfo.lpTitle=L"";
			StartupInfo.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
			StartupInfo.wShowWindow=SW_HIDE;
			std::wstring STDOut;
			std::wstring STDErr;
			std::wstring STDIn;
			SECURITY_ATTRIBUTES SA;
			SA.nLength=sizeof(SA);
			SA.lpSecurityDescriptor=NULL;
			SA.bInheritHandle=TRUE;

			STDOut = STDErr= STDIn=TargetFile;
			STDOut+=L".out.txt";
			STDErr+=L".err.txt";
			STDIn+=L".In.Txt";
			StartupInfo.hStdOutput=CreateFile(STDOut.c_str(),FILE_ALL_ACCESS,0,&SA,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
			StartupInfo.hStdError=CreateFile(STDErr.c_str(),FILE_ALL_ACCESS,0,&SA,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
			StartupInfo.hStdInput=CreateFile(STDIn.c_str(),FILE_ALL_ACCESS,0,&SA,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
			

			BOOL CreateProcessStatus = CreateProcess( NULL,
												 (LPTSTR)CommandLine.c_str(),
												 NULL,
												 NULL,
												 TRUE,
												 CREATE_UNICODE_ENVIRONMENT,//CREATE_NO_WINDOW/*|CREATE_UNICODE_ENVIRONMENT*/,
												 NULL,
												 NULL,
												 &StartupInfo,
												 &ProcessInformation
											   );

			if(CreateProcessStatus!=FALSE)
			{
				DWORD ExitCode;
				WaitForSingleObject( ProcessInformation.hProcess, INFINITE );
				GetExitCodeProcess(ProcessInformation.hProcess,&ExitCode);
				if(ExitCode!=0)
					ReportError(PACKAGE_NAME L"ImportInspectionPlans", L"Exit code of xml2dcm !=0 at File %s Line %d",__FILEW__,__LINE__);
				else
				{
					IPImportList.push_back(m_ExternalIPList[i]);
					InsertNewIPFile(TargetFile.c_str());
				}
				CloseHandle( ProcessInformation.hProcess );
				CloseHandle( ProcessInformation.hThread );
			}
			CloseHandle(StartupInfo.hStdOutput);
			CloseHandle(StartupInfo.hStdError);
			CloseHandle(StartupInfo.hStdInput);

		}
Dcmdmp tells

Code: Select all

        (3215,5622) UT [ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ... # 4098, 1 SetupParameters
about that tag.
if you replace

Code: Select all

              AcquisitionWidth      =    50.00:50.00 #dddd
with

Code: Select all

              AcquisitionWidth      =    50.00:50.00 #ddd
DCMDMP tells

Code: Select all

        (3215,5622) UT [
              [BasicEngine.AbstractParams]
              Acquisit... # 4096, 1 SetupParameters
It is absolute not clear to me what can happen that the CreateProcess call can spawn the program, but sometimes stop it to fill large memory.
I know this is not a completely XML2DCM problem, but may be someone here already had seen such behavior before.

I played a little bit with the CreateProcess to get the Output Dcm2xml writes to stdout /STDError, but it only reports that it generates the files. even with Verbose and debug no interesting output there.

Thanks in advance and
best regards

NDT
Posts: 7
Joined: Mon, 2006-10-16, 10:08

#2 Post by NDT »

I got it! :D
The problem was not DCMTK.
The problem was that an other module modified some entries directly after the conversion to dcm file. But it saved the file without a loadAllDataIntoMemory() :oops: call so data that was larger than default size was not loaded. And that data was not loaded automatically before the it was stored. :idea:

Post Reply

Who is online

Users browsing this forum: Google [Bot] and 1 guest