changeset 486:6144ef431512

new tests for sequences in ExtraMainDicomTags
author Alain Mazy <am@osimis.io>
date Tue, 28 Jun 2022 18:38:21 +0200
parents 459eb688d3a1
children 18f2d55182fd
files NewTests/DelayedDeletion/test_delayed_deletion.py NewTests/ExtraMainDicomTags/__init__.py NewTests/ExtraMainDicomTags/test_extra_main_dicom_tags.py NewTests/Housekeeper/test_housekeeper.py NewTests/README Tests/Tests.py
diffstat 5 files changed, 192 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- 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()
--- /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
--- 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"])
--- 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
 
 
--- 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):