# HG changeset patch # User Alain Mazy # Date 1656434301 -7200 # Node ID 6144ef431512bc1c7efd105b69c2f586674781eb # Parent 459eb688d3a1b9e44a67a0b0516c41e7eb158578 new tests for sequences in ExtraMainDicomTags diff -r 459eb688d3a1 -r 6144ef431512 NewTests/DelayedDeletion/test_delayed_deletion.py --- a/NewTests/DelayedDeletion/test_delayed_deletion.py Thu Jun 23 14:54:48 2022 +0200 +++ b/NewTests/DelayedDeletion/test_delayed_deletion.py Tue Jun 28 18:38:21 2022 +0200 @@ -46,14 +46,13 @@ config=config, plugins=Helpers.plugins ) + + print('-------------- waiting for orthanc-to-prepare-db to be available') + cls.o.wait_started() - populator = OrthancTestDbPopulator( - api_client=cls.o, - studies_count=2, - random_seed=42 - ) - populator.execute() - + print('-------------- populating') + cls.o.upload_folder(here / "../../Database/Knix/Loc") + print('-------------- populated') cls.files_count_after_preparation = len(glob.glob(os.path.join(cls.get_storage_path("DelayedDeletion"), "**"), recursive=True)) all_studies_ids = cls.o.studies.get_all_ids() diff -r 459eb688d3a1 -r 6144ef431512 NewTests/ExtraMainDicomTags/__init__.py diff -r 459eb688d3a1 -r 6144ef431512 NewTests/ExtraMainDicomTags/test_extra_main_dicom_tags.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NewTests/ExtraMainDicomTags/test_extra_main_dicom_tags.py Tue Jun 28 18:38:21 2022 +0200 @@ -0,0 +1,158 @@ +import unittest +import time +import os +from helpers import OrthancTestCase, Helpers + +from orthanc_api_client import OrthancApiClient, generate_test_dicom_file +from orthanc_tools import OrthancTestDbPopulator + +import pathlib +import glob +here = pathlib.Path(__file__).parent.resolve() + + +class TestExtraMainDicomTags(OrthancTestCase): + + @classmethod + def prepare(cls): + print('-------------- preparing TestExtraMainDicomTags tests') + + cls.clear_storage(storage_name="ExtraMainDicomTags") + + config = { + "ExtraMainDicomTags": { + "Instance" : [ + "Rows", + "PerformedProtocolCodeSequence" + ], + "Series" : [ + "RequestAttributesSequence" + ], + "Study": [], + "Patient": [] + }, + "OverwriteInstances": True, + "DicomWeb" : { + "StudiesMetadata" : "MainDicomTags", + "SeriesMetadata": "MainDicomTags" + } + } + + config_path = cls.generate_configuration( + config_name="extra_main_dicom_tags", + storage_name="ExtraMainDicomTags", + config=config, + plugins=Helpers.plugins + ) + + print('-------------- prepared ExtraMainDicomTags tests') + if Helpers.break_after_preparation: + print(f"++++ It is now time to start your Orthanc under tests with configuration file '{config_path}' +++++") + input("Press Enter to continue") + else: + print('-------------- launching ExtraMainDicomTags tests') + cls.launch_orthanc_under_tests( + config_path=config_path, + config_name="extra_main_dicom_tags", + storage_name="ExtraMainDicomTags", + plugins=Helpers.plugins + ) + + print('-------------- waiting for orthanc-under-tests to be available') + cls.o.wait_started() + + def test_main_dicom_tags(self): + + # upload a study + self.o.upload_file(here / "../../Database/Brainix/Flair/IM-0001-0001.dcm") + + instance = self.o.get(endpoint="instances/4dc71dc0-6093b5f8-ca67aa8a-07b18ff5-95dbe3c8").json() + + self.assertIn("Rows", instance["MainDicomTags"]) + self.assertIn("PerformedProtocolCodeSequence", instance["MainDicomTags"]) + + def test_main_dicom_tags_full(self): + + # upload a study + self.o.upload_file(here / "../../Database/Brainix/Flair/IM-0001-0001.dcm") + + instance = self.o.get(endpoint="instances/4dc71dc0-6093b5f8-ca67aa8a-07b18ff5-95dbe3c8?full").json() + + self.assertIn("0028,0010", instance["MainDicomTags"]) + self.assertIn("0040,0260", instance["MainDicomTags"]) + + + def test_main_reconstruct(self): + + # upload a study + self.o.upload_file(here / "../../Database/Brainix/Flair/IM-0001-0001.dcm") + + instance = self.o.get(endpoint="instances/4dc71dc0-6093b5f8-ca67aa8a-07b18ff5-95dbe3c8").json() + + self.assertIn("Rows", instance["MainDicomTags"]) + self.assertIn("PerformedProtocolCodeSequence", instance["MainDicomTags"]) + + # reconstruct instance + self.o.post(endpoint="/instances/4dc71dc0-6093b5f8-ca67aa8a-07b18ff5-95dbe3c8/reconstruct", json={}) + instance = self.o.get(endpoint="instances/4dc71dc0-6093b5f8-ca67aa8a-07b18ff5-95dbe3c8").json() + self.assertIn("Rows", instance["MainDicomTags"]) + self.assertIn("PerformedProtocolCodeSequence", instance["MainDicomTags"]) + + + def test_tools_find(self): + + # upload a study + self.o.upload_file(here / "../../Database/Brainix/Flair/IM-0001-0001.dcm") + + # instance level + r = self.o.post( + endpoint="/tools/find", + json={ + "Level": "Instances", + "Query": { + "PatientID": "5Yp0E" + }, + "Expand": True, + "RequestedTags" : ["Rows", "PerformedProtocolCodeSequence", "ReferencedStudySequence"] # "ReferencedStudySequence" is not stored in MainDicomTags ! + } + ) + + instances = r.json() + self.assertEqual(1, len(instances)) + self.assertIn("Rows", instances[0]["RequestedTags"]) + self.assertIn("PerformedProtocolCodeSequence", instances[0]["RequestedTags"]) + self.assertIn("ReferencedStudySequence", instances[0]["RequestedTags"]) + + + # series level, request a sequence + r = self.o.post( + endpoint="/tools/find", + json={ + "Level": "Series", + "Query": { + "PatientID": "5Yp0E" + }, + "Expand": True, + "RequestedTags" : ["RequestAttributesSequence"] + } + ) + + series = r.json() + self.assertEqual(1, len(series)) + self.assertIn("RequestAttributesSequence", series[0]["RequestedTags"]) + + + + def test_dicom_web_metadata(self): + + # upload a study + self.o.upload_file(here / "../../Database/Brainix/Flair/IM-0001-0001.dcm") + + metadata = self.o.get( + endpoint="/dicom-web/studies/2.16.840.1.113669.632.20.1211.10000357775/metadata" + ).json() + + self.assertEqual(1, len(metadata)) + self.assertIn("00280010", metadata[0]) # Rows + self.assertNotIn("00280011", metadata[0]) # Columns should not be stored ! + self.assertIn("00400260", metadata[0]) # PerformedProtocolCodeSequence \ No newline at end of file diff -r 459eb688d3a1 -r 6144ef431512 NewTests/Housekeeper/test_housekeeper.py --- a/NewTests/Housekeeper/test_housekeeper.py Thu Jun 23 14:54:48 2022 +0200 +++ b/NewTests/Housekeeper/test_housekeeper.py Tue Jun 28 18:38:21 2022 +0200 @@ -45,7 +45,7 @@ "Patient" : ["PatientWeight", "PatientAge"], "Study": ["NameOfPhysiciansReadingStudy"], "Series": ["ScanOptions"], - "Instance": ["Rows", "Columns"] + "Instance": ["Rows", "Columns", "DerivationCodeSequence"] }, "Housekeeper": { "Enable": True @@ -111,12 +111,14 @@ # extra tags were not in DB before reconstruction self.assertNotIn("Rows", self.instance_before["MainDicomTags"]) + self.assertNotIn("DerivationCodeSequence", self.instance_before["MainDicomTags"]) self.assertNotIn("ScanOptions", self.series_before["MainDicomTags"]) self.assertNotIn("NameOfPhysiciansReadingStudy", self.study_before["MainDicomTags"]) self.assertNotIn("PatientWeight", self.patient_before["MainDicomTags"]) # extra tags are in DB after reconstruction self.assertIn("Rows", instance_after["MainDicomTags"]) + self.assertIn("DerivationCodeSequence", instance_after["MainDicomTags"]) self.assertIn("ScanOptions", series_after["MainDicomTags"]) self.assertIn("NameOfPhysiciansReadingStudy", study_after["MainDicomTags"]) self.assertIn("PatientWeight", patient_after["MainDicomTags"]) diff -r 459eb688d3a1 -r 6144ef431512 NewTests/README --- a/NewTests/README Thu Jun 23 14:54:48 2022 +0200 +++ b/NewTests/README Tue Jun 28 18:38:21 2022 +0200 @@ -67,5 +67,22 @@ TODO: implement and document usage with Docker !!!! +ExtraMainDicomTags: +------------------ + +Runs an Orthanc in Index Only mode while storing extra main dicom tags and perform various find (including DicomWeb). + +Run the ExtraMainDicomTags tests with your locally build version. + +python3 NewTests/main.py --pattern=ExtraMainDicomTags.* \ + --orthanc_under_tests_exe=/home/alain/o/build/orthanc/Orthanc \ + --orthanc_under_tests_http_port=8043 \ + --plugin=/home/alain/o/build/orthanc-dicomweb/libOrthancDicomWeb.so \ + --break_after_preparation + +The test script will: +- generate 1 configuration file in the `configurations` folder, +- interrupt and instruct you how to start your own version, pointing to the configuration file to use +- execute tests diff -r 459eb688d3a1 -r 6144ef431512 Tests/Tests.py --- a/Tests/Tests.py Thu Jun 23 14:54:48 2022 +0200 +++ b/Tests/Tests.py Tue Jun 28 18:38:21 2022 +0200 @@ -8603,7 +8603,7 @@ def test_rest_find_requested_tags(self): - if IsOrthancVersionAbove(_REMOTE, 1, 11, 0): + if IsOrthancVersionAbove(_REMOTE, 1, 11, 1): # RequestedTags introduced in 1.11.0 but Sequences allowed since 1.11.1 # Upload instances for i in range(2): @@ -8613,7 +8613,7 @@ a = DoPost(_REMOTE, '/tools/find', { 'Level' : 'Patient', 'CaseSensitive' : False, 'Query' : { 'PatientName' : 'BRAINIX' }, - 'RequestedTags' : [ 'PatientName', 'PatientID', 'PatientSex', 'PatientBirthDate' ], + 'RequestedTags' : [ 'PatientName', 'PatientID', 'PatientSex', 'PatientBirthDate'], 'Expand': True }) self.assertEqual(1, len(a)) @@ -8646,24 +8646,26 @@ a = DoPost(_REMOTE, '/tools/find', { 'Level' : 'Series', 'CaseSensitive' : False, 'Query' : { 'PatientName' : 'BRAINIX' }, - 'RequestedTags' : [ 'PatientName', 'StudyInstanceUID', 'SeriesInstanceUID'], + 'RequestedTags' : [ 'PatientName', 'StudyInstanceUID', 'SeriesInstanceUID', 'RequestAttributesSequence'], '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('RequestAttributesSequence', 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('A10029316690', a[0]['RequestedTags']['RequestAttributesSequence'][0]['RequestedProcedureID']) # 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'], + 'RequestedTags' : [ 'PatientName', 'StudyInstanceUID', 'SeriesInstanceUID', 'SOPInstanceUID', 'PhotometricInterpretation', 'RequestAttributesSequence'], 'Expand': True }) self.assertEqual(1, len(a)) @@ -8671,11 +8673,13 @@ self.assertIn('StudyInstanceUID', a[0]['RequestedTags']) self.assertIn('SeriesInstanceUID', a[0]['RequestedTags']) self.assertIn('PhotometricInterpretation', a[0]['RequestedTags']) + self.assertIn('RequestAttributesSequence', 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']) + self.assertEqual('A10029316690', a[0]['RequestedTags']['RequestAttributesSequence'][0]['RequestedProcedureID']) def test_rest_find_requested_tags_computed_tags(self):