Compare commits

..

No commits in common. "7bdbe5adc03c170c0d65e678f5db9214aa1bdc77" and "614d72923254de5c413049f0d38e90d01f2a4a24" have entirely different histories.

23 changed files with 467 additions and 683 deletions

34
.env
View File

@ -1,20 +1,29 @@
# docker-compose environment file
#
# When you set the same environment variable in multiple files,
# heres the priority used by Compose to choose which value to use:
#
# 1. Compose file
# 2. Shell environment variables
# 3. Environment file
# 4. Dockerfile
# 5. Variable is not defined
# #
# Nginx configuration # Nginx configuration
# #
NGINX_DEFAULT_CONF=./config/ohif/nginx/default.conf NGINX_DEFAULT_CONF=./config/nginx_ohif.conf
NGINX_OHIF_CONF=./config/ohif/nginx/ohif.conf
# #
# OHIF Viewer # OHIF Viewer
# #
OHIF_CONFIG=./config/ohif/ohif.js VIEWER_CONFIG=./config/ohif.js
OHIF_LOGO=./config/ohif/logo.png
# #
# Orthanc core with plugins # Orthanc core with plugins
# #
ORTHANC_CONFIG=./config/orthanc ORTHANC_CONFIG=./config/orthanc.json
ORTHANC_OHIF=./config/ohif/ohif.js ORTHANC_OHIF=./config/orthanc_ohif.js
ORTHANC_DB_MNT=./volumes/orthanc_db ORTHANC_DB_MNT=./volumes/orthanc_db
ORTHANC_LOG=./volumes/orthanc_logs ORTHANC_LOG=./volumes/orthanc_logs
@ -23,24 +32,11 @@ ORTHANC_LOG=./volumes/orthanc_logs
# #
POSTGRES_DATA_MNT=./volumes/pg_data POSTGRES_DATA_MNT=./volumes/pg_data
PGDATA=/var/lib/postgresql/data PGDATA=/var/lib/postgresql/data
PGPASSWORD=secret
POSTGRES_DB=orthanc POSTGRES_DB=orthanc
POSTGRES_PORT=5432 POSTGRES_PORT=5432
POSTGRES_USER=postgres POSTGRES_USER=postgres
POSTGRES_PASSWORD=password POSTGRES_PASSWORD=password
POSTGRES_HOST=postgres
TZ="Asia/Dhaka" TZ="Asia/Dhaka"
PGTZ="Asia/Dhaka" PGTZ="Asia/Dhaka"
PGADMIN_MAIL=admin@blackfish.dev
PGADMIN_PASS=secret
PGADMIN_SERVER=False
PGADMIN_MASTER_PASS=False
PGADMIN_PORT=5050
ORTHANC_AET=BLACKFISH
ORTHANC_USERNAME=blackfish
ORTHANC_PASSWORD=letmein
ORTHANC_TOOLS_MNT=./volumes/orthanc_tools

View File

@ -1 +0,0 @@
1

28
config/nginx_ohif.conf Normal file
View File

@ -0,0 +1,28 @@
server {
listen 80;
# set client body size to 500M, this is to allow uploading of DICOMs, throws '413 request entity too large nginx' error otherwise #
client_max_body_size 500M;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# https://book.orthanc-server.com/faq/nginx.html#nginx
location /orthanc/ {
proxy_pass http://orthanc:8042;
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr;
rewrite /orthanc(.*) $1 break;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Origin' '*';
}
}

View File

@ -19,14 +19,6 @@ window.config = {
}, },
], ],
}, },
studyPrefetcher: {
enabled: true,
displaySetCount: 2,
maxNumPrefetchRequests: 8,
order: 'closest',
},
whiteLabeling: { whiteLabeling: {
/* Used to replace the default Logo */ /* Used to replace the default Logo */
createLogoComponentFn: function (React) { createLogoComponentFn: function (React) {

View File

@ -1,17 +0,0 @@
server {
listen [::]:80 default_server;
listen 80;
proxy_intercept_errors off;
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
gzip_comp_level 9;
etag on;
charset utf-8;
# max upload size
client_max_body_size 250M;
include /etc/nginx/enabled-sites/*.conf;
}

View File

@ -1,42 +0,0 @@
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
add_header Cross-Origin-Opener-Policy same-origin;
add_header Cross-Origin-Embedder-Policy require-corp;
add_header Cross-Origin-Resource-Policy same-origin;
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# https://book.orthanc-server.com/faq/nginx.html#nginx
location /orthanc/ {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
expires 0;
add_header Cache-Control private;
proxy_pass http://orthanc:8042/;
rewrite /orthanc(.*) $1 break;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Origin' '*';
}

View File

@ -1,237 +0,0 @@
window.config = {
extensions: [],
modes: [],
customizationService: {
// Shows a custom route -access via http://localhost:3000/custom
// helloPage: '@ohif/extension-default.customizationModule.helloPage',
},
showStudyList: false,
studyListFunctionsEnabled: false,
filterQueryParam: false,
investigationalUseDialog: {
option: "never",
},
whiteLabeling: {
/* Used to replace the default Logo */
createLogoComponentFn: function (React) {
return React.createElement("a", {
target: "_self",
rel: "noopener noreferrer",
className: "header-brand",
href: "/",
style: {
display: "block",
background: "url(logo.png)",
backgroundSize: "contain",
backgroundRepeat: "no-repeat",
width: "200px",
},
});
},
},
customizationService: {
cornerstoneOverlayTopLeft: {
id: "cornerstoneOverlayTopLeft",
items: [
{
id: "WindowLevel",
customizationType: "ohif.overlayItem.windowLevel",
},
{
id: "PatientName",
customizationType: "ohif.overlayItem",
label: "Pt:",
color: "white",
condition: ({ instance }) =>
instance && instance.PatientName && instance.PatientName.Alphabetic,
contentF: ({ instance, formatters: { formatPN } }) => {
if (
instance &&
instance.PatientName &&
instance.PatientName.Alphabetic
) {
return (
formatPN(instance.PatientName.Alphabetic) +
" " +
(instance.PatientSex ? "(" + instance.PatientSex + ")" : "")
);
} else {
return "N/A";
}
},
},
{
id: "PatientAge",
customizationType: "ohif.overlayItem",
label: "Age:",
color: "white",
title: "Patient's Age",
condition: ({ instance }) => instance && instance.PatientAge,
contentF: ({ instance }) => instance.PatientAge,
},
{
id: "ID",
customizationType: "ohif.overlayItem",
label: "ID:",
color: "white",
title: "Patient PID",
condition: ({ instance }) => instance && instance.PatientID,
contentF: ({ instance }) => instance.PatientID,
},
],
},
},
// some windows systems have issues with more than 3 web workers
maxNumberOfWebWorkers: 3,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
strictZSpacingForVolumeViewport: true,
maxNumRequests: {
interaction: 100,
thumbnail: 75,
// Prefetch number is dependent on the http protocol. For http 2 or
// above, the number of requests can be go a lot higher.
prefetch: 25,
},
httpErrorHandler: (error) => {
// This is 429 when rejected from the public idc sandbox too often.
if (error.status) {
console.warn(error.status);
} else {
console.warn(error);
}
},
hotkeys: [
{
commandName: "incrementActiveViewport",
label: "Next Viewport",
keys: ["right"],
},
{
commandName: "decrementActiveViewport",
label: "Previous Viewport",
keys: ["left"],
},
{ commandName: "rotateViewportCW", label: "Rotate Right", keys: ["r"] },
{ commandName: "rotateViewportCCW", label: "Rotate Left", keys: ["l"] },
{ commandName: "invertViewport", label: "Invert", keys: ["i"] },
{
commandName: "flipViewportHorizontal",
label: "Flip Horizontally",
keys: ["h"],
},
{
commandName: "flipViewportVertical",
label: "Flip Vertically",
keys: ["v"],
},
{ commandName: "scaleUpViewport", label: "Zoom In", keys: ["+"] },
{ commandName: "scaleDownViewport", label: "Zoom Out", keys: ["-"] },
{ commandName: "fitViewportToWindow", label: "Zoom to Fit", keys: ["="] },
{ commandName: "resetViewport", label: "Reset", keys: ["space"] },
{ commandName: "nextImage", label: "Next Image", keys: ["down"] },
{ commandName: "previousImage", label: "Previous Image", keys: ["up"] },
// {
// commandName: 'previousViewportDisplaySet',
// label: 'Previous Series',
// keys: ['pagedown'],
// },
// {
// commandName: 'nextViewportDisplaySet',
// label: 'Next Series',
// keys: ['pageup'],
// },
{
commandName: "setToolActive",
commandOptions: { toolName: "Zoom" },
label: "Zoom",
keys: ["z"],
},
// ~ Window level presets
{
commandName: "windowLevelPreset1",
label: "W/L Preset 1",
keys: ["1"],
},
{
commandName: "windowLevelPreset2",
label: "W/L Preset 2",
keys: ["2"],
},
{
commandName: "windowLevelPreset3",
label: "W/L Preset 3",
keys: ["3"],
},
{
commandName: "windowLevelPreset4",
label: "W/L Preset 4",
keys: ["4"],
},
{
commandName: "windowLevelPreset5",
label: "W/L Preset 5",
keys: ["5"],
},
{
commandName: "windowLevelPreset6",
label: "W/L Preset 6",
keys: ["6"],
},
{
commandName: "windowLevelPreset7",
label: "W/L Preset 7",
keys: ["7"],
},
{
commandName: "windowLevelPreset8",
label: "W/L Preset 8",
keys: ["8"],
},
{
commandName: "windowLevelPreset9",
label: "W/L Preset 9",
keys: ["9"],
},
],
routerBasename: "/ohif/",
dataSources: [
{
friendlyName: "BlackFish DICOMweb",
namespace: "@ohif/extension-default.dataSourcesModule.dicomweb",
sourceName: "dicomweb",
configuration: {
name: "orthanc",
wadoUriRoot: "../dicom-web",
qidoRoot: "../dicom-web",
wadoRoot: "../dicom-web",
qidoSupportsIncludeField: false,
supportsReject: false,
imageRendering: "wadors",
thumbnailRendering: "wadors",
enableStudyLazyLoad: true,
supportsFuzzyMatching: false,
supportsWildcard: true,
staticWado: true,
singlepart: "bulkdata,pdf,video",
acceptHeader: [
"multipart/related; type=application/octet-stream; transfer-syntax=*",
],
},
},
],
defaultDataSourceName: "dicomweb",
};

View File

@ -1,11 +1,7 @@
{ {
"Name": "${ORTHANC_NAME:-BlackFish}", "Name": "PixelBridge",
"StorageDirectory": "/var/lib/orthanc/db", "StorageDirectory": "/var/lib/orthanc/db",
"IndexDirectory": "/var/lib/orthanc/db", "IndexDirectory": "/var/lib/orthanc/db",
"DicomServerEnabled": true,
"DicomAet": "${DICOM_AET:-BLACKFISH}",
"DicomCheckCalledAet": false,
"DicomPort": ${DICOM_PORT:-4242},
"StorageCompression": true, "StorageCompression": true,
"MaximumStorageSize": 0, "MaximumStorageSize": 0,
"MaximumPatientCount": 0, "MaximumPatientCount": 0,
@ -15,6 +11,9 @@
"/usr/share/orthanc/plugins", "/usr/share/orthanc/plugins",
"/usr/local/share/orthanc/plugins" "/usr/local/share/orthanc/plugins"
], ],
"OHIF": {
"UserConfiguration": "/usr/local/share/orthanc/ohif.js"
},
"ExtraMainDicomTags": { "ExtraMainDicomTags": {
"Instance": [ "Instance": [
"Rows", "Rows",
@ -75,14 +74,21 @@
] ]
}, },
"ConcurrentJobs": 8, "ConcurrentJobs": 8,
"HttpServerEnabled": true, "HttpServerEnabled": true,
"OrthancExplorerEnabled": true, "OrthancExplorerEnabled": true,
"HttpPort": 8042, "HttpPort": 8042,
"HttpDescribeErrors": true, "HttpDescribeErrors": true,
"HttpCompressionEnabled": true, "HttpCompressionEnabled": true,
"WebDavEnabled": true, "WebDavEnabled": true,
"WebDavDeleteAllowed": false, "WebDavDeleteAllowed": false,
"WebDavUploadAllowed": true, "WebDavUploadAllowed": true,
"DicomServerEnabled": true,
"DicomAet": "BLACKFISH",
"DicomCheckCalledAet": false,
"DicomPort": 4242,
"DefaultEncoding": "Utf8", "DefaultEncoding": "Utf8",
"AcceptedTransferSyntaxes": [ "AcceptedTransferSyntaxes": [
"1.2.840.10008.1.*" "1.2.840.10008.1.*"
@ -94,12 +100,19 @@
"JpipTransferSyntaxAccepted" : true, "JpipTransferSyntaxAccepted" : true,
"UnknownSopClassAccepted": false, "UnknownSopClassAccepted": false,
"DicomScpTimeout": 30, "DicomScpTimeout": 30,
"RemoteAccessAllowed": true, "RemoteAccessAllowed": true,
"SslEnabled": false, "SslEnabled": false,
"SslCertificate": "certificate.pem", "SslCertificate": "certificate.pem",
"SslMinimumProtocolVersion": 4, "SslMinimumProtocolVersion": 4,
"SslVerifyPeers": false, "SslVerifyPeers": false,
"SslTrustedClientCertificates": "trustedClientCertificates.pem", "SslTrustedClientCertificates": "trustedClientCertificates.pem",
"AuthenticationEnabled": false,
"RegisteredUsers": {
"dicom": "letmein"
},
"DicomTlsEnabled": false, "DicomTlsEnabled": false,
"DicomTlsRemoteCertificateRequired": true, "DicomTlsRemoteCertificateRequired": true,
"DicomAlwaysAllowEcho": true, "DicomAlwaysAllowEcho": true,
@ -109,6 +122,9 @@
"DicomAlwaysAllowGet": false, "DicomAlwaysAllowGet": false,
"DicomAlwaysAllowMove": false, "DicomAlwaysAllowMove": false,
"DicomCheckModalityHost": false, "DicomCheckModalityHost": false,
"DicomModalities": {
// "sample" : [ "STORESCP", "127.0.0.1", 2000 ]
},
"DicomModalitiesInDatabase": false, "DicomModalitiesInDatabase": false,
"DicomEchoChecksFind": false, "DicomEchoChecksFind": false,
"DicomScuTimeout": 10, "DicomScuTimeout": 10,
@ -116,11 +132,13 @@
"DicomThreadsCount": 4, "DicomThreadsCount": 4,
"OrthancPeers": {}, "OrthancPeers": {},
"OrthancPeersInDatabase": false, "OrthancPeersInDatabase": false,
"HttpProxy": "", "HttpProxy": "",
"HttpVerbose": false, "HttpVerbose": false,
"HttpTimeout": 60, "HttpTimeout": 60,
"HttpsVerifyPeers": false, "HttpsVerifyPeers": false,
"HttpsCACertificates": "/etc/ssl/certs/ca-certificates.crt", "HttpsCACertificates": "/etc/ssl/certs/ca-certificates.crt",
"UserMetadata": { "UserMetadata": {
// "Sample" : 1024 // "Sample" : 1024
}, },
@ -128,6 +146,7 @@
// "sample" : 1024 // "sample" : 1024
// "sample2" : [ 1025, "application/pdf" ] // "sample2" : [ 1025, "application/pdf" ]
}, },
"StableAge": 60, "StableAge": 60,
"StrictAetComparison": false, "StrictAetComparison": false,
"StoreMD5ForAttachments": true, "StoreMD5ForAttachments": true,
@ -142,6 +161,11 @@
"QueryRetrieveSize": 100, "QueryRetrieveSize": 100,
"CaseSensitivePN": false, "CaseSensitivePN": false,
"LoadPrivateDictionary": true, "LoadPrivateDictionary": true,
"Dictionary" : {
"0011,1060" : [ "LO", "InnowaveUploaderID", 1, 1, "InowavePrivateGroup"],
"1971,0010" : [ "CS", "PBSender", 1, 1, "PixelBridge"],
"1971,1001" : [ "LO", "DicomSenderID", 1, 1, "PixelBridge"]
},
"SynchronousCMove": true, "SynchronousCMove": true,
"JobsHistorySize": 10, "JobsHistorySize": 10,
"SaveJobs": true, "SaveJobs": true,
@ -151,7 +175,7 @@
"MetricsEnabled": true, "MetricsEnabled": true,
"ExecuteLuaEnabled": false, "ExecuteLuaEnabled": false,
"HttpRequestTimeout": 30, "HttpRequestTimeout": 30,
"DefaultPrivateCreator": "BlackFish", "DefaultPrivateCreator": "PixelBridge",
"StorageCommitmentReportsSize": 100, "StorageCommitmentReportsSize": 100,
"TranscodeDicomProtocol": true, "TranscodeDicomProtocol": true,
"BuiltinDecoderTranscoderOrder": "After", "BuiltinDecoderTranscoderOrder": "After",
@ -170,5 +194,87 @@
"Warnings": { "Warnings": {
"W001_TagsBeingReadFromStorage": true, "W001_TagsBeingReadFromStorage": true,
"W002_InconsistentDicomTagsInDb": true "W002_InconsistentDicomTagsInDb": true
},
"StoneWebViewer": {
/**
* Enables/disables the print button.
**/
"PrintEnabled": false,
/**
* Enables/disables the button to download a screenshot of the
* active viewport as a JPEG file.
**/
"DownloadAsJpegEnabled": false,
/**
* Enables/disables the button to download the display study.
* Only used if "OrthancApiRoot" is properly set.
**/
"DownloadStudyEnabled": false,
/**
* If option "DownloadDicomDir" is set to "true", the Stone Web
* viewer will create DICOMDIR media archives (as generated by the
* route "/studies/{id}/media" of Orthanc), instead of archives
* containing a human-readable hierarchy of folders (as generated
* by the route "/studies/{id}/archive").
**/
"DownloadDicomDir": false,
/**
* By setting option "InstitutionLogo" to an URL containing an
* image, this logo will be displayed at the bottom-left of the
* Stone Web viewer.
**/
"InstitutionLogo": "",
/**
* Whether to display the info panel at startup. Allowed values:
* "Always", "Never", "User". With "User", the user can decide to
* show or not the info panel in the user preferences panel (this
* is implemented using a cookie). (New in Stone Web viewer 2.4)
**/
"ShowInfoPanelAtStartup": "Never",
/**
* Whether to give access to the user preferences window. (New in
* Stone Web viewer 2.4)
**/
"ShowUserPreferencesButton": true,
/**
* Display a "not for diagnostic usage" disclaimer above the list
* of studies/series. (New in Stone Web viewer 2.4)
**/
"ShowNotForDiagnosticUsageDisclaimer": false
},
"DicomWeb": {
"Enable": true,
"Root": "/dicom-web/",
"PublicRoot": "/dicom-web/",
"EnableWado": true,
"WadoRoot": "/wado",
"Ssl": false,
"Servers": {
"main": [
"http://pacs.mylabctg.com:8042/dicom-web/"
]
},
"QidoCaseSensitive": true,
"MetadataWorkerThreadsCount": 10,
"EnableMetadataCache": true,
"StudiesMetadata": "Full",
"SeriesMetadata": "Full"
},
"OrthancExplorer2": {
"Enable": true,
"IsDefaultOrthancUI": true
},
"PostgreSQL": {
"EnableIndex": true,
"EnableStorage": false, // DICOM files are stored in the Orthanc container in /var/lib/orthanc/db/
"Host": "postgres", // the name of the PostgreSQL container
"Port": 5432,
"Database": "orthanc", // 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": "password"
} }
} }

View File

@ -1,18 +0,0 @@
{
"DicomWeb": {
"Enable": true,
"Root": "/dicom-web/",
"PublicRoot": "/dicom-web/",
"EnableWado": true,
"WadoRoot": "/wado",
"Ssl": false,
"Servers": {
//"main": ["http://orthanc:8042/dicom-web/"]
},
"QidoCaseSensitive": true,
"MetadataWorkerThreadsCount": 10,
"EnableMetadataCache": true,
"StudiesMetadata": "Full",
"SeriesMetadata": "Full"
}
}

View File

@ -1,6 +0,0 @@
{
"Dictionary": {
"1971,0010": ["CS", "PBSender", 1, 1, "BlackFish"],
"1971,1001": ["LO", "DicomSenderID", 1, 1, "BlackFish"]
}
}

View File

@ -1,76 +0,0 @@
{
"OrthancExplorer2": {
"CustomTitle": "BlackFish PACS",
"IsDefaultOrthancUI": true,
"Theme": "light",
"UiOptions": {
"EnableOpenInMedDreamViewer": false,
"EnableOpenInOhifViewer3": true,
"EnableOpenInVolView": true,
"EnableStudyList": true,
"EnableDownloadZip": true,
"EnableLinkToLegacyUi": false,
"ShowOrthancName": false,
"DateFormat": "dd/MM/yyyy",
"EnableDownloadDicomFile": true,
"EnableModification": true,
"DefaultShareDuration": 0,
"EnableApiViewMenu": true,
"EnableEditLabels": true,
"EnableViewerQuickButton": true,
"EnableReportQuickButton": false,
"StudyListSearchMode": "search-button",
"StudyListContentIfNoSearch": "empty",
"MaxStudiesDisplayed": 150,
"PageLoadSize": 50,
"MaxMyJobsHistorySize": 5,
"UploadReportTags": [
"PatientName",
"StudyDescription",
"PatientID",
"AccessionNumber",
"StudyDate"
],
"UploadReportMaxTags": 2,
"PatientMainTags": [
"PatientID",
"PatientName",
"PatientBirthDate",
"PatientSex",
"OtherPatientIDs"
],
"StudyMainTags": [
"StudyDate",
"StudyTime",
"StudyDescription",
"AccessionNumber",
"StudyID",
"StudyInstanceUID",
"RequestingPhysician",
"ReferringPhysicianName",
"Department",
"ReportingDoctor",
"InstitutionName"
],
"SeriesMainTags": [
"SeriesDate",
"SeriesTime",
"SeriesDescription",
"SeriesNumber",
"BodyPartExamined",
"ProtocolName",
"SeriesInstanceUID"
],
"StudyListColumns": [
"PatientBirthDate",
"PatientName",
"PatientID",
"StudyDescription",
"StudyDate",
"modalities",
"AccessionNumber",
"seriesAndInstancesCount"
]
}
}
}

View File

@ -1,25 +0,0 @@
{
"Housekeeper": {
"Enable": true,
"GlobalPropertyId": 1971,
"Force": false,
"ThrottleDelay": 15,
"Schedule": {
"Monday": ["3-6"],
"Tuesday": ["3-6"],
"Wednesday": ["3-6"],
"Thursday": ["3-6"],
"Friday": ["3-6"],
"Saturday": ["3-6"],
"Sunday": ["3-6"]
},
"Triggers": {
"StorageCompressionChange": true,
"MainDicomTagsChange": true,
"UnnecessaryDicomAsJsonFiles": true,
"IngestTranscodingChange": true,
"DicomWebCacheChange": true
},
"LimitMainDicomTagsReconstructLevel": "Study"
}
}

View File

@ -1,5 +0,0 @@
{
"DicomModalities": {
// "sample" : [ "STORESCP", "127.0.0.1", 2000 ]
}
}

View File

@ -1,13 +0,0 @@
{
"MultitenantDicom" : {
"Servers" : [
{
"AET" : "BLKFSHIN",
"Port" : 4243,
"Labels" : [ "BLACKFISH_CHENNAI" ],
"LabelsConstraint" : "All",
"LabelsStoreLevels" : [ "Patient", "Study" ]
}
]
}
}

View File

@ -1,5 +0,0 @@
{
"OHIF": {
"UserConfiguration": "/usr/local/share/orthanc/ohif.js"
}
}

View File

@ -1,11 +0,0 @@
{
"PostgreSQL": {
"EnableIndex": true,
"EnableStorage": false,
"Host": "postgres",
"Port": 5432,
"Database": "orthanc",
"Username": "postgres",
"Password": "password"
}
}

View File

@ -1,6 +0,0 @@
{
"AuthenticationEnabled": false,
"RegisteredUsers": {
"blackfish": "letmein"
}
}

View File

@ -1,20 +0,0 @@
{
"StoneWebViewer": {
"DateFormat": "DD/MM/YYYY",
"PrintEnabled": false,
"CombinedToolEnabled": true,
"CombinedToolBehaviour": {
"LeftMouseButton": "Windowing",
"MiddleMouseButton": "Pan",
"RightMouseButton": "Zoom"
},
"DownloadAsJpegEnabled": false,
"DownloadStudyEnabled": false,
"DownloadDicomDir": false,
"InstitutionLogo": "",
"ShowInfoPanelAtStartup": "Never",
"ShowUserPreferencesButton": true,
"ShowNotForDiagnosticUsageDisclaimer": false,
"DicomCacheSize": 256
}
}

View File

@ -1,7 +0,0 @@
{
"WebViewer": {
"CachePath": "WebViewerCache",
"CacheSize": 128,
"Threads": 4
}
}

256
config/orthanc_ohif.js Normal file
View File

@ -0,0 +1,256 @@
/**
* SPDX-FileCopyrightText: 2023-2024 Sebastien Jodogne, UCLouvain, Belgium,
* and 2018-2024 Open Health Imaging Foundation
* SPDX-License-Identifier: MIT
*/
window.config = {
extensions: [],
modes: [],
customizationService: {
// Shows a custom route -access via http://localhost:3000/custom
// helloPage: '@ohif/extension-default.customizationModule.helloPage',
},
showStudyList: false,
investigationalUseDialog: {
option: 'never',
},
whiteLabeling: {
/* Used to replace the default Logo */
createLogoComponentFn: function (React) {
return React.createElement("a", {
target: "_self",
rel: "noopener noreferrer",
className: "header-brand",
href: "/",
style: {
display: "block",
background: "url(logo.png)",
backgroundSize: "contain",
backgroundRepeat: "no-repeat",
width: "200px",
},
});
},
},
customizationService: {
cornerstoneOverlayTopLeft: {
id: 'cornerstoneOverlayTopLeft',
items: [
{
id: 'WindowLevel',
customizationType: 'ohif.overlayItem.windowLevel',
},
{
id: 'PatientName',
customizationType: 'ohif.overlayItem',
label: 'Pt:',
color: 'white',
condition: ({ instance }) =>
instance &&
instance.PatientName &&
instance.PatientName.Alphabetic,
contentF: ({ instance, formatters: { formatPN } }) => {
if (instance && instance.PatientName && instance.PatientName.Alphabetic) {
return formatPN(instance.PatientName.Alphabetic) + ' ' + (instance.PatientSex ? '(' + instance.PatientSex + ')' : '');
} else {
return 'N/A';
}
},
},
{
id: 'PatientAge',
customizationType: 'ohif.overlayItem',
label: 'Age:',
color: 'white',
title: "Patient's Age",
condition: ({ instance }) => instance && instance.PatientAge,
contentF: ({ instance }) => instance.PatientAge,
},
{
id: 'ID',
customizationType: 'ohif.overlayItem',
label: 'ID:',
color: 'white',
title: 'Patient PID',
condition: ({ instance }) => instance && instance.PatientID,
contentF: ({ instance }) => instance.PatientID,
},
],
},
},
// some windows systems have issues with more than 3 web workers
maxNumberOfWebWorkers: 3,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showWarningMessageForCrossOrigin: true,
showCPUFallbackMessage: true,
showLoadingIndicator: true,
strictZSpacingForVolumeViewport: true,
maxNumRequests: {
interaction: 100,
thumbnail: 75,
// Prefetch number is dependent on the http protocol. For http 2 or
// above, the number of requests can be go a lot higher.
prefetch: 25,
},
// filterQueryParam: false,
httpErrorHandler: error => {
// This is 429 when rejected from the public idc sandbox too often.
if (error.status) {
console.warn(error.status);
} else {
console.warn(error);
}
},
hotkeys: [
{
commandName: 'incrementActiveViewport',
label: 'Next Viewport',
keys: ['right'],
},
{
commandName: 'decrementActiveViewport',
label: 'Previous Viewport',
keys: ['left'],
},
{ commandName: 'rotateViewportCW', label: 'Rotate Right', keys: ['r'] },
{ commandName: 'rotateViewportCCW', label: 'Rotate Left', keys: ['l'] },
{ commandName: 'invertViewport', label: 'Invert', keys: ['i'] },
{
commandName: 'flipViewportHorizontal',
label: 'Flip Horizontally',
keys: ['h'],
},
{
commandName: 'flipViewportVertical',
label: 'Flip Vertically',
keys: ['v'],
},
{ commandName: 'scaleUpViewport', label: 'Zoom In', keys: ['+'] },
{ commandName: 'scaleDownViewport', label: 'Zoom Out', keys: ['-'] },
{ commandName: 'fitViewportToWindow', label: 'Zoom to Fit', keys: ['='] },
{ commandName: 'resetViewport', label: 'Reset', keys: ['space'] },
{ commandName: 'nextImage', label: 'Next Image', keys: ['down'] },
{ commandName: 'previousImage', label: 'Previous Image', keys: ['up'] },
// {
// commandName: 'previousViewportDisplaySet',
// label: 'Previous Series',
// keys: ['pagedown'],
// },
// {
// commandName: 'nextViewportDisplaySet',
// label: 'Next Series',
// keys: ['pageup'],
// },
{
commandName: 'setToolActive',
commandOptions: { toolName: 'Zoom' },
label: 'Zoom',
keys: ['z'],
},
// ~ Window level presets
{
commandName: 'windowLevelPreset1',
label: 'W/L Preset 1',
keys: ['1'],
},
{
commandName: 'windowLevelPreset2',
label: 'W/L Preset 2',
keys: ['2'],
},
{
commandName: 'windowLevelPreset3',
label: 'W/L Preset 3',
keys: ['3'],
},
{
commandName: 'windowLevelPreset4',
label: 'W/L Preset 4',
keys: ['4'],
},
{
commandName: 'windowLevelPreset5',
label: 'W/L Preset 5',
keys: ['5'],
},
{
commandName: 'windowLevelPreset6',
label: 'W/L Preset 6',
keys: ['6'],
},
{
commandName: 'windowLevelPreset7',
label: 'W/L Preset 7',
keys: ['7'],
},
{
commandName: 'windowLevelPreset8',
label: 'W/L Preset 8',
keys: ['8'],
},
{
commandName: 'windowLevelPreset9',
label: 'W/L Preset 9',
keys: ['9'],
},
],
};
/**
* SPDX-FileCopyrightText: 2023-2024 Sebastien Jodogne, UCLouvain, Belgium,
* and 2018-2024 Open Health Imaging Foundation
* SPDX-License-Identifier: MIT
*/
window.config.routerBasename = '/ohif/';
if (true) {
window.config.dataSources = [
{
friendlyName: 'Orthanc DICOMweb',
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
sourceName: 'dicomweb',
configuration: {
name: 'orthanc',
wadoUriRoot: '../dicom-web',
qidoRoot: '../dicom-web',
wadoRoot: '../dicom-web',
qidoSupportsIncludeField: false,
supportsReject: false,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
enableStudyLazyLoad: true,
supportsFuzzyMatching: false,
supportsWildcard: true,
staticWado: true,
singlepart: 'bulkdata,pdf,video',
acceptHeader: ['multipart/related; type=application/octet-stream; transfer-syntax=*']
}
}
];
window.config.defaultDataSourceName = 'dicomweb';
} else {
window.config.showStudyList = false;
window.config.dataSources = [
{
friendlyName: 'Orthanc DICOM JSON',
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
sourceName: 'dicomjson',
configuration: {
name: 'json',
},
}
];
window.config.defaultDataSourceName = 'dicomjson';
}

View File

@ -1,158 +1,88 @@
services: services:
postgres: postgres:
image: postgres:alpine image: postgres:17
container_name: postgres container_name: postgres
profiles: [main, extra]
ports:
- "5432:5432"
networks: networks:
pacs: - pacs
aliases:
- postgres
environment:
PGPASSWORD: ${PGPASSWORD}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
PGDATA: ${PGDATA}
PGTZ: ${PGTZ}
POSTGRES_HOST_AUTH_METHOD: "trust"
volumes: volumes:
- ${POSTGRES_DATA_MNT}:${PGDATA}:Z - ${POSTGRES_DATA_MNT}:${PGDATA}
environment:
- PGPASSWORD='secret'
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
- PGDATA=${PGDATA}
- PGTZ=${PGTZ}
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] test: [ "CMD", "pg_isready", "-q", "-d", "${DB_DATABASE}", "-U", "${DB_USERNAME}" ]
start_period: 20s retries: 3
interval: 30s
retries: 5
timeout: 5s timeout: 5s
pgadmin:
depends_on:
- postgres
container_name: pgadmin
image: dpage/pgadmin4
restart: unless-stopped restart: unless-stopped
environment:
PGADMIN_DEFAULT_EMAIL: admin@blackfish.dev
PGADMIN_DEFAULT_PASSWORD: password
ports:
- 5050:88
orthanc: orthanc:
container_name: orthanc container_name: orthanc
profiles: [main, extra] image: jodogne/orthanc-plugins
image: orthancteam/orthanc
ports: ports:
- "8042:8042" - 8042:8042
- "4242:4242" - 4242:4242
volumes: volumes:
- ${ORTHANC_CONFIG:-./config/orthanc}:/etc/orthanc/:ro # configuration file
- ${ORTHANC_DB_MNT:-./volumes/orthanc_db}:/var/lib/orthanc/db:Z - ${ORTHANC_CONFIG:-./config/orthanc.json}:/etc/orthanc/orthanc.json:ro
- ${ORTHANC_OHIF:-./config/ohif/ohif.js}:/usr/local/share/orthanc/ohif.js:ro # storage volume for raw dicoms
- ${ORTHANC_LOG:-./volumes/orthanc_logs}:/var/log/orthanc - ${ORTHANC_DB_MNT:-./volumes/orthanc_db}:/var/lib/orthanc/db
env_file: - ${ORTHANC_OHIF:-./config/orthanc_ohif.js}:/usr/local/share/orthanc/ohif.js:ro
- orthanc.env - ${ORTHANC_LOG:-./volumes/orthanc_logs}:/etc/orthanc/logs
environment: environment:
ORTHANC__DICOM_AET: "${ORTHANC_AET}" VERBOSE_ENABLED: "true"
ORTHANC__POSTGRESQL__HOST: "${POSTGRES_HOST}" VERBOSE_STARTUP: "true"
restart: unless-stopped DICOM_WEB_PLUGIN_ENABLED: "true"
OHIF_PLUGIN_ENABLED: "true"
VOLVIEW_PLUGIN_ENABLED: "true"
restart: always
networks: networks:
pacs: - pacs
aliases:
- orthanc
depends_on: depends_on:
- postgres - postgres
ohif: ohif:
container_name: ohif container_name: ohif
profiles: [main, extra] image: ohif/viewer
image: ohif/app:v3.9.2
ports: ports:
- "3000:80" - 3000:80
environment: environment:
APP_CONFIG: /usr/share/nginx/html/app-config.js - APP_CONFIG:/usr/share/nginx/html/app-config.js
volumes: volumes:
- ${NGINX_DEFAULT_CONF}:/etc/nginx/conf.d/default.conf:ro - ${NGINX_DEFAULT_CONF}:/etc/nginx/conf.d/default.conf:ro
- ${NGINX_OHIF_CONF}:/etc/nginx/enabled-sites/ohif.conf:ro - ${VIEWER_CONFIG}:/usr/share/nginx/html/app-config.js:ro
- ${OHIF_CONFIG}:/usr/share/nginx/html/app-config.js:ro - ./logo.png:/usr/share/nginx/html/logo.png:ro
- ${OHIF_LOGO}:/usr/share/nginx/html/logo.png:ro restart: always
restart: unless-stopped
depends_on:
- orthanc
networks: networks:
pacs: - pacs
aliases:
- ohif
meddream: meddream:
image: meddream/dicom-viewer:8.5.0 image: meddream/dicom-viewer:8.5.0
profiles: [extra] restart: always
container_name: meddream
restart: unless-stopped
ports: ports:
- "80:8080" - "80:8080"
depends_on:
- orthanc
- postgres
networks: networks:
pacs: - pacs
aliases:
- meddream
volumes: volumes:
- ./config/meddream/application.properties:/opt/meddream/application.properties:ro - ./config/meddream/application.properties:/opt/meddream/application.properties:ro
#- ./config/meddream/license:/opt/meddream/license:ro #- ./config/meddream/license:/opt/meddream/license:ro
- ./config/meddream/system.json:/opt/meddream/sys/settings/system.json:ro - ./config/meddream/system.json:/opt/meddream/sys/settings/system.json:ro
orthanctoolsjs:
profiles: [extra]
image: salimkanoun/orthanctoolsjs
restart: unless-stopped
ports:
- "4000:4000"
volumes:
- ${ORTHANC_TOOLS_MNT:-./volumes/orthanc_tools}:/OrthancToolsJs/data
environment:
TZ: "${TZ}"
ORTHANC_ADDRESS: "http://orthanc"
ORTHANC_PORT: "8042"
ORTHANC_USERNAME: "${ORTHANC_USERNAME}"
ORTHANC_PASSWORD: "${ORTHANC_PASSWORD}"
REDIS_HOST: "redis"
REDIS_PORT: "6379"
REDIS_PASSWORD: ""
DB_USERNAME: "${POSTGRES_USER}"
DB_PASSWORD: "${POSTGRES_PASSWORD}"
DB_HOST: "${POSTGRES_HOST}"
DB_PORT: ${POSTGRES_PORT}
DB_NAME: ${POSTGRES_DB}
DOMAIN_PROTOCOL: "http"
DOMAIN_ADDRESS: "localhost:4000"
depends_on:
- redis
- orthanc
- postgres
networks:
pacs:
aliases:
- orthanctoolsjs
redis:
profiles: [extra]
image: redis:alpine
networks:
pacs:
aliases:
- redis
pgadmin:
container_name: pgadmin
profiles: [extra]
image: dpage/pgadmin4:latest
restart: unless-stopped
environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_MAIL}
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASS}
PGADMIN_CONFIG_SERVER_MODE: ${PGADMIN_SERVER}
PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: ${PGADMIN_MASTER_PASS}
PGADMIN_LISTEN_PORT: ${PGADMIN_PORT}
ports:
- "${PGADMIN_PORT}:${PGADMIN_PORT}"
depends_on:
- postgres
networks:
pacs:
aliases:
- pgadmin
networks: networks:
pacs: pacs:
external: true external: true

View File

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

@ -1,35 +0,0 @@
VERBOSE_STARTUP=true
#VERBOSE_ENABLED=true
ORTHANC__POSTGRESQL__HOST=orthanc-db
ORTHANC__POSTGRESQL__TRANSACTION_MODE=ReadCommitted
ORTHANC__POSTGRESQL__INDEX_CONNECTIONS_COUNT=10
ORTHANC__OVERWRITE_INSTANCES=true
#ORTHANC__DICOM_MODALITIES={"pacs": ["PACS", "pacs", 4242]}
ORTHANC__DICOM_WEB__SERVERS={"pacs": ["http://orthanc:8042/dicom-web/"]}
ORTHANC__DICOM_WEB__SERIES_METADATA="Full"
ORTHANC__DICOM_WEB__STUDIES_METADATA="Full"
ORTHANC__DICOM_WEB__METADATA_WORKER_THREADS_COUNT=4
ORTHANC__STONE_WEB_VIEWER__DATE_FORMAT: "DD/MM/YYYY"
ORTHANC__AUTHENTICATION_ENABLED: "false"
ORTHANC__NAME="BlackFish"
POSTGRESQL_PLUGIN_ENABLED=true
LOGDIR="/var/log/orthanc"
VERBOSE_ENABLED=true
VERBOSE_STARTUP=true
DICOM_WEB_PLUGIN_ENABLED=true
OHIF_PLUGIN_ENABLED=true
VOLVIEW_PLUGIN_ENABLED=true
ORTHANC_WEB_VIEWER_PLUGIN_ENABLED=true
STONE_WEB_VIEWER_PLUGIN_ENABLED=true
HOUSEKEEPER_PLUGIN_ENABLED=true
ORTHANC_EXPLORER_2_ENABLED=true
#PYTHON_PLUGIN_ENABLED=true
#TRANSFERS_PLUGIN_ENABLED=true
#WORKLISTS_PLUGIN_ENABLED=true
#MULTITENANT_DICOM_PLUGIN_ENABLED=true
#INDEXER_PLUGIN_ENABLED=true
#OSIMIS_WEB_VIEWER1_PLUGIN_ENABLED=true