changeset 5793:a8055aebc6cb find-refactoring

added standard MainDicomTags that are used in QIDO-RS
author Alain Mazy <am@orthanc.team>
date Wed, 18 Sep 2024 12:30:49 +0200
parents 89a13d8ec80b
children 44eef6975662
files NEWS OrthancFramework/Sources/DicomFormat/DicomMap.cpp OrthancFramework/Sources/DicomFormat/DicomTag.h OrthancFramework/UnitTestsSources/DicomMapTests.cpp OrthancServer/Sources/OrthancInitialization.cpp OrthancServer/Sources/ResourceFinder.cpp
diffstat 6 files changed, 60 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Wed Sep 18 10:38:42 2024 +0200
+++ b/NEWS	Wed Sep 18 12:30:49 2024 +0200
@@ -60,6 +60,16 @@
   - W003_DecoderFailure
   - W004_NoMainDicomTagsSignature
   - W005_RequestingTagFromLowerResourceLevel
+* New default MainDicomTags are now stored in DB.  Note that, in order to store these values
+  for resources that were ingested in Orthanc before this release, you would have to run
+  the Housekeeper plugin or call /reconstruct on every resources
+  - At Study Level:
+    - TimezoneOffsetFromUTC (used in QIDO-RS default queries)
+  - At Series Level:
+    - TimezoneOffsetFromUTC (used in QIDO-RS default queries)
+    - PerformedProcedureStepStartDate (used in QIDO-RS default queries)
+    - PerformedProcedureStepStartTime (used in QIDO-RS default queries)
+    - RequestAttributesSequence (used in QIDO-RS default queries)
 
 
 
--- a/OrthancFramework/Sources/DicomFormat/DicomMap.cpp	Wed Sep 18 10:38:42 2024 +0200
+++ b/OrthancFramework/Sources/DicomFormat/DicomMap.cpp	Wed Sep 18 12:30:49 2024 +0200
@@ -55,9 +55,9 @@
   // These lists have a specific signature.  When a resource does not have
   // the metadata "MainDicomTagsSignature", we'll assume that they were stored
   // with an Orthanc prior to 1.11.  It is therefore very important that you never
-  // change these lists !
+  // change these lists !  Update ResetDefaultMainDicomTags instead.
 
-  static const DicomTag DEFAULT_PATIENT_MAIN_DICOM_TAGS[] =
+  static const DicomTag DEFAULT_1_11_PATIENT_MAIN_DICOM_TAGS[] =
   {
     // { DicomTag(0x0010, 0x1010), "PatientAge" },
     // { DicomTag(0x0010, 0x1040), "PatientAddress" },
@@ -66,9 +66,11 @@
     DICOM_TAG_PATIENT_SEX,
     DICOM_TAG_OTHER_PATIENT_IDS,
     DICOM_TAG_PATIENT_ID
+
+    // don't add tags here, check ResetDefaultMainDicomTags instead
   };
   
-  static const DicomTag DEFAULT_STUDY_MAIN_DICOM_TAGS[] =
+  static const DicomTag DEFAULT_1_11_STUDY_MAIN_DICOM_TAGS[] =
   {
     // { DicomTag(0x0010, 0x1020), "PatientSize" },
     // { DicomTag(0x0010, 0x1030), "PatientWeight" },
@@ -84,9 +86,11 @@
     DICOM_TAG_INSTITUTION_NAME,
     DICOM_TAG_REQUESTING_PHYSICIAN,
     DICOM_TAG_REFERRING_PHYSICIAN_NAME
+
+    // don't add tags here, check ResetDefaultMainDicomTags instead
   };
 
-  static const DicomTag DEFAULT_SERIES_MAIN_DICOM_TAGS[] =
+  static const DicomTag DEFAULT_1_11_SERIES_MAIN_DICOM_TAGS[] =
   {
     // { DicomTag(0x0010, 0x1080), "MilitaryRank" },
     DICOM_TAG_SERIES_DATE,
@@ -113,9 +117,11 @@
     DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION,
     DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION,
     DICOM_TAG_CONTRAST_BOLUS_AGENT
+
+    // don't add tags here, check ResetDefaultMainDicomTags instead
   };
 
-  static const DicomTag DEFAULT_INSTANCE_MAIN_DICOM_TAGS[] =
+  static const DicomTag DEFAULT_1_11_INSTANCE_MAIN_DICOM_TAGS[] =
   {
     DICOM_TAG_INSTANCE_CREATION_DATE,
     DICOM_TAG_INSTANCE_CREATION_TIME,
@@ -138,6 +144,8 @@
      * indexed in the database by an older version of Orthanc.
      **/
     DICOM_TAG_IMAGE_ORIENTATION_PATIENT  // New in Orthanc 1.4.2
+
+    // don't add tags here, check ResetDefaultMainDicomTags instead
   };
 
   class DicomMap::MainDicomTagsConfiguration : public boost::noncopyable
@@ -187,23 +195,23 @@
       switch (level)
       {
         case ResourceType_Patient:
-          tags = DEFAULT_PATIENT_MAIN_DICOM_TAGS;
-          size = sizeof(DEFAULT_PATIENT_MAIN_DICOM_TAGS) / sizeof(DicomTag);
+          tags = DEFAULT_1_11_PATIENT_MAIN_DICOM_TAGS;
+          size = sizeof(DEFAULT_1_11_PATIENT_MAIN_DICOM_TAGS) / sizeof(DicomTag);
           break;
 
         case ResourceType_Study:
-          tags = DEFAULT_STUDY_MAIN_DICOM_TAGS;
-          size = sizeof(DEFAULT_STUDY_MAIN_DICOM_TAGS) / sizeof(DicomTag);
+          tags = DEFAULT_1_11_STUDY_MAIN_DICOM_TAGS;
+          size = sizeof(DEFAULT_1_11_STUDY_MAIN_DICOM_TAGS) / sizeof(DicomTag);
           break;
 
         case ResourceType_Series:
-          tags = DEFAULT_SERIES_MAIN_DICOM_TAGS;
-          size = sizeof(DEFAULT_SERIES_MAIN_DICOM_TAGS) / sizeof(DicomTag);
+          tags = DEFAULT_1_11_SERIES_MAIN_DICOM_TAGS;
+          size = sizeof(DEFAULT_1_11_SERIES_MAIN_DICOM_TAGS) / sizeof(DicomTag);
           break;
 
         case ResourceType_Instance:
-          tags = DEFAULT_INSTANCE_MAIN_DICOM_TAGS;
-          size = sizeof(DEFAULT_INSTANCE_MAIN_DICOM_TAGS) / sizeof(DicomTag);
+          tags = DEFAULT_1_11_INSTANCE_MAIN_DICOM_TAGS;
+          size = sizeof(DEFAULT_1_11_INSTANCE_MAIN_DICOM_TAGS) / sizeof(DicomTag);
           break;
 
         default:
@@ -247,7 +255,7 @@
       
       if (existingLevelTags.find(tag) != existingLevelTags.end())
       {
-        throw OrthancException(ErrorCode_MainDicomTagsMultiplyDefined, tag.Format() + " is already defined");
+        throw OrthancException(ErrorCode_MainDicomTagsMultiplyDefined, tag.Format() + " is already defined", false);
       }
 
       existingLevelTags.insert(tag);
@@ -287,6 +295,17 @@
       defaultSignatures_[ResourceType_Study] = signatures_[ResourceType_Study];
       defaultSignatures_[ResourceType_Series] = signatures_[ResourceType_Series];
       defaultSignatures_[ResourceType_Instance] = signatures_[ResourceType_Instance];
+
+      // only add new tags here !
+      // introduced in v 1.12.5
+      AddMainDicomTagInternal(DICOM_TAG_TIMEZONE_OFFSET_FROM_UTC, ResourceType_Study);  // used in default QIDO-RS queries
+      
+      AddMainDicomTagInternal(DICOM_TAG_TIMEZONE_OFFSET_FROM_UTC, ResourceType_Series);  // used in default QIDO-RS queries
+      AddMainDicomTagInternal(DICOM_TAG_PERFORMED_PROCEDURE_STEP_START_DATE, ResourceType_Series);  // used in default QIDO-RS queries
+      AddMainDicomTagInternal(DICOM_TAG_PERFORMED_PROCEDURE_STEP_START_TIME, ResourceType_Series);  // used in default QIDO-RS queries
+      AddMainDicomTagInternal(DICOM_TAG_REQUEST_ATTRIBUTES_SEQUENCE, ResourceType_Series);  // used in default QIDO-RS queries
+
+      // TODO-FIND: remove it from metadata when adding it ! AddMainDicomTagInternal(DICOM_TAG_SOP_CLASS_UID, ResourceType_Instance);  // previously saved in a metadata; makes more sense to store it in a DICOM tag
     }
 
     void AddMainDicomTag(const DicomTag& tag,
--- a/OrthancFramework/Sources/DicomFormat/DicomTag.h	Wed Sep 18 10:38:42 2024 +0200
+++ b/OrthancFramework/Sources/DicomFormat/DicomTag.h	Wed Sep 18 12:30:49 2024 +0200
@@ -157,7 +157,10 @@
   static const DicomTag DICOM_TAG_REQUESTING_PHYSICIAN(0x0032, 0x1032);
   static const DicomTag DICOM_TAG_REFERRING_PHYSICIAN_NAME(0x0008, 0x0090);
   static const DicomTag DICOM_TAG_OPERATOR_NAME(0x0008, 0x1070);
+  static const DicomTag DICOM_TAG_PERFORMED_PROCEDURE_STEP_START_DATE(0x0040, 0x0244);
+  static const DicomTag DICOM_TAG_PERFORMED_PROCEDURE_STEP_START_TIME(0x0040, 0x0245);
   static const DicomTag DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION(0x0040, 0x0254);
+  static const DicomTag DICOM_TAG_REQUEST_ATTRIBUTES_SEQUENCE(0x0040, 0x0275);
   static const DicomTag DICOM_TAG_IMAGE_COMMENTS(0x0020, 0x4000);
   static const DicomTag DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION(0x0018, 0x1400);
   static const DicomTag DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_CODE(0x0018, 0x1401);
--- a/OrthancFramework/UnitTestsSources/DicomMapTests.cpp	Wed Sep 18 10:38:42 2024 +0200
+++ b/OrthancFramework/UnitTestsSources/DicomMapTests.cpp	Wed Sep 18 12:30:49 2024 +0200
@@ -1085,7 +1085,7 @@
     std::set<DicomTag> tags;
     m.GetTags(tags);
 
-    // This corresponds to the values of DEFAULT_PATIENT_MAIN_DICOM_TAGS
+    // This corresponds to the values of DEFAULT_1_11_PATIENT_MAIN_DICOM_TAGS
     ASSERT_EQ(5u, tags.size());
     ASSERT_EQ("", m.GetStringValue(DICOM_TAG_PATIENT_ID, "nope", false));
 
--- a/OrthancServer/Sources/OrthancInitialization.cpp	Wed Sep 18 10:38:42 2024 +0200
+++ b/OrthancServer/Sources/OrthancInitialization.cpp	Wed Sep 18 12:30:49 2024 +0200
@@ -261,7 +261,17 @@
             {
               LOG(INFO) << "  - " << tagName;
             }
-            DicomMap::AddMainDicomTag(tag, level);
+
+            try
+            {
+              DicomMap::AddMainDicomTag(tag, level);
+            }
+            catch(OrthancException& e)
+            {
+              LOG(WARNING) << "  - !!! " << tagName << " is already defined as a standard MainDicomTags, it is useless to include it in the ExtraMainDicomTags";
+            }
+            
+            
           }
         }
       }
--- a/OrthancServer/Sources/ResourceFinder.cpp	Wed Sep 18 10:38:42 2024 +0200
+++ b/OrthancServer/Sources/ResourceFinder.cpp	Wed Sep 18 12:30:49 2024 +0200
@@ -1008,7 +1008,8 @@
         InjectRequestedTags(outRequestedTags, remainingRequestedTags, resource, ResourceType_Series);
         InjectRequestedTags(outRequestedTags, remainingRequestedTags, resource, ResourceType_Instance);
 
-        if (!remainingRequestedTags.empty())
+        if (!remainingRequestedTags.empty() && 
+            !DicomMap::HasOnlyComputedTags(remainingRequestedTags)) // if the only remaining tags are computed tags, it is worthless to read them from disk
         {
           if (!allowStorageAccess_)
           {