changeset 44:9afd691bfb74

added tags: RescaleIntercept, RescaleSlope, and NumberOfFrames
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 03 May 2024 13:02:51 +0200
parents f3dc8ecf4349
children 61771e7c44a8
files Resources/ClearMetadataCache.py Sources/Plugin.cpp
diffstat 2 files changed, 103 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/ClearMetadataCache.py	Fri May 03 13:02:51 2024 +0200
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+
+import argparse
+import requests
+
+parser = argparse.ArgumentParser(description = 'Clear the cache of the OHIF plugin (for "dicom-json" data source).')
+parser.add_argument('--url',
+                    default = 'http://localhost:8042',
+                    help = 'URL to the REST API of the Orthanc server')
+parser.add_argument('--username',
+                    default = 'orthanc',
+                    help = 'Username to the REST API')
+parser.add_argument('--password',
+                    default = 'orthanc',
+                    help = 'Password to the REST API')
+
+args = parser.parse_args()
+
+auth = requests.auth.HTTPBasicAuth(args.username, args.password)
+
+METADATA = '4202'
+
+for instance in requests.get('%s/instances' % args.url, auth=auth).json():
+    if METADATA in requests.get('%s/instances/%s/metadata' % (args.url, instance), auth=auth).json():
+        requests.delete('%s/instances/%s/metadata/%s' % (args.url, instance, METADATA), auth=auth)
--- a/Sources/Plugin.cpp	Fri May 03 10:00:37 2024 +0200
+++ b/Sources/Plugin.cpp	Fri May 03 13:02:51 2024 +0200
@@ -27,6 +27,7 @@
 #include <Compression/GzipCompressor.h>
 #include <DicomFormat/DicomInstanceHasher.h>
 #include <DicomFormat/DicomMap.h>
+#include <Logging.h>
 #include <MultiThreading/SharedMessageQueue.h>
 #include <SerializationToolbox.h>
 #include <SystemToolbox.h>
@@ -113,6 +114,12 @@
    * Those are the tags that are found in the documentation of the
    * "DICOM JSON" data source:
    * https://docs.ohif.org/configuration/dataSources/dicom-json
+   *
+   * Official list of tags:
+   * https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/faq.md#what-are-the-list-of-required-metadata-for-the-ohif-viewer-to-work
+   *
+   * Official example:
+   * https://ohif-dicom-json-example.s3.amazonaws.com/LIDC-IDRI-0001.json
    **/
   ohifStudyTags_[Orthanc::DICOM_TAG_STUDY_INSTANCE_UID] = TagInformation(DataType_String, "StudyInstanceUID");
   ohifStudyTags_[Orthanc::DICOM_TAG_STUDY_DATE]         = TagInformation(DataType_String, "StudyDate");
@@ -170,6 +177,14 @@
   ohifInstanceTags_[Orthanc::DicomTag(0x0054, 0x1300)]        = TagInformation(DataType_Float, "FrameReferenceTime");
   ohifInstanceTags_[RADIOPHARMACEUTICAL_INFORMATION_SEQUENCE] = TagInformation(DataType_None, "RadiopharmaceuticalInformationSequence");
 
+  /**
+   * Added in version 1.3
+   **/
+  ohifInstanceTags_[Orthanc::DICOM_TAG_RESCALE_INTERCEPT] = TagInformation(DataType_Float, "RescaleIntercept");
+  ohifInstanceTags_[Orthanc::DICOM_TAG_RESCALE_SLOPE]     = TagInformation(DataType_Float, "RescaleSlope");
+  ohifInstanceTags_[Orthanc::DICOM_TAG_NUMBER_OF_FRAMES]  = TagInformation(DataType_Integer, "NumberOfFrames");
+
+
   // UNTESTED
   ohifInstanceTags_[Orthanc::DicomTag(0x7053, 0x1000)] = TagInformation(DataType_Float, "70531000");  // Philips SUVScaleFactor
   ohifInstanceTags_[Orthanc::DicomTag(0x7053, 0x1009)] = TagInformation(DataType_Float, "70531009");  // Philips ActivityConcentrationScaleFactor
@@ -310,22 +325,42 @@
 
           case DataType_Integer:
           {
-            int32_t v;
-            if (Orthanc::SerializationToolbox::ParseInteger32(v, value.asString()))
+            std::vector<std::string> tokens;
+            Orthanc::Toolbox::TokenizeString(tokens, value.asString(), '\\');
+
+            if (!tokens.empty())
             {
-              target[name] = v;
+              int32_t v;
+              if (Orthanc::SerializationToolbox::ParseInteger32(v, tokens[0]))
+              {
+                target[name] = v;
+              }
+              return true;
             }
-            return true;
+            else
+            {
+              return false;
+            }
           }
 
           case DataType_Float:
           {
-            float v;
-            if (Orthanc::SerializationToolbox::ParseFloat(v, value.asString()))
+            std::vector<std::string> tokens;
+            Orthanc::Toolbox::TokenizeString(tokens, value.asString(), '\\');
+
+            if (!tokens.empty())
             {
-              target[name] = v;
+              float v;
+              if (Orthanc::SerializationToolbox::ParseFloat(v, tokens[0]))
+              {
+                target[name] = v;
+              }
+              return true;
             }
-            return true;
+            else
+            {
+              return false;
+            }
           }
 
           case DataType_ListOfStrings:
@@ -457,6 +492,10 @@
 static bool GetOhifInstance(Json::Value& target,
                             const std::string& instanceId)
 {
+#if 0
+  // This disables all the caching (for debugging)
+  return EncodeOhifInstance(target, instanceId);
+#else
   const std::string uri = GetCacheUri(instanceId);
   
   std::string metadata;
@@ -498,6 +537,7 @@
   {
     return false;
   }
+#endif
 }
 
 
@@ -660,6 +700,9 @@
 
       study["series"] = Json::arrayValue;
 
+      std::set<std::string> modalities;
+      unsigned int countInstances = 0;
+
       for (MapOfResources::const_iterator it3 = seriesInStudy.begin(); it3 != seriesInStudy.end(); ++it3)
       {
         if (!it3->second.empty())
@@ -667,6 +710,11 @@
           assert(it3->second.front() != NULL);
           const Json::Value& firstInstanceInSeries = *it3->second.front();
 
+          if (firstInstanceInSeries.isMember(Orthanc::DICOM_TAG_MODALITY.Format()))
+          {
+            modalities.insert(firstInstanceInSeries[Orthanc::DICOM_TAG_MODALITY.Format()].asString());
+          }
+
           Json::Value series = Json::objectValue;
           for (TagsDictionary::const_iterator tag = ohifSeriesTags_.begin(); tag != ohifSeriesTags_.end(); ++tag)
           {
@@ -702,12 +750,26 @@
             instance["url"] = "dicomweb:../instances/" + hasher.HashInstance() + "/file";
 
             series["instances"].append(instance);
+            countInstances++;
           }
 
           study["series"].append(series);
         }
       }
 
+      std::string jsonModalities;
+      for (std::set<std::string>::const_iterator it = modalities.begin(); it != modalities.end(); ++it)
+      {
+        if (!jsonModalities.empty())
+        {
+          jsonModalities += ",";
+        }
+        jsonModalities += *it;
+      }
+
+      study["NumInstances"] = countInstances;
+      study["Modalities"] = jsonModalities;
+
       target["studies"].append(study);
     }
   }  
@@ -856,6 +918,14 @@
   {
     OrthancPlugins::SetGlobalContext(context, ORTHANC_PLUGIN_NAME);
 
+#if ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 4)
+    Orthanc::Logging::InitializePluginContext(context, ORTHANC_PLUGIN_NAME);
+#elif ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 7, 2)
+    Orthanc::Logging::InitializePluginContext(context);
+#else
+    Orthanc::Logging::Initialize(context);
+#endif
+
     /* Check the version of the Orthanc core */
     if (OrthancPluginCheckVersion(context) == 0)
     {