Posts by lploeger

    Indeed, we didn't want to blame Conquest but we had (still have?) to figure out under which circumstances the wrong patient ID winds up in Conquest's database. The Dutch BSNs are typically of length 9 where our patient IDs have a length of 8 digits. Also, the BSN should satisfy this modulus-11 check ('11-proef'), see https://nl.wikipedia.org/wiki/Burgerservicenummer#11-proef (in Dutch). For some phantom data or test data people may come up with a patient ID that resembles an SSN, but this should be considered an exception.

    Perhaps one could also argue that 'incomplete' queries (which could not be sent to the host) should not be stored in the database? Or maybe this can be made configurable behavior? What do you think?

    Hi Marcel,

    As Maarten is currently off I will try to answer. Other than the 'FixKodak' logic we don't modify the Patient ID. In my local database I do see the 'MAG0.0' entries for cases where I deliberately corrupted the AE title causing the download of e.g. RTSTRUCT/RTPLAN to fail.

    As a test I loaded a patient with a known PatientID and SSN into one of our DICOM browsers. First using the SSN as PatientID combined with an incorrect AE title (causing 'Remote DICOM Error code c005'), then with our PatientID with a correct AE title. The latter results in 'Remote DICOM Error code c004'. When I request the data again based on the SSN with a correct AE title it works. Apparently using a query by SSN triggers the PACS to use the SSN number as the primary PatientID, which is stored in the database. So a possible scenario to run into this problem is by first trying to download data by SSN with a wrong AE title (or some other way breaking NewPDU.Connect (IP, lPort), perhaps a user hitting the 'Cancel' button), after which subsequent queries based on our PatientID will fail.

    Veel dank & hartelijke groeten,

    Lennert.

    Hi Marcel,

    I hope you are well?

    Recently I did some profiling of the DICOM library code and found that the "Array" class can be optimized. At the moment this is implemented as a linked list, causing quite some overhead when looping over the elements using the Get(Index) function as is the case in e.g. PresentationContext::Size(). After converting this code to a plain array (reallocating it in chunks as the buffer grows), I was able to reduce the time needed to load a CT volume by approximately 20%. This also reduces the code in array.tcc quite a bit as finding an element can simply be implemented as e.g.: return *(first_dyn[IndexIn]) instead of having to follow links to the right node in several steps. This update also implies trivial changes to deivr.cxx and qrsop.cxx as the "DataLink" class will no longer be available. If you are interested I can upload the array.tcc and array.thh files (and deivr.cxx/qrsop.cxx as well) to this forum or perhaps the GitHub location?

    Best regards,

    Lennert.

    I found the discussion on http://forum.image-systems.biz/viewtopic.php?f=33&t=44345 about the PDU size of 16384.

    As Conquest DICOM Server does not take the value of MaxSubLength into account I am not surprised that changing this value to 32768 had no effect. The buffer sizes marked in yellow of 4108 bytes are most likely due to the aforementioned "BlockSize" value being 4096 bytes. Apparently, 12 bytes are added somewhere else. When running a version of dgate64.exe with BlockSize increased to 256KB the "Process Monitor" program provided by SysInternals indeed shows larger buffers being used:

    13:27:20.6558062 dgate64.exe 183252 TCP Send WS0206.nki.nl:1052 -> WS0206.nki.nl:1234 SUCCESS Length: 262144, startime: 5951544, endtime: 5951544, seqnum: 0, connid: 0

    For the shipped version of dgate64.exe this was:

    13:29:56.2398665 dgate64.exe 193828 TCP Send WS0206.nki.nl:1093 -> WS0206.nki.nl:1234 SUCCESS Length: 4108, startime: 5953100, endtime: 5953100, seqnum: 0, connid: 0

    Hi Marcel,

    Good to know that an update to this "MaxSubLength" is already in scope. Is your plan to adjust the buffer sizes for data transfer accordingly, or is this mainly to improve communication with external DICOM software?

    Next time, I will try to make it to ESTRO!

    Best regards,

    Lennert.

    Hi Marcel,

    In the code I found another somewhat arbitrary number related to buffer sizes. In pdu.cxx in InterogateAAssociateRQ() and also in Connect() there is this statement:

    MaxSubLength.Set(16384); // we can do all DICOM can handle

    This number seems to be inspired by the example value on http://dicom.nema.org/medical/dicom/…sect_D.3.3.html. The Conquest DICOM server itself does not take this value into account as far as I can tell. Other implementations don't accept larger buffers in e.g. PDataTF::Write(Buffer &Link), like we encountered while writing data to Pinnacle with a "BlockSize" of 262144 bytes. To be able to write to both Pinnacle and Conquest DICOM server with the same code in CqDicom.dll, would it be possible to use MaxSubLength.Set(262144) instead in a future version?

    Best regards,

    Lennert.

    Thank you Marcel!

    I applied this change in pdata.cxx:

    Code
    BOOL    PDataTF ::      Write(Buffer    &Link)
            {
            // Generate P-DATA-TF Messages.
            UINT    BlockSize, SentSize, TotalSize, TLength;
    
    
            TotalSize = VRBuffer.GetOutgoingSize();
            BlockSize = 262144; // was 4096;
    (..)
    }

    To take advantage of this code you may also want to change ReadBlock() in buffer.cxx (currently this is a hard-coded value of 10240) and the #define DEFAULT_BREAK_SIZE of 8192 or 32600, combined with a new build of CqDicom.dll.

    While investigating the performance of dgate.exe I found that the speed is limited by the current buffer size in pdata.cxx, which is set to 4096 bytes. By enlarging this BlockSize in PDataTF::Write() to e.g. 262144 I observed a speedup of approximately 40% on a local DICOM server for a test case of 680 slices.

    I tried to find some references for the optimal buffer size and found this link: https://stackoverflow.com/questions/2862…-socket-library, where 256kB is advised.

    Do you think it is a good idea to increase the buffer size in a future version?

    Lennert.

    Thanks again Marcel.

    Currently anonymization is only performed on local DICOM servers, so I do not expect that anonymization will take more than 5 minutes this way. Fortunately, we have the technique of using the "modifystudy" command documented this way, so hopefully others can benefit from my hunt for a solution.

    Best regards,

    Lennert.

    Hi Marcel,

    Thank you for your swift reply. My understanding was that the "'modifystudy" command required a valid StudyInstanceUID, but it seems that it can be left out. In windowsmanual.pdf it is documented as:

    Quote

    --modifystudy:p,s,script Change items in patient or study

    Having a shortcut like "--anonymize:oldpatid,newpatid" would further facilitate this process. Does this sound reasonable?

    Best regards,

    Lennert.

    Hi Marcel,

    I hope you are doing well. At AVL I got a few requests to run anonymization in batch mode, i.e. for multiple patients at once.

    To achieve this I looked at connecting the Conquest DICOM server to ZeroBrane Studio to open up the scripting capabilities. I came up with this solution:

    1. Create a local file e.g. "anonpat.lua" with the following content:

    2. Modify the three lines of code marked with "Change This" to your liking. For large scale anonymization we can optimize this by e.g. reading the pair of new and old names from a text file. Note: the name 'CONQUESTSRV1' has to match with an entry in your ACRNEMA.MAP (4th screen of the Conquest DICOM server).

    3. Start ZeroBrane Studio and connect it to your local DICOM server (this may require to run the install.lua script from the lua folder for the DICOM server first).

    4. Run the script above by pressing the "Play" button twice

    Is this also how you would suggest to do this, or is there a more straightforward approach?

    Best regards,

    Lennert.

    Hi Marcel et al.,

    I am trying to automate a few tasks using the lua interface you added to the DICOM server. I used the following approach suggested by you:

    <q>
    Download and install server 1.4.17, download and unzip zerobranestudio 0.38. Run dicomserver/zerobranestudio/install.lua in zbs as described in its header and you have created a working scripting IDE in zbs with debugging, code completion and all.
    </q>

    After this I was able to run the "livecoding.lua" example, great!

    From the local console I tried an example described in overview.lua (from ZBS Local console):

    print(Association.Calling, Association.Called, Association.Thread, Association.ConnectedIP)

    This results in

    [string "print(Association.Calling, Associati..."]:1: attempt to index global 'Association' (a nil value)

    Do you know how to solve this? Perhaps zbstudio.exe should be in the same folder as dgate64.exe?

    Best regards & many thanks,

    Lennert.