Posts by Tx

    Hi Marcel,


    is there any syntax to use image manipulation like getpixel(),setpixel() with other dicom objects than the default 'Data' ?
    And another question: it seems, that dicomquery() can't handle worklist query level or I have not found the right keyword to use for.
    Regards


    Gerald

    Hi,


    update to 1.4.16f broke a lua script that inserts a ReferencedRTPlanSequence into RTImages.
    These lines are part of it:

    Code
    Data.ReferencedRTPlanSequence={}
    Data.ReferencedRTPlanSequence.ReferencedSOPClassUID=RTPlanStorage
    Data.ReferencedRTPlanSequence.ReferencedSOPInstanceUID=a[1][1]


    Using only the first line correctly inserts an empty ReferencedRTPlanSequence. The second line causes the server to crash - even if the third line is commented out.
    To get the system working again, I downgraded to 1.4.16d.
    1.4.16e has this bug too.


    Gerald

    Hi Marcel,


    I try to code a script that should do several look-ups.


    The file "aliasfileQX.txt" with line
    "IDWRONG IDRIGHT" and additional newline is in conquest *.exe folder


    ImportConverter2 = set 0010,0020 if "%QX0010,0020"
    or
    ImportConverter2 = set 0010,0020 to "%QX0010,0020"


    to reassign few wrong Patient ID doesn't anything - even in highest debug level, but


    ImportConverter2 = nop "%QX0010,0020"


    shows 'nop "IDRIGHT' in serverstatus.log (missing right doublequote) i.e. the lookup works but set command doesn't.


    The use of dbquery() in lua ImportConverter seems to be limited to a single call per dicom object.
    The first dbquery() is executed correctly but a second crashes the server. For debugging purposes I used exactly the same dbquery() twice.
    In highest debug level I can see the correct SELECT parameters in log only for the first dbquery().
    It doesn't matter if I split the task into different ImportConverter.
    Have I to use another command to free memory or environment after dbquery()?
    I tried this with conquest 1.4.16f under XP64 with MySQL and 32bit XP with SQLite driver with identical results.


    lua call in dicom.ini looks so:


    [lua]
    ImportConverter0 = require('ImpCon'); ImpCon()


    and function ImpCon() is in ImpCon.lua in conquest *.exe folder


    Regards


    Gerald

    Hi spanky,


    this happens with private tags and tags, that are not in conquests 'dicom.dic'. Afaik conquest stores data with implicit VR, i.e. VR type is not stored. Only types for the known tags (see dgate.dic) can be regenerated when the object is sent with explicit VR. All the other VR are then 'UN'known.
    Dcmtk has it's own dictionary and can regenerate VR types from implicit transfer syntax or explicit 'UN'. The private tags you don't want to see binary in the output of dcmdump, you can put into dcmtk's 'private.dic'. Under Windows additionally you have to set the environment variable 'DCMDICTPATH' to something like 'C:\dcmtk-3.5.4-win32-i386\lib\private.dic' (see dcmtk help>related pages>dcmdump>environment). So when the receiving side is dcmtk and it knows all the tags you need, you are independent of the transfer syntax used.
    But be aware, that many commercial products remove private tags they don't know.


    Gerald

    Hi Marcel,


    probably it's not the right syntax I used.
    I tried
    print(Data['ExposureSequence']) -> userdata:... may be, this really exists
    print(Data['ExposureSequence.0.BeamLimitingDeviceSequence.0.RTBeamLimitingDeviceType']) -> userdata:... I expected 'MLCX' in the example above
    print(Data['ExposureSequence.1']) -> userdata:... this sequence element doesn't exist, I expected 'nil'
    print(Data['ExposureSequence.5.BeamLimitingDeviceSequence']) -> userdata:...


    There are no more empty sequence elements in Data but also no information about existing and non-existing elements.
    Please correct me.


    Gerald

    Hi,


    I use a Lua RetrieveResultConverter to adapt archived RT data from Helax TMS to newer treatment planning without modifying the archived data.
    Now I run into a problem in sequences:
    Some sequences like '(300a,00b6)-BeamLimitingDeviceSequence' are of unknown length.
    I did not succeed with Lua functions like
    'bldmax=#Data.ExposureSequence[ex].BeamLimitingDeviceSequence' or
    'bldmax=table.getn(Data.ExposureSequence[ex].BeamLimitingDeviceSequence)'
    because of type 'userdata'.
    To point out the problem I used this Lua function as RetrieveResultConverter for RTIMAGE from our linac

    Code
    function rrc0() writedicom(Data,Data.SOPInstanceUID..'-before') if Data.Modality=='RTIMAGE' then print('RTImage from',Data.RadiationMachineName) ex=0 while Data.ExposureSequence and Data.ExposureSequence[ex] and Data.ExposureSequence[ex].BeamLimitingDeviceSequence do print(' Exposure #',ex,' Frame=',Data.ExposureSequence[ex].ReferencedFrameNumber) bld=0 while Data.ExposureSequence[ex].BeamLimitingDeviceSequence and Data.ExposureSequence[ex].BeamLimitingDeviceSequence[bld] and Data.ExposureSequence[ex].BeamLimitingDeviceSequence[bld].RTBeamLimitingDeviceType do print(' BeamLimitingDevice #',bld,'=',Data.ExposureSequence[ex].BeamLimitingDeviceSequence[bld].RTBeamLimitingDeviceType) bld=bld+1 end -- BeamLimitingDeviceSequence ex=ex+1 end -- ExposureSequence end writedicom(Data,Data.SOPInstanceUID..'-after')end


    There is no explicit modification of 'Data' in the lua function, but the dump of the dicom file saved at the end of the function shows additional empty sequence elements:


    If the receiving system is another conquest, I can't see these empty elements in the header dump of the gui, but they are sent over the network and Masterplan chokes on RTPLANs containing such sequence elements reporting parsing errors.
    Access to the not existing 'Data.ExposureSequence[1]' in line 7 of the function doesn't give result 'nil' but generates an empty sequence element as I further tested. It is not possible to destroy the empty element after the loop by 'Data.ExposureSequence[ex]=nil' after line 18.


    What is the recomended way to parse sequences without this result?


    Gerald

    Hi,


    please help me to understand the RejectedImageConverter.
    It seems that at first the sending system gets the "image rejected" answer and thereafter the converter is executed.
    Some of our nodes break the transfer if a single image in the middle is rejected.
    How could I prevent the "image rejected" answer to the sending system?
    Is it possible to do the inconsitency test after the RejectedImageConverter again?
    So one could solve the problem for instance by the newuids command, the lua chunk from this post http://forum.image-systems.biz…f=33&t=2478&p=10110#p9736 or save such images for further investigation and destroy thereafter without a break of the transfer.


    Gerald

    Hi Marcel,


    some wider sql binding could help sharing data between threads.
    I think of a free function sql(<any valid sql>) as the flexible way.


    Correct me if I'm wrong, dbquery() seems to be limited to SELECT

      a=dbquery(b,c,d)


    does build and execute this

      "SELECT <c> FROM <b> WHERE <d>"


    and returns the result array in a.
    d can contain everything legal after "WHERE" in SELECT syntax.


    With (manually or lua created) additional table "UserTable" in Conquest database

      sql("INSERT INTO UserTable (CounterID,Val) VALUES ('CT',1) ON DUPLICATE KEY UPDATE Val=Val+1")


    would count up the CT counter or create it when not there. (See Lua http://forum.image-systems.biz/viewtopic.php?f=33&t=3111)


    If you could easily make the truncate function for database field names available to lua, this would be nice.


    Is the result of GetVR() allways in little endian order or where can I get the order from?


    Gerald

    Hi Marcel,


    I wanted to know the index range used for the returned table od and so I tried to print before it starts and beyond the end, i.e. from -1 to 5.
    The first output line shows #od witch I considered to be something like "size of". As you corrected, this gives the index of the last element.
    The next line is od[-1] and there is no value so it prints "nil". I think you shouldn't worry about this.
    The next output lines show the real content and above its last element "nil" again.


    Gerald

    Hi,


    I played a bit with lua and overlay. This is the relevant part of the GUI header dump

    Code
    (6000,0000) UN \80\80\00\00 # 4 ?(6000,0010) UN \00\02 # 2 ?(6000,0011) UN \00\02 # 2 ?(6000,0015) UN [1 ] # 2 ?(6000,0022) UN [Siemens MedCom Object Graphics] # 30 ?(6000,0040) UN [G ] # 2 ?(6000,0050) UN \01\00\01\00 # 4 ?(6000,0051) UN \01\00 # 2 ?(6000,0100) UN \01\00 # 2 ?(6000,0102) UN \00\00 # 2 ?(6000,3000) UN (not loaded) # 32768 ?


    Because I got problems calculating the right overlay size, I run this for the tags above

    Code
    VR='6000,0010'print(VR,' type:',type(Data[VR]),' = ',Data[VR])


    and this is the (cleaned) output

    Code
    6000,0000 type: nil = nil6000,0010 type: nil = nil6000,0011 type: nil = nil6000,0015 type: string = 16000,0022 type: string = Siemens MedCom Object Graphics6000,0040 type: string = G6000,0050 type: string = 6000,0051 type: string = 6000,0100 type: string = 6000,0102 type: nil = nil


    every VR starting with a null character is of type nil and I don't know how to get the expected value. Tags 6000,0050 and 6000,0051 consists of only one character with code 1.
    It looks like the method above works for string-like VR, but not for binary data.


    At next I tried the new command GetVR() for the binary values

    Code
    od=Data:GetVR(0x6000,0x0010)print(#od)for i=-1,5 do print(od[i]) end


    This is the cleaned output

    Code
    1nil02nilnilnilnil


    and for tag 6000,0050

    Code
    3
    nil
    1
    0
    1
    0
    nil
    nil


    This works well but I'm a bit confused about #od beeing one less than the real table size.
    I don't know lua very well, but I assume, that this is because the first table element has the index [0].


    Btw. the result dicomobjectarray of the "dicomquery()" command starts at [0], and the result of "dbquery()" at [1][1].
    May be this is not relevant when the lua iterators pairs() or ipairs() are used.


    Gerald

    Hi,


    access to tag 6000,3000 seems not to work correctly. Function testfn() called from importconverter0


    Code
    function testfn() print('Type : ',type(Data['6000,3000'])) print('Length : ',#Data['6000,3000']) print(Data['6000,3000']) Data['6000,3000']=string.sub(Data['6000,3000'],1,25088)end


    produced the following output to serverlog


    Code
    [CQDCM1416] Type : string[CQDCM1416] Length : 10[CQDCM1416] (too long)[CQDCM1416] Importconverter-1.0 executes: set 6000,3000 to "(too long)"


    And exactly


    Code
    (6000,3000) UN [(too long)] # 10 ?


    is the new content of tag 6000,3000. But I can remove it when I assign nil.
    Is there another lua binding for large binary VRs necessary? If so, please put it on the wishlist. Lua integration in Conquest is great!


    Gerald

    Hi,


    you're right, the received data is correctly stored at mag0 and looks like

    Code
    ...(300a,0006) DA [20090129] # 8 RTPlanDate(300a,0007) TM [152448.11 ] # 10 RTPlanTime(300a,000c) CS [TREATMENT_DEVICE] # 16 RTPlanGeometry(300a,0010) SQ (empty) # 0 DoseReferenceSequence (300a,0000) UL 116 # 4 RTPlanGroupLength (300a,0012) IS [1 ] # 2 DoseReferenceNumber (300a,0014) CS [COORDINATES ] # 12 DoseReferenceStructureType (300a,0016) LO [Evaluation normalization point dose ] # 36 DoseReferenceDescription (300a,0018) DS [-89.98\40.83\-20.00 ] # 20 DoseReferencePointCoordinates (300a,0020) CS [TARGET] # 6 DoseReferenceType(300a,0070) SQ (empty) # 0 FractionGroupSequence (300a,0000) UL 38 # 4 RTPlanGroupLength (300a,0071) IS [1 ] # 2 FractionGroupNumber (300a,0078) IS (empty) # 0 NumberOfFractionsPlanned (300a,0080) IS [2 ] # 2 NumberOfBeams (300a,00a0) IS [0 ] # 2 NumberOfBrachyApplicationSetups (300c,0000) UL 236 # 4 RTRelationshipGroupLength (300c,0004) SQ (empty) # 0 ReferencedBeamSequence (300a,0000) UL 56 # 4 RTPlanGroupLength (300a,0082) DS [-89.98\40.83\-20.00 ] # 20 BeamDoseSpecificationPoint...


    but the by importconverters "save to" command saved "original" data looks so:

    Code
    ...
    (300a,0006) DA [20090129] # 8 RTPlanDate
    (300a,0007) TM [152448.11 ] # 10 RTPlanTime
    (300a,000c) CS [TREATMENT_DEVICE] # 16 RTPlanGeometry
    (300a,0010) SQ (empty) # 0 DoseReferenceSequence
    (300a,0070) SQ (empty) # 0 FractionGroupSequence
    (300a,00b0) SQ (empty) # 0 BeamSequence
    (300a,0180) SQ (empty) # 0 PatientSetupSequence
    ...


    This seems like lossy RTPlan compression. 8)


    Gerald

    Hi,


    we have a problem with some MR stydies: our Syngo RT division of workstations doesn't accept some series at network level whereas diagnostic workstations (Centricity RA600), clinic pacs, and Conquest don't have any problem with them.
    It's been investigated, that the 6000,xxxx overlay plane module generated by Syngo MR is the cause.


    In Conquest 1.4.16 this part dumps to


    Code
    (6000,0010) UN \c0\01 # 2 ?(6000,0011) UN \c0\01 # 2 ?(6000,0015) UN [1 ] # 2 ?(6000,0022) UN [Siemens MedCom Object Graphics] # 30 ?(6000,0040) UN [G ] # 2 ?(6000,0045) UN [USER] # 4 ?(6000,0050) UN \01\00\01\00 # 4 ?(6000,0051) UN \01\00 # 2 ?(6000,0100) UN \01\00 # 2 ?(6000,0102) UN \00\00 # 2 ?(6000,3000) UN (not loaded) # 25202 ?


    more clear from dcmtk:



    Size of overlay data should be 448 x 448 x 1bit = 25088byte
    In every image of the same dimension 448 x 448 the size of overlay data is different but too big.
    Is there a way to simply resize tag 6000,3000?
    How can I adress unknown tags numerical in lua (like %V6000,0010 in traditional Conquest converter scripts)?
    We don't really need the overlay. How could I remove all 6000,xxxx tags without addressing each tag individually?


    Thanks in advance


    Gerald

    Hi,


    I use an Importconverter like

    Code
    ImportConverter1 = save to F:\Exchange\TMS_Original\%V0008,0018.dcm; set 0008,1030 to "%V0020,0010"; set 0010,0030 to "20%i[4,5]%i[2,3]%i[0,1]"; ifnumgreater "%V0010,0030","%V0008,0020"; set 0010,0030 to "19%i[4,5]%i[2,3]%i[0,1]"


    in the idea to preserve unmodified images for the case I have to detect, where a certain problem with the modified images come from.


    Now I noticed, that all sequences (3002,0030 ExposureSequence, 3006,0010 ReferencedFrameOfReferenceSequence, 300A,0010 DoseReferenceSequence, 300A,0070 FractionGroupSequence, 300A,00B0 BeamSequence and some more RT specific sequences) have length 0. Some private sequences of the planning system are preserved.
    I got the same behavior for Conquest 1.4.14 and 1.4.16.
    In Conquest 1.4.16 lua does the same:

    Code
    ImportConverter1 = lua "Data:Write('F:\\Exchange\\TMS_Original\\'..Data.SOPInstanceUID..'.dcm')";


    or

    Code
    ImportConverter1 = lua "writedicom(Data,'F:\\Exchange\\TMS_Original\\'..Data.SOPInstanceUID..'.dcm')";


    To have only a look at the original data this lua syntax dumps all sequences:

    Code
    ImportConverter1 = lua "Data:Dump('F:\\Exchange\\TMS_Original\\'..Data.SOPInstanceUID..'.txt')";


    Is this a bug or a feature?


    Gerald