# HG changeset patch # User Alain Mazy # Date 1650900108 -7200 # Node ID 1f6c9debddf665a866ca8131640361e1be660da5 # Parent e1867aeb57e26c3527465d7f4073683f6ee0aca3# Parent c19d33c5defeb703733e9d6f10ae5af5763575fb merged more-tags -> mainline diff -r e1867aeb57e2 -r 1f6c9debddf6 README --- a/README Wed Apr 20 14:53:22 2022 +0200 +++ b/README Mon Apr 25 17:21:48 2022 +0200 @@ -53,7 +53,7 @@ 2. In the second command shell: -# python ./Tests/Run.py +# python ./Plugins/Worklists/Run.py @@ -125,6 +125,8 @@ To run a single test with by fixing the Orthanc 0.8.6 executable path: # python2 ./Tests/Run.py --orthanc /home/alain/Releases/Orthanc-0.8.6/Build/Orthanc Orthanc.test_peer_store_straight +To run a plugin test (no need for Orthanc 0.8.6) +# python2 ./Plugins/DicomWeb/Run.py Orthanc.test_peer_store_straight Use the flag "--help" to get the full list of arguments. These arguments will notably allow you to specify the network parameters diff -r e1867aeb57e2 -r 1f6c9debddf6 Tests/Tests.py --- a/Tests/Tests.py Wed Apr 20 14:53:22 2022 +0200 +++ b/Tests/Tests.py Mon Apr 25 17:21:48 2022 +0200 @@ -217,6 +217,14 @@ self.assertFalse(IsOrthancVersionAbove(_LOCAL, 0, 9, 6)) self.assertFalse(IsOrthancVersionAbove(_LOCAL, 1, 8, 6)) + system = DoGet(_REMOTE, '/system') + self.assertIn("MainDicomTags", system) + self.assertIn("Patient", system["MainDicomTags"]) + self.assertIn("Studies", system["MainDicomTags"]) + self.assertIn("Series", system["MainDicomTags"]) + self.assertIn("Instance", system["MainDicomTags"]) + + def test_upload(self): self.assertEqual('0', DoGet(_REMOTE, '/statistics')['TotalDiskSize']) self.assertEqual('0', DoGet(_REMOTE, '/statistics')['TotalUncompressedSize']) @@ -1124,8 +1132,12 @@ series = DoGet(_REMOTE, '/series')[0] m = DoGet(_REMOTE, '/patients/%s/metadata' % p) - self.assertEqual(1, len(m)) - self.assertEqual('LastUpdate', m[0]) + if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + self.assertEqual(2, len(m)) + self.assertTrue('MainDicomTagsSignature' in m) + else: + self.assertEqual(1, len(m)) + self.assertTrue('LastUpdate' in m) # The lines below failed on Orthanc <= 1.8.2 self.assertRaises(Exception, lambda: DoGet(_REMOTE, '/studies/%s/metadata' % p)) @@ -1133,11 +1145,19 @@ self.assertRaises(Exception, lambda: DoGet(_REMOTE, '/instances/%s/metadata' % p)) m = DoGet(_REMOTE, '/studies/%s/metadata' % DoGet(_REMOTE, '/studies')[0]) - self.assertEqual(1, len(m)) - self.assertEqual('LastUpdate', m[0]) + if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + self.assertEqual(2, len(m)) + self.assertTrue('MainDicomTagsSignature' in m) + else: + self.assertEqual(1, len(m)) + self.assertTrue('LastUpdate' in m) m = DoGet(_REMOTE, '/series/%s/metadata' % series) - self.assertEqual(2, len(m)) + if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + self.assertEqual(3, len(m)) + self.assertTrue('MainDicomTagsSignature' in m) + else: + self.assertEqual(2, len(m)) self.assertTrue('LastUpdate' in m) # New in Orthanc 1.9.0 @@ -1145,7 +1165,10 @@ self.assertEqual(DoGet(_REMOTE, '/series/%s/metadata/RemoteAET' % series), '') # None, received by REST API m = DoGet(_REMOTE, '/instances/%s/metadata' % i) - if IsOrthancVersionAbove(_REMOTE, 1, 9, 1): + if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + self.assertEqual(10, len(m)) + self.assertTrue('MainDicomTagsSignature' in m) + elif IsOrthancVersionAbove(_REMOTE, 1, 9, 1): self.assertEqual(9, len(m)) self.assertTrue('PixelDataOffset' in m) # New in Orthanc 1.9.1 self.assertEqual(int(DoGet(_REMOTE, '/instances/%s/metadata/PixelDataOffset' % i)), 0x0c78) @@ -1178,7 +1201,11 @@ self.assertFalse('etag' in headers) m = DoGet(_REMOTE, '/patients/%s/metadata' % p) - self.assertEqual(2, len(m)) + if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + self.assertEqual(3, len(m)) + self.assertTrue('MainDicomTagsSignature' in m) + else: + self.assertEqual(2, len(m)) self.assertTrue('LastUpdate' in m) self.assertTrue('5555' in m) self.assertEqual('coucou', DoGet(_REMOTE, '/patients/%s/metadata/5555' % p)) @@ -1202,7 +1229,11 @@ DoDelete(_REMOTE, '/patients/%s/metadata/5555' % p) m = DoGet(_REMOTE, '/patients/%s/metadata' % p) - self.assertEqual(1, len(m)) + if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + self.assertEqual(2, len(m)) + self.assertTrue('MainDicomTagsSignature' in m) + else: + self.assertEqual(1, len(m)) self.assertTrue('LastUpdate' in m) @@ -1345,7 +1376,10 @@ self.assertEqual(1, len(i)) m = DoGet(_REMOTE, '/instances/%s/metadata' % i[0]) - if IsOrthancVersionAbove(_REMOTE, 1, 9, 1): + if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + self.assertEqual(10, len(m)) + self.assertTrue('MainDicomTagsSignature' in m) # New in Orthanc 1.11.0 + elif IsOrthancVersionAbove(_REMOTE, 1, 9, 1): self.assertEqual(9, len(m)) self.assertTrue('PixelDataOffset' in m) # New in Orthanc 1.9.1 else: @@ -1367,7 +1401,11 @@ series = DoGet(_REMOTE, '/series')[0] m = DoGet(_REMOTE, '/series/%s/metadata' % series) - self.assertEqual(2, len(m)) + if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + self.assertEqual(3, len(m)) + self.assertTrue('MainDicomTagsSignature' in m) + else: + self.assertEqual(2, len(m)) self.assertTrue('LastUpdate' in m) self.assertTrue('RemoteAET' in m) self.assertEqual(DoGet(_REMOTE, '/series/%s/metadata/RemoteAET' % series), 'STORESCU') @@ -1573,6 +1611,11 @@ 'ModalitiesInStudy' : 'US\\CT' }) self.assertEqual(1, len(t)) + t = DoPost(_REMOTE, '/modalities/orthanctest/find-study', { + 'PatientID' : 'B9uTHKOZ', + 'ModalitiesInStudy' : '' }) + self.assertEqual(1, len(t)) + # Test the "find-series" level t = DoPost(_REMOTE, '/modalities/orthanctest/find-series', { 'PatientID' : 'B9uTHKOZ', @@ -7793,8 +7836,12 @@ self.assertEqual('Patient', a[0]['Type']) self.assertEqual('KNEE', a[0]['MainDicomTags']['PatientName']) self.assertTrue('Metadata' in a[0]) - self.assertEqual(1, len(a[0]['Metadata'])) - self.assertTrue('LastUpdate' in a[0]['Metadata']) + if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + self.assertEqual(2, len(a[0]['Metadata'])) + self.assertTrue('MainDicomTagsSignature' in a[0]['Metadata']) + else: + self.assertEqual(1, len(a[0]['Metadata'])) + self.assertTrue('LastUpdate' in a[0]['Metadata']) for level in [ 'Instance', 'Series', 'Study', 'Patient' ]: a = DoPost(_REMOTE, '/tools/bulk-content', { 'Resources' : [ knee1, brainix ], @@ -8438,6 +8485,205 @@ self.assertEqual(1, len(a)) + def test_rest_find_requested_tags(self): + # Upload instances + for i in range(2): + UploadInstance(_REMOTE, 'Brainix/Flair/IM-0001-000%d.dcm' % (i + 1)) + + # Patient level + a = DoPost(_REMOTE, '/tools/find', { 'Level' : 'Patient', + 'CaseSensitive' : False, + 'Query' : { 'PatientName' : 'BRAINIX' }, + 'RequestedTags' : [ 'PatientName', 'PatientID', 'PatientSex', 'PatientBirthDate' ], + 'Expand': True + }) + self.assertEqual(1, len(a)) + self.assertIn('PatientName', a[0]['RequestedTags']) + self.assertIn('PatientID', a[0]['RequestedTags']) + self.assertIn('PatientSex', a[0]['RequestedTags']) + self.assertIn('PatientBirthDate', a[0]['RequestedTags']) + + self.assertEqual('BRAINIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('5Yp0E', a[0]['RequestedTags']['PatientID']) + self.assertEqual('0000', a[0]['RequestedTags']['PatientSex']) + self.assertEqual('19490301', a[0]['RequestedTags']['PatientBirthDate']) + + # Study level, request patient tags too + a = DoPost(_REMOTE, '/tools/find', { 'Level' : 'Study', + 'CaseSensitive' : False, + 'Query' : { 'PatientName' : 'BRAINIX' }, + 'RequestedTags' : [ 'PatientName', 'StudyInstanceUID'], + 'Expand': True + }) + self.assertEqual(1, len(a)) + self.assertIn('PatientName', a[0]['RequestedTags']) + self.assertIn('StudyInstanceUID', a[0]['RequestedTags']) + + self.assertEqual('BRAINIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('2.16.840.1.113669.632.20.1211.10000357775', a[0]['RequestedTags']['StudyInstanceUID']) + + + # Series level, request patient and study tags too + a = DoPost(_REMOTE, '/tools/find', { 'Level' : 'Series', + 'CaseSensitive' : False, + 'Query' : { 'PatientName' : 'BRAINIX' }, + 'RequestedTags' : [ 'PatientName', 'StudyInstanceUID', 'SeriesInstanceUID'], + 'Expand': True + }) + self.assertEqual(1, len(a)) + self.assertIn('PatientName', a[0]['RequestedTags']) + self.assertIn('StudyInstanceUID', a[0]['RequestedTags']) + self.assertIn('SeriesInstanceUID', a[0]['RequestedTags']) + + self.assertEqual('BRAINIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('2.16.840.1.113669.632.20.1211.10000357775', a[0]['RequestedTags']['StudyInstanceUID']) + self.assertEqual('1.3.46.670589.11.0.0.11.4.2.0.8743.5.5396.2006120114285654497', a[0]['RequestedTags']['SeriesInstanceUID']) + + + # Instance level, request patient, study and series tags too, include tags that are not part of the main dicom tags + a = DoPost(_REMOTE, '/tools/find', { 'Level' : 'Series', + 'CaseSensitive' : False, + 'Query' : { 'PatientName' : 'BRAINIX' }, + 'RequestedTags' : [ 'PatientName', 'StudyInstanceUID', 'SeriesInstanceUID', 'SOPInstanceUID', 'PhotometricInterpretation'], + 'Expand': True + }) + self.assertEqual(1, len(a)) + self.assertIn('PatientName', a[0]['RequestedTags']) + self.assertIn('StudyInstanceUID', a[0]['RequestedTags']) + self.assertIn('SeriesInstanceUID', a[0]['RequestedTags']) + self.assertIn('PhotometricInterpretation', a[0]['RequestedTags']) + + self.assertEqual('BRAINIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('2.16.840.1.113669.632.20.1211.10000357775', a[0]['RequestedTags']['StudyInstanceUID']) + self.assertEqual('1.3.46.670589.11.0.0.11.4.2.0.8743.5.5396.2006120114285654497', a[0]['RequestedTags']['SeriesInstanceUID']) + self.assertEqual('MONOCHROME2', a[0]['RequestedTags']['PhotometricInterpretation']) + + + def test_rest_find_requested_tags_computed_tags(self): + # Upload instances + for i in range(2): + UploadInstance(_REMOTE, 'Brainix/Flair/IM-0001-000%d.dcm' % (i + 1)) + + + # Patient level + a = DoPost(_REMOTE, '/tools/find', { 'Level' : 'Patient', + 'CaseSensitive' : False, + 'Query' : { 'PatientName' : 'BRAINIX' }, + 'RequestedTags' : [ 'PatientName', 'NumberOfPatientRelatedStudies', 'NumberOfPatientRelatedSeries', 'NumberOfPatientRelatedInstances'], + 'Expand': True + }) + self.assertEqual(1, len(a)) + + self.assertEqual('BRAINIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('1', a[0]['RequestedTags']['NumberOfPatientRelatedStudies']) + self.assertEqual('1', a[0]['RequestedTags']['NumberOfPatientRelatedSeries']) + self.assertEqual('2', a[0]['RequestedTags']['NumberOfPatientRelatedInstances']) + + # Study level + a = DoPost(_REMOTE, '/tools/find', { 'Level' : 'Study', + 'CaseSensitive' : False, + 'Query' : { 'PatientName' : 'BRAINIX' }, + 'RequestedTags' : [ 'PatientName', 'StudyInstanceUID', 'ModalitiesInStudy', 'SOPClassesInStudy', 'NumberOfStudyRelatedInstances', 'NumberOfStudyRelatedSeries'], + 'Expand': True + }) + self.assertEqual(1, len(a)) + + self.assertEqual('BRAINIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('2.16.840.1.113669.632.20.1211.10000357775', a[0]['RequestedTags']['StudyInstanceUID']) + self.assertEqual('MR', a[0]['RequestedTags']['ModalitiesInStudy']) + self.assertEqual('1.2.840.10008.5.1.4.1.1.4', a[0]['RequestedTags']['SOPClassesInStudy']) + self.assertEqual('2', a[0]['RequestedTags']['NumberOfStudyRelatedInstances']) + self.assertEqual('1', a[0]['RequestedTags']['NumberOfStudyRelatedSeries']) + + # Series level + a = DoPost(_REMOTE, '/tools/find', { 'Level' : 'Series', + 'CaseSensitive' : False, + 'Query' : { 'PatientName' : 'BRAINIX' }, + 'RequestedTags' : [ 'PatientName', 'StudyInstanceUID', 'NumberOfSeriesRelatedInstances'], + 'Expand': True + }) + self.assertEqual(1, len(a)) + + self.assertEqual('BRAINIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('2.16.840.1.113669.632.20.1211.10000357775', a[0]['RequestedTags']['StudyInstanceUID']) + self.assertEqual('2', a[0]['RequestedTags']['NumberOfSeriesRelatedInstances']) + + # Instance level + a = DoPost(_REMOTE, '/tools/find', { 'Level' : 'Instance', + 'CaseSensitive' : False, + 'Query' : { 'PatientName' : 'BRAINIX' }, + 'RequestedTags' : [ 'PatientName', 'StudyInstanceUID', 'SOPInstanceUID', 'InstanceAvailability'], + 'Expand': True + }) + self.assertEqual(2, len(a)) + + self.assertEqual('BRAINIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('2.16.840.1.113669.632.20.1211.10000357775', a[0]['RequestedTags']['StudyInstanceUID']) + self.assertEqual('ONLINE', a[0]['RequestedTags']['InstanceAvailability']) + + def test_list_resources_requested_tags(self): + + instance = UploadInstance(_REMOTE, 'DummyCT.dcm') ['ID'] + patient = DoGet(_REMOTE, '/instances/%s/patient' % instance) ['ID'] + study = DoGet(_REMOTE, '/instances/%s/study' % instance) ['ID'] + + # list series and request tags that are not in the default main dicom tags + a = DoGet(_REMOTE, '/studies/%s/series?expand&simplify&requestedTags=PatientName;Modality;SeriesInstanceUID;MRAcquisitionType' % study) + + self.assertEqual('2D', a[0]['RequestedTags']['MRAcquisitionType']) + self.assertEqual('MR', a[0]['RequestedTags']['Modality']) + self.assertEqual('KNIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('1.2.840.113619.2.176.2025.1499492.7391.1171285944.394', a[0]['RequestedTags']['SeriesInstanceUID']) + + # list studies and request patient and studies tags + a = DoGet(_REMOTE, '/patients/%s/studies?expand&simplify&requestedTags=PatientName;StudyInstanceUID' % patient) + + self.assertEqual('1.2.840.113619.2.176.2025.1499492.7391.1171285944.390', a[0]['RequestedTags']['StudyInstanceUID']) + self.assertEqual('KNIX', a[0]['RequestedTags']['PatientName']) + + + # list instances and request patient, studies and series tags including tags that are not in main dicom tags + a = DoGet(_REMOTE, '/patients/%s/instances?expand&simplify&requestedTags=PatientName;StudyInstanceUID;SeriesInstanceUID;SOPInstanceUID;Rows;Columns;InstanceAvailability' % patient) + + self.assertEqual('1.2.840.113619.2.176.2025.1499492.7391.1171285944.390', a[0]['RequestedTags']['StudyInstanceUID']) + self.assertEqual('1.2.840.113619.2.176.2025.1499492.7391.1171285944.394', a[0]['RequestedTags']['SeriesInstanceUID']) + self.assertEqual('1.2.840.113619.2.176.2025.1499492.7040.1171286242.109', a[0]['RequestedTags']['SOPInstanceUID']) + self.assertEqual('KNIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('512', a[0]['RequestedTags']['Rows']) + self.assertEqual('512', a[0]['RequestedTags']['Columns']) + self.assertEqual('ONLINE', a[0]['RequestedTags']['InstanceAvailability']) + + + def test_list_resources_requested_tags_study_computed_tags(self): + + instance = UploadInstance(_REMOTE, 'DummyCT.dcm') ['ID'] + patient = DoGet(_REMOTE, '/instances/%s/patient' % instance) ['ID'] + study = DoGet(_REMOTE, '/instances/%s/study' % instance) ['ID'] + + # list studies and request patient and studies tags, including ModalitiesInStudy + a = DoGet(_REMOTE, '/patients/%s/studies?expand&simplify&requestedTags=PatientName;StudyInstanceUID;ModalitiesInStudy;SOPClassesInStudy;NumberOfStudyRelatedInstances;NumberOfStudyRelatedSeries' % patient) + + self.assertEqual('1.2.840.113619.2.176.2025.1499492.7391.1171285944.390', a[0]['RequestedTags']['StudyInstanceUID']) + self.assertEqual('KNIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('MR', a[0]['RequestedTags']['ModalitiesInStudy']) + self.assertEqual('1.2.840.10008.5.1.4.1.1.4', a[0]['RequestedTags']['SOPClassesInStudy']) + self.assertEqual('1', a[0]['RequestedTags']['NumberOfStudyRelatedInstances']) + self.assertEqual('1', a[0]['RequestedTags']['NumberOfStudyRelatedSeries']) + + + def test_list_resources_requested_tags_series_computed_tags(self): + + instance = UploadInstance(_REMOTE, 'DummyCT.dcm') ['ID'] + patient = DoGet(_REMOTE, '/instances/%s/patient' % instance) ['ID'] + study = DoGet(_REMOTE, '/instances/%s/study' % instance) ['ID'] + + # list studies and request patient and studies tags, including ModalitiesInStudy + a = DoGet(_REMOTE, '/studies/%s/series?expand&simplify&requestedTags=PatientName;SeriesInstanceUID;NumberOfSeriesRelatedInstances' % study) + + self.assertEqual('1.2.840.113619.2.176.2025.1499492.7391.1171285944.394', a[0]['RequestedTags']['SeriesInstanceUID']) + self.assertEqual('KNIX', a[0]['RequestedTags']['PatientName']) + self.assertEqual('1', a[0]['RequestedTags']['NumberOfSeriesRelatedInstances']) + def test_dicomweb_jpeg2k_implicit(self): # This is a file encoded using 1.2.840.10008.1.2.4.90 transfer # syntax, in which most DICOM tags have the "UN" value