changeset 45:0725da868940

fix compatibility with current TCIA services
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 28 Jan 2026 13:37:54 +0100
parents bdab3cde19cf
children 958152db4858 19d127fd0a7c
files CMakeLists.txt NEWS Plugin/Plugin.cpp Plugin/TciaImportJob.cpp Plugin/TciaImportJob.h WebApplication/index.html
diffstat 6 files changed, 84 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Fri Jan 02 15:18:28 2026 +0100
+++ b/CMakeLists.txt	Wed Jan 28 13:37:54 2026 +0100
@@ -117,7 +117,7 @@
   -DHAS_ORTHANC_EXCEPTION=1
   -DORTHANC_PLUGIN_NAME="tcia"
   -DORTHANC_PLUGIN_VERSION="${ORTHANC_PLUGIN_VERSION}"
-  -DTCIA_BASE_URL="https://services.cancerimagingarchive.net/services/v4/TCIA/query"
+  -DTCIA_BASE_URL="https://nbia.cancerimagingarchive.net/nbia-api/services/v4"
   )
 
 EmbedResources(
--- a/NEWS	Fri Jan 02 15:18:28 2026 +0100
+++ b/NEWS	Wed Jan 28 13:37:54 2026 +0100
@@ -1,6 +1,12 @@
 Pending changes in the mainline
 ===============================
 
+* Replaced default base URL of TCIA REST API from
+  "https://services.cancerimagingarchive.net/services/v4/TCIA/query" to
+  "https://nbia.cancerimagingarchive.net/nbia-api/services/v4"
+* Added configuration option "BaseUrl" to manually configure the base URL
+* Fix for newer versions of the NBIA cart file format
+
 
 Version 1.2 (2024-03-26)
 ========================
--- a/Plugin/Plugin.cpp	Fri Jan 02 15:18:28 2026 +0100
+++ b/Plugin/Plugin.cpp	Wed Jan 28 13:37:54 2026 +0100
@@ -73,10 +73,7 @@
   }
   else
   {
-    assert(TCIA_BASE_URL[strlen(TCIA_BASE_URL) - 1] != '/' &&
-           TCIA_BASE_URL[strlen(TCIA_BASE_URL)] == 0);
-    
-    std::string tcia = std::string(TCIA_BASE_URL) + "/" + std::string(request->groups[0]);
+    std::string tcia = OrthancPlugins::TciaImportJob::GetTciaUrl(request->groups[0]);
 
     for (uint32_t i = 0; i < request->getCount; i++)
     {
@@ -105,12 +102,14 @@
     {
       OrthancPlugins::MemoryBuffer body, headersBuffer;
       uint16_t status;
-    
+
       if (OrthancPluginErrorCode_Success == OrthancPluginHttpClient(
             OrthancPlugins::GetGlobalContext(), *body, *headersBuffer, &status,
             OrthancPluginHttpMethod_Get, tcia.c_str(),
-            0, NULL, NULL, NULL, 0, "" /* username */, "" /* password */,
-            0 /* default timeout */, NULL, NULL, NULL, 0))
+            0 /* HTTP headers in request */, NULL, NULL,
+            NULL /* body */, 0,
+            NULL /* username */, NULL /* password */,
+            0 /* use default timeout */, NULL, NULL, NULL, 0))
       {
         Json::Value headers;
         headersBuffer.ToJson(headers);
@@ -303,6 +302,8 @@
 
     OrthancPlugins::SetDescription(ORTHANC_PLUGIN_NAME, "Interface with TCIA (The Cancer Imaging Archive).");
 
+    OrthancPlugins::TciaImportJob::SetTciaBaseUrl(TCIA_BASE_URL);
+
     try
     {
       static const char* const KEY_TCIA = "Tcia";
@@ -324,6 +325,14 @@
                      << "to \"true\" in the \"" << KEY_TCIA << "\" section of the configuration file of Orthanc";
         return 0;
       }
+
+      {
+        std::string s;
+        if (tcia.LookupStringValue(s, "BaseUrl"))
+        {
+          OrthancPlugins::TciaImportJob::SetTciaBaseUrl(s);
+        }
+      }
       
       OrthancPlugins::SetRootUri(ORTHANC_PLUGIN_NAME, "/tcia/app/index.html");
 
--- a/Plugin/TciaImportJob.cpp	Fri Jan 02 15:18:28 2026 +0100
+++ b/Plugin/TciaImportJob.cpp	Wed Jan 28 13:37:54 2026 +0100
@@ -36,6 +36,9 @@
 static const char* const SIZE = "Size";
 
 
+static std::string tciaBaseUrl_;
+
+
 namespace OrthancPlugins
 {
   TciaImportJob::Series::Series(const std::string& collection,
@@ -170,11 +173,23 @@
   
   void TciaImportJob::AddNbiaClientSpreadsheet(const std::string& csv)
   {
+#if 1
+    // Values that are used since orthanc-tcia 1.3
+    static const char* const COLLECTION_NAME = "Collection";
+    static const char* const SUBJECT_ID = "PatientID";
+    static const char* const SERIES_ID = "SeriesInstanceUID";
+    static const char* const NUMBER_OF_IMAGES = "ImageCount";
+    static const char* const FILE_SIZE = "FileSize";
+#endif
+
+#if 0
+    // Values that were used in orthanc-tcia <= 1.2
     static const char* const COLLECTION_NAME = "Collection Name";
     static const char* const SUBJECT_ID = "Subject ID";
     static const char* const SERIES_ID = "Series ID";
     static const char* const NUMBER_OF_IMAGES = "Number of images";
     static const char* const FILE_SIZE = "File Size (Bytes)";
+#endif
       
     OrthancPlugins::CsvParser parser;
     parser.Parse(csv);
@@ -342,4 +357,42 @@
       return job.release();
     }
   }
+
+
+  std::string TciaImportJob::GetTciaUrl(const std::string& path)
+  {
+    if (tciaBaseUrl_.empty())
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+    else if (tciaBaseUrl_[tciaBaseUrl_.size() - 1] == '/')
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+    }
+    else
+    {
+      return tciaBaseUrl_ + "/" + path;
+    }
+  }
+
+
+  void TciaImportJob::SetTciaBaseUrl(const std::string& url)
+  {
+    std::string s = url;
+
+    while (!s.empty() &&
+           s[s.size() - 1] == '/')
+    {
+      s.resize(s.size() - 1);
+    }
+
+    if (s.empty())
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+    }
+    else
+    {
+      tciaBaseUrl_ = s;
+    }
+  }
 }
--- a/Plugin/TciaImportJob.h	Fri Jan 02 15:18:28 2026 +0100
+++ b/Plugin/TciaImportJob.h	Wed Jan 28 13:37:54 2026 +0100
@@ -117,5 +117,9 @@
     static std::string GetJobType();
     
     static TciaImportJob* Unserialize(const Json::Value& serialized);
+
+    static std::string GetTciaUrl(const std::string& path);
+
+    static void SetTciaBaseUrl(const std::string& url);
   };
 }
--- a/WebApplication/index.html	Fri Jan 02 15:18:28 2026 +0100
+++ b/WebApplication/index.html	Wed Jan 28 13:37:54 2026 +0100
@@ -118,7 +118,7 @@
           Note that loading the information about the TCIA collections
           takes time because of the throttling that is applied to the
           <a
-          href="https://wiki.cancerimagingarchive.net/display/Public/TCIA+REST+API+Guide"
+          href="https://wiki.cancerimagingarchive.net/display/Public/TCIA+Programmatic+Interface+REST+API+Guides"
           target="_blank">REST API of TCIA</a>. Orthanc caches this
           information in memory to speed up further access to the same
           resources. This cache can be cleared using the button at the
@@ -182,13 +182,13 @@
               </thead>
               <tbody>
                 <tr v-for="patient in patients"
-                    v-if="globStringToRegex(filter).test(patient.PatientID + ' ' + patient.PatientName + ' ' + patient.PatientSex)">
-                  <td>{{ patient.PatientID }}</td>
+                    v-if="globStringToRegex(filter).test(patient.PatientId + ' ' + patient.PatientName + ' ' + patient.PatientSex)">
+                  <td>{{ patient.PatientId }}</td>
                   <td>{{ patient.PatientName }}</td>
                   <td>{{ patient.PatientSex }}</td>
                   <td style="text-align: center;">
                     <button type="button" class="btn btn-outline-primary btn-sm"
-                            v-on:click="openPatient(patient.PatientID)">&triangleright;</button>
+                            v-on:click="openPatient(patient.PatientId)">&triangleright;</button>
                   </td>
                 </tr>
               </tbody>