Lua Export Script using PatientMainDicomTags

Hi Orthanc Group.

I have a script that can’t separating multiple exams with with the same PatientID but different PatientNames, they are all being merged under a single PatientName.

  • All CTs and MRs (using an if string.find) is PatientID/PatientName/Modality/StudyDescription/SeriesDescription
  • For RF/US it’s just PatientID/PatientName/Modality/StudyDescription

The research group are using the PatientID as the Research Project Title, then record each study with a unique PatientName, for instance:

  • 2244, PIG 01
  • 2244, PIG 02
  • 2244, PIG 03 etc.
    When my script outputs this data using ‘/series/ … seriesId … /patient))[MainDicomTags]’ it only recognises a single PatientName merging all studies together underneath it. I think something to do with MainDicomTags but under Study I found PatientMainDicomTags where I’m seeing the unique PatientName but I’m having trouble understanding how I would call it in my script. I just don’t know how to or if it’s possible.

I can see the PatientMainDicomTags in a curl lookup under study but I don’t know how to translate that into the script.

Below is my original ‘working’ script I cobbled together from different scripts found in this group except all studies are merged under the same PatientName. I know the else is not needed but I might need to add something different for another potential modality in the future.

1 TARGET = ‘/opt/Imaging_Data/’
2
3 function ToAscii(s)

4 return s:gsub(‘[^a-zA-Z0-9-\/-:.()]’, ‘_’)
5 end
6
7 function OnStableSeries(seriesId, tags, metadata, origin)
8 print(‘This series is now stable, writing its instances on the disk: ’ … seriesId)
9 PrintRecursive(origin)
10
11 local modality = string.lower(tags[‘Modality’])
12 local instances = ParseJson(RestApiGet(’/series/’ … seriesId)) [‘Instances’]
13 local patient = ParseJson(RestApiGet(‘/series/’ … seriesId … ‘/patient’)) [‘MainDicomTags’]
14 local study = ParseJson(RestApiGet(‘/series/’ … seriesId … ‘/study’)) [‘MainDicomTags’]
15 local series = ParseJson(RestApiGet(‘/series/’ … seriesId)) [‘MainDicomTags’]
16
17
18 if string.find(modality, ‘MR’) or not string.find(modality, ‘CT’) then
19 for i, instance2 in pairs(instances) do
20 local path2 = ToAscii(TARGET … ‘/’ …
21
22
23 patient[‘PatientName’] … ‘-’ … study[‘StudyDate’] … ‘/’ … patient[‘PatientID’] … ‘/’ … series[‘Modality’] … ‘/’ … study[‘StudyDescription’] … ‘/’ … series[‘SeriesDescription’])
24
25 local dicom = RestApiGet (‘/instances/’ … instance2 … ‘/file’)
26 os.execute(‘mkdir -p "’ … path2 … ‘"’)
27
28 local target = assert(io.open(path2 … ‘/’ … instance2 … ‘.dcm’, ‘wb’))
29 target:write(dicom)
30 target:close()
31
32 end
33
34 elseif string.find(modality, ‘US’) or not string.find(modality, ‘RF’) then
35 for i, instance1 in pairs(instances) do
36 local path1 = ToAscii(TARGET … ‘/’ …
37 patient[‘PatientID’] … ‘-’ … study[‘StudyDate’] … ‘/’ … series[‘Modality’] … ‘/’ … patient[‘PatientName’] … ‘/’ … study[‘StudyDescription’])
38
39 local dicom = RestApiGet(‘/instances/’ … instance1 … ‘/file’)
40 os.execute(‘mkdir -p "’ … path1 … ‘"’)
41
42 local target = assert(io.open(path1 … ‘/’ … instance1 … ‘.dcm’, ‘wb’))
43 target:write(dicom)
44 target:close()
45
46 end
47
48 else
49 local path3 = ToAscii(TARGET … ‘/’ …
50 patient[‘PatientID’] … ‘-’ … study[‘StudyDate’] … ‘/’ … series[‘Modality’] … ‘/’ … patient[‘PatientName’] … ‘/’ … study[‘StudyDescription’])
51 local dicom = RestApiGet(‘/instances/’ … instance3 … ‘/file’)
52 os.execute(‘mkdir -p "’ … path3 … ‘"’)
53 local target = assert(io.open(path3 … ‘/’ … instance3 … ‘.dcm’, ‘wb’))
54 target:write(dicom)
55 target:close()
56
57 end
58 end

Hi,

You can not trust the /patients/ route if all your patients have the same PatientID since the PatientID is the key identifier for patients.

Around line 12-13 of your script, instead of calling
local patient = ParseJson(RestApiGet(‘/series/’ … seriesId … ‘/patient’)) [‘MainDicomTags’]

you should probably have something like:
local instanceTags = ParseJson(RestApiGet(‘/instances/’ … instances[0] … ‘/tags?simplify’))
and then:
local patientName = instanceTags[‘PatientName’]

With this code, you’ll get the PatientName from the instance file itself not from the DB.

HTH

Alain.

Thank you for the advice. From that, I managed to get what I needed from OnStoredInstance

For anyone that finds this conversation, my final script looks like

TARGET = '/opt/dcmconf/datastore/Imaging_Data/'

function ToAscii(s)

return s:gsub(‘[^a-zA-Z0-9-/-:.()]’, ‘_’)

end

function OnStoredInstance(instanceId, tags, metadata, origin)

print('This series is now stable, writing its instance on the disk: ’ … instanceId)

local inst = ParseJson(RestApiGet(‘/instances/’ … instanceId)) [‘ID’]

local patient = ParseJson(RestApiGet(‘/instances/’ … inst … ‘/patient’))

local iTags = ParseJson(RestApiGet(‘/instances/’ … inst … ‘/simplified-tags’))

local modality = iTags[‘Modality’]

local seriesdesc = iTags[‘SeriesDescription’]

print('the “local modality = iTags…” variable: ’ … modality)

print('StudyDescription from Simplified-Tags: ’ … iTags[‘StudyDescription’])

print('the type(instances) is: ’ … type(inst))

if modality == ‘MR’ then

local path2 = ToAscii(TARGET … ‘/’ …

iTags[‘PatientID’] … ‘-’ … iTags[‘StudyDate’] … ‘/’ … iTags[‘Modality’] … ‘/’ … iTags[‘PatientName’] … ‘/’ … iTags[‘StudyDescription’] … ‘/’ … iTags[‘SeriesDescription’])

local dicom = RestApiGet (‘/instances/’ … inst … ‘/file’)

os.execute(‘mkdir -p "’ … path2 … ‘"’)

local target = assert(io.open(path2 … ‘/’ … inst … ‘.dcm’, ‘wb’))

target:write(dicom)

target:close()

print('is the MR path (path2): ’ … path2)

end

if modality == ‘CT’ then

local path3 = ToAscii(TARGET … ‘/’ …

iTags[‘PatientID’] … ‘-’ … iTags[‘StudyDate’] … ‘/’ … iTags[‘Modality’] … ‘/’ … iTags[‘PatientName’] … ‘/’ … iTags[‘StudyDescription’] … ‘/’ … iTags[‘SeriesDescription’])

local dicom = RestApiGet(‘/instances/’ … inst … ‘/file’)

os.execute(‘mkdir -p "’ … path3 … ‘"’)

local target = assert(io.open(path3 … ‘/’ … inst … ‘.dcm’, ‘wb’))

target:write(dicom)

target:close()

print('is the “CT” path (path3): ’ … path3)

end

if modality == ‘US’ then

local path4 = ToAscii(TARGET … ‘/’ …

iTags[‘PatientID’] … ‘-’ … iTags[‘StudyDate’] … ‘/’ … iTags[‘Modality’] … ‘/’ … iTags[‘PatientName’] … ‘/’ … iTags[‘StudyDescription’])

local dicom = RestApiGet(‘/instances/’ … inst … ‘/file’)

os.execute(‘mkdir -p "’ … path4 … ‘"’)

local target = assert(io.open(path4 … ‘/’ … inst … ‘.dcm’, ‘wb’))

target:write(dicom)

target:close()

print('is the “other” path (path4): ’ … path4)

end

if modality == ‘RF’ then

local path5 = ToAscii(TARGET … ‘/’ …

iTags[‘PatientID’] … ‘-’ … iTags[‘StudyDate’] … ‘/’ … iTags[‘Modality’] … ‘/’ … iTags[‘PatientName’] … ‘/’ … iTags[‘StudyDescription’])

local dicom = RestApiGet(‘/instances/’ … inst … ‘/file’)

os.execute(‘mkdir -p "’ … path5 … ‘"’)

local target = assert(io.open(path5 … ‘/’ … inst … ‘.dcm’, ‘wb’))

target:write(dicom)

target:close()

print('is the “other” path (path5): ’ … path5)

end

end