Mercurial > hg > orthanc-tcia
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)">▹</button> + v-on:click="openPatient(patient.PatientId)">▹</button> </td> </tr> </tbody>
