Hi Orthanc experts! We are looking into using Orthanc as local dicom server in our MRI lab, and potentially use Orthanc’s web-UI to allow researcher to easily search, filter & download studies as needed directly from their web browser (on local LAN). We were able to setup orthanc and it seems to be working. However, any search/filter is very slow to load results on Orthanc Explorer 2 (OE2). A somewhat unique aspect of our studies is that we have a lot of instances in each series. We research with advanced diffusion MRI type sequences and its often common to have 70-80K instances in each study. Sometime, even more when with long fMRI sequences.
The issue: Orthanc Explorer 2 (OE2) takes a long time, 30-40 secs, to finish loading the filter/search for local studies stored in orthanc. It gets stuck on “Searching…” for good 30-40 seconds after we click the search button. As of now the sever has only 17 studies (1-2 study with large number of instance; rest have ~50-200 instances). In contrast, in original orthanc-explorer (/app/explorer.html), I can click “Do Lookup” and filter studies as I type (its instantaneous).
In order to troubleshoot, I followed the log as I was clicking thing in OE2 UI. Logs below. I found that first three lines appear in the log immediately after I click search button. However, the web-UI keep showing “Searching…” for next ~30 seconds, until the results actually appear. I clicked on one the results as soon as they appear in the OE2 UI and Line #4 onwards appear immediately in the log below.
I1004 16:28:54.582900 HTTP-36 HttpServer.cpp:1263] (http) POST /tools/find
I1004 16:28:54.594135 HTTP-36 ServerContext.cpp:1566] Number of candidate resources after fast DB filtering on main DICOM tags: 12
I1004 16:28:54.602693 HTTP-36 ServerContext.cpp:1714] Number of matching resources: 12
I1004 16:29:36.265116 HTTP-39 HttpServer.cpp:1263] (http) GET /tools/labels
I1004 16:29:36.266632 HTTP-40 HttpServer.cpp:1263] (http) POST /tools/find
I1004 16:29:36.268311 HTTP-40 ServerContext.cpp:1566] Number of candidate resources after fast DB filtering on main DICOM tags: 6
I1004 16:29:36.272701 HTTP-40 ServerContext.cpp:1714] Number of matching resources: 6
I1004 16:29:36.275990 HTTP-40 HttpServer.cpp:1263] (http) GET /studies/51b86852-1b8cb668-bd7579cb-e5a1d5c1-f957b972/series
Also, If I change my search criteria such that I avoid all the studies with huge number of instances, then the results appear in OE2 UI almost instantaneously. With these observations, my hypothesis is that OE2 UI is loading some additional attributes from all instances that match the search criteria, which is consuming some time. So, I searched around and tried removing columns like modality from UI, and also add more tags to ExtraMainDicomTags so that they are cached in the index. But it did not help.
Also the index is stored on SSD, while dicom storage is on RAID10 HDD. Sever hardware is reasonably new; I can dig up detains if needed. Full Config below.
Any ideas, what else can I try to make search faster in OE2 with studies with large number of instances?
Statistics
# Patients 11
# Studies 17
# Series 183
# Instances 109956
Storage Size 9.34 GB
Docker compose config:
version: "3.3"
services:
orthanc:
image: orthancteam/orthanc:24.9.1
restart: unless-stopped
depends_on: [orthanc-index]
ports: ["4006:4006", "8042:8042"]
volumes:
- orthanc-storage:/var/lib/orthanc/db
- /data_nobackup/orthanc-index/logs:/logs
secrets:
- orthanc.secret.json
environment:
VERBOSE_STARTUP: "true"
VERBOSE_ENABLED: "true"
LOGDIR: "/logs"
# enable DicomWeb plugins
DICOM_WEB_PLUGIN_ENABLED: "true"
# enable StoneViewer, DicomWeb plugins, OrthancWebViewer, and old OSIMIS_WEB_VIEWER
ORTHANC_WEB_VIEWER_PLUGIN_ENABLED: "true"
# OSIMIS_WEB_VIEWER1_PLUGIN_ENABLED: "true"
# OSIMIS_WEB_VIEWER1_ALPHA_PLUGIN_ENABLED: "true"
STONE_WEB_VIEWER_PLUGIN_ENABLED: "true"
OHIF_PLUGIN_ENABLED: "true"
NEURO_PLUGIN_ENABLED: "true"
HOUSEKEEPER_PLUGIN_ENABLED: "true"
ORTHANC_JSON: |
{
"Name": "HAGRID",
"DicomAet": "HAGRID",
"DicomPort": 4006,
"DicomAlwaysAllowEcho": true,
"DicomAlwaysAllowStore": true,
"DicomAlwaysAllowFind": true,
"DicomAlwaysAllowGet": true,
"DicomCheckCalledAet": false,
"DicomCheckModalityHost": false,
"RemoteAccessAllowed": true,
"AuthenticationEnabled": true,
"StorageCompression": false, // compress dicoms or not
"LimitFindResults": 100, // performance boost
"LimitFindInstances": 100, // performance boost
"KeepAlive": true, // performance boost
"TcpNoDelay": true, // performance boost
"StorageAccessOnFind": "Never", // performance boost
"SaveJobs": false, // performance boost
"DefaultEncoding": "Utf8",
"MaximumStorageCacheSize" : 1280, // Max RAM cache in MB. contains copy recently accessed files (written or read)
"DicomModalities" : {
"gr3Tarch" : [ "gr3Tarch", "10.178.100.61", 4006 ],
"nmr-aw3" : [ "nmr-aw3", "10.178.100.68", 4006 ]
},
"PostgreSQL": {
"EnableIndex": true,
"EnableStorage": false, // DICOM files are stored outside PostgreSQL
"Host": "orthanc-index", // the name of the PostgreSQL container
"Database": "postgres", // default database name in PostgreSQL container (no need to create it)
"Username": "postgres", // default user name in PostgreSQL container (no need to create it)
"Password": "postgrespassword",
"EnableSsl" : false, // Disable SSL connections between Orthanc and PostgreSQL server
"Lock": false,
"MaximumConnectionRetries" : 10,
"ConnectionRetryInterval" : 5,
"IndexConnectionsCount" : 10
},
"OrthancExplorer2" : {
"Enable": true,
"IsDefaultOrthancUI": true,
"Theme": "light",
"UiOptions" : {
"EnableStudyList": true, // Enables the access to the study list
"EnableUpload": true, // Enables the upload menu/interface
"EnableDicomModalities": true, // Enables the 'DICOM Modalities' interface in the side menu
"EnableDeleteResources": true, // Enables the delete button for Studies/Series/Instances
"EnableDownloadZip": true, // Enables the download zip button for Studies/Series
"EnableDownloadDicomDir": false, // Enables the download DICOM DIR button for Studies/Series
"EnableDownloadDicomFile": false, // Enables the download DICOM file button for Instances
"EnableAnonymization": false, // Enables the anonymize button
"EnableModification": false, // Enables the modify button
"EnableSendTo": true, // Enables the 'SendTo' button for Studies/Series/Instances
"EnableApiViewMenu": false, // Enables the API button to open API routes for Studies/Series/Instances (developer mode)
"EnableSettings": true, // Enables the settings menu/interface
"EnableLinkToLegacyUi": false, // Enables a link to the legacy Orthanc UI
"EnableChangePassword": false, // Enables the 'change password' button in the side bar. Only applicable if Keycloak is enabled
"EnableEditLabels": false, // Enables labels management (create/delete/assign/unassign)
"EnableAddSeries": false, // Enables the "Add series" button
"MaxStudiesDisplayed": 100, // The maximum number of studies displayed in the study list
"MaxMyJobsHistorySize": 5, // The maximum number of jobs appearing under 'my jobs' in side bar (0 = unlimited)
"StudyListSearchMode": "search-button", // mode to trigger a search in the StudyList. Accepted values: 'search-as-you-type' or 'search-button'
"StudyListSearchAsYouTypeMinChars": 3, // minimum number of characters to enter in a text search field before it starts searching the DB
"StudyListSearchAsYouTypeDelay": 400, // Delay [ms] between the last key stroke and the trigger of the search
"StudyListContentIfNoSearch": "empty", // Defines what to show if no search criteria has been entered Allowed values: "empty", "most-recents"
"ShowOrthancName": true, // display the Orthanc Name in the side menu
"StudyListColumns" : [
"StudyID",
"PatientName",
"PatientID",
"StudyDescription",
"StudyDate"
],
"PatientMainTags" : [
"PatientID",
"PatientName"
],
"StudyMainTags" : [
"StudyID",
"StudyDate",
"StudyDescription",
"StudyInstanceUID",
"InstitutionName"
],
"SeriesMainTags" : [
"SeriesNumber",
"SeriesDescription",
"SeriesDate",
"SeriesInstanceUID"
],
"ModalitiesFilter": [
"CR", "CT", "MR", "NM", "US"
],
"DefaultLanguage" : "en",
"DateFormat": "yyyy-MMM-dd"
}
},
"DicomWeb" : {
"Enable" : true, // Whether DICOMweb support is enabled
"Root" : "/dicom-web/", // Root URI of the DICOMweb API (for QIDO-RS STOW-RS and WADO-RS)
"EnableWado" : true, // Whether WADO-URI (previously known as WADO) support is enabled
"WadoRoot" : "/wado", // Root URI of the WADO-URI (aka WADO) API
"Ssl" : false, // Whether HTTPS should be used for subsequent WADO-RS requests
"QidoCaseSensitive" : true, // For QIDO-RS server, whether search is case sensitive (since release 0.5)
"EnableMetadataCache": true, // Wheter the plugin caches metadata as a gzipped attachment (since release 1.15)
"StudiesMetadata" : "MainDicomTags",
"SeriesMetadata" : "MainDicomTags"
},
// When using Web-viewer or OHIF viewer in a setup where performance and accuracy are both important,
// you should configure ExtraMainDicomTags and configure StudiesMetadata and SeriesMetadata to MainDicomTags as
// demonstrated in this https://github.com/orthanc-server/orthanc-setup-samples/blob/master/docker/stone-viewer/docker-compose.yml
// https://orthanc.uclouvain.be/book/plugins/dicomweb.html?highlight=enablemetadatacache#id6
// https://orthanc.uclouvain.be/book/faq/main-dicom-tags.html#adding-more-tags-in-db
"ExtraMainDicomTags" : {
"Instance" : [
"Rows",
"Columns",
"ImageType",
"SOPClassUID",
"ContentDate",
"ContentTime",
"FrameOfReferenceUID",
"PixelSpacing",
"SpecificCharacterSet",
"BitsAllocated",
"BitsStored",
"RescaleSlope",
"RescaleIntercept",
"SliceThickness",
"WindowCenter",
"WindowWidth",
"PhotometricInterpretation",
"PixelRepresentation"
],
"Series" : [
"TimezoneOffsetFromUTC",
"PerformedProcedureStepStartDate",
"PerformedProcedureStepStartTime",
"RequestAttributesSequence"
],
"Study": [
"TimezoneOffsetFromUTC"
],
"Patient": []
},
"Housekeeper": {
"Enable": true, // Enables/disables the plugin,
// Delay (in seconds) between reconstruction of 2 studies
// This avoids overloading Orthanc with the housekeeping
// process and leaves room for other operations.
"ThrottleDelay": 5,
// configure events that can trigger a housekeeping processing
"Triggers" : {
"StorageCompressionChange": true,
"MainDicomTagsChange": true,
"UnnecessaryDicomAsJsonFiles": true,
"IngestTranscodingChange": true,
"DicomWebCacheChange": true // new in 1.12.2
}
}
}
orthanc-index:
image: postgres:15
restart: unless-stopped
ports: ["5432:5432"]
volumes: ["orthanc-index:/var/lib/postgresql/data:Z"]
environment:
POSTGRES_PASSWORD: "postgrespassword"
volumes:
orthanc-storage:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/data_nobackup2/orthanc-storage'
orthanc-index:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/data_nobackup/orthanc-index'
secrets:
orthanc.secret.json:
file: orthanc.secret.json