Last update : March 20, 2016
This contribution explains how to implement an Orthanc DICOM PACS Server on a Raspberry Pi (RPI) standalone single-board computer. The Orthanc source code was compiled on a Raspberry Pi 1 model B computer and tested on RPI models B Pi 1, Pi 2 and Pi 3. I use Raspbian Jessie for my RPI’s, a free operating system based on Debian, optimized for the Raspberry Pi hardware. I call the resulting mini PACS server an OrthancPi.
Debian Med
An Orthanc package for Debian is available at the Debian website. This package is part of Debian Med, a specific flavour of Debian that is particularly well fit for the requirements for medical practice and biomedical research. The Debian Med package is maintained by the developer of Orthanc, Sébastien Jodogne, a Medical Imaging Engineer at the Medical Physics Department from the University Hospital of Liège (CHU) in Belgium.
The stable Orthanc version for Debian Jessie is 0.8.4. The Orthanc version 1.0 is only available for the testing (Stretch) and for the unstable (SID) Debian distributions. A release for the armhf architecture is part of the Orthanc package. The file list of the orthanc package in the Debian stretch distribution for the armhf architecture is the following :
/etc/init.d/orthanc
/etc/orthanc/orthanc.json
/etc/orthanc/serve-folders.json
/etc/orthanc/worklists.json
/usr/lib/orthanc/libModalityWorklists.so.1.0.0
/usr/lib/orthanc/libServeFolders.so.1.0.0
/usr/sbin/Orthanc
/usr/share/doc/orthanc/NEWS.gz
/usr/share/doc/orthanc/README.Debian
/usr/share/doc/orthanc/changelog.Debian.armhf.gz
/usr/share/doc/orthanc/changelog.Debian.gz
/usr/share/doc/orthanc/changelog.gz
/usr/share/doc/orthanc/copyright
/usr/share/lintian/overrides/orthanc
/usr/share/man/man1/Orthanc.1.gz
/usr/share/orthanc/plugins/libModalityWorklists.so
/usr/share/orthanc/plugins/libServeFolders.so
Orthanc Source Code
RPI’s are based on the ARM architecture and Raspbian releases usually follow the corresponding Debian release, but do deviate in a handful of cases. For this reason I preferred to build Orthanc version 1.0 from the source code, located on Bitbucket, on the Raspberry Pi hardware.
I downloaded the repository and put the content into a folder named Orthanc in the Raspberry Pi /home/pi/ directory. The following packages needed for compilation and linking have been installed first :
sudo apt-get install build-essential unzip cmake mercurial \
uuid-dev libcurl4-openssl-dev liblua5.1-0-dev \
libgoogle-glog-dev libgtest-dev libpng-dev libjpeg-dev \
libsqlite3-dev libssl-dev zlib1g-dev libdcmtk2-dev \
libboost-all-dev libwrap0-dev libjsoncpp-dev libpugixml-dev
I created a new folder OrthancBuild inside the /home/pi/ directory and executed the following commands :
cd OrthancBuild
cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Release ~/Orthanc
make
During the configuration process, the following files have been downloaded from the website http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/ :
- boost_1_59_0 : (boost C++ librairies)
- curl-7.44.0 : (curl tool and library for transferring data with URL syntax)
- dcmtk-3.6.0 : (DICOM librairies and applications)
- gtest-1.7.0 : (C++ Google framework to write tests)
- jsoncpp-0.10.5 : (C++ library that allows manipulating JSON values)
- libpng-1.5.12 : (official PNG reference C89 library)
- jpeg-9a : (JPEG image compression)
- lua-5.1.5 : (powerful, fast, lightweight, embeddable scripting language)
- mongoose-3.8 : (easy to use web server)
- openssl-1.0.2d : (toolkit implementing SSL v2/v3 andTLS protocols)
- pugixml-1.4 : (C++ light-weight XML processing library)
- sqlite-amalgamation-3071300 : (self-contained SQL database engine)
- zlib-1.2.7 : (Unobtrusive Compression Library)
All the files have been saved in a new folder orthanc-default/ThirdPartyDownloads. All the third-party dependencies are statically linked to the Orthanc build. The compilation takes more time (several hours), compared to the default behavior where system wide libraries are used. Statically linked builds are however easier to share and to clone.
The result of the compilation was the generation of the following files :
- Orthanc (executable)
- UnitTests (executable)
- libServeFolders.so.mainline (shared library) -> renamed to libServeFolders.so
- libModalityWorklist.so.mainline (shared library) -> renamed to libModalityWorklist.so
- libCoreLibrary.a (AR archive)
- libServerLibrary.a (AR archive)
- libOpenSSL.a (AR archive)
Running the UnitTests shows that all 154 tests from 43 test cases passed, 2 tests were disabled.
Orthanc plugins
I used the same procedure to compile the plugins DICOMweb and WebViewer. The source code was copied into the folders /home/pi/Dicomweb/ and /home/pi/Webviewer/. I created the new folders /home/pi/DicomwebBuild/ and /home/pi/WebviewerBuild and finally executed the commands
cd /home/pi/DicomwebBuild
cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Release ~/Dicomweb
make
cd /home/pi/WebviewerBuild
cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Release ~/Webviewer
make
The following third-party libraries are used by the plugins :
Dicomweb | Webviewer |
boost_1_59_0 | boost_1_59_0 |
GDCM-prefix | GDCM-prefix |
gtest-1.7.0 | gtest-1.7.0 |
jsoncpp-0.10.5 | jsoncpp-0.10.5 |
pugixml-1.4 | – |
zlib-1.2.7 | – |
– | cornerstone-0.8.4 |
– | javascript-libs |
– | jquery-ui-1.11.3 |
– | jspanel |
– | jsurl-1.8.6 |
– | pako-0.2.5 |
– | sqlite-amalgamation-3071300 |
The shared libraries libOrthancDicomWeb.so.mainline and libOrthancWebViewer.so.mainline were created as a result of the compilation and linking process. I renamed these libraries without the mainline suffix.
The results of the UnitTests runs are shown hereafter :
OrthancPi
The OrthancPi distribution files are assembled as follows in a directory named /home/pi/orthancpi/.
- Orthanc (executable)
- UnitTests (executable)
- configuration.json
- /plugins/libServeFolders.so
- /plugins/libModalityWorklists.so
- /plugins/libOrthancDicomWeb.so
- /plugins/libOrthancWebViewer.so.
- /web/index.html (OrthancPi welcome page)
- /python/ (empty)
- /lua/ (empty)
- /WorklistsDatabase/ (worklist samples)
- /OrthancStorage/ (empty)
The default configuration.json file is created with the command
cd orthancpi
./Orthanc --config=configuration.json
I modified the configuration file as follows :
{
// ***
// General configuration of Orthanc
// ***
// The logical name of this instance of Orthanc. This one is
// displayed in Orthanc Explorer and at the URI "/system".
"Name" : "OrthancPi",
// Path to the directory that holds the heavyweight files
// (i.e. the raw DICOM instances)
"StorageDirectory" : "OrthancStorage",
// Path to the directory that holds the SQLite index (if unset,
// the value of StorageDirectory is used). This index could be
// stored on a RAM-drive or a SSD device for performance reasons.
"IndexDirectory" : "OrthancStorage",
// Enable the transparent compression of the DICOM instances
"StorageCompression" : false,
// Maximum size of the storage in MB (a value of "0" indicates no
// limit on the storage size)
"MaximumStorageSize" : 0,
// Maximum number of patients that can be stored at a given time
// in the storage (a value of "0" indicates no limit on the number
// of patients)
"MaximumPatientCount" : 0,
// List of paths to the custom Lua scripts that are to be loaded
// into this instance of Orthanc
"LuaScripts" : [
],
// List of paths to the plugins that are to be loaded into this
// instance of Orthanc (e.g. "./libPluginTest.so" for Linux, or
// "./PluginTest.dll" for Windows). These paths can refer to
// folders, in which case they will be scanned non-recursively to
// find shared libraries.
"Plugins" : [
"../plugins/libServeFolders.so",
"../plugins/libOrthancWebViewer.so",
"../plugins/libOrthancDicomWeb.so",
"../plugins/libModalityWorklists.so"
],
"Worklists" : {
"Enable": true,
"Database": "../WorklistsDatabase"
},
"ServeFolders" : {
"/web" : "/home/pi/orthancpi/web"
},
"DicomWeb" : {
"Enable" : true,
"Root" : "/dicom-web/",
"EnableWadoo" : true,
"WadooRoot" : "/wado",
"Host" : "localhost",
"Ss1" : false
},
// **
// Configuration of the HTTP server
// **
// Enable the HTTP server. If this parameter is set to "false",
// Orthanc acts as a pure DICOM server. The REST API and Orthanc
// Explorer will not be available.
"HttpServerEnabled" : true,
// HTTP port for the REST services and for the GUI
"HttpPort" : 8042,
// When the following option is "true", if an error is encountered
// while calling the REST API, a JSON message describing the error
// is put in the HTTP answer. This feature can be disabled if the
// HTTP client does not properly handles such answers.
"HttpDescribeErrors" : true,
// Enable HTTP compression to improve network bandwidth utilization,
// at the expense of more computations on the server. Orthanc
// supports the "gzip" and "deflate" HTTP encodings.
"HttpCompressionEnabled" : true,
// **
// Configuration of the DICOM server
// **
// Enable the DICOM server. If this parameter is set to "false",
// Orthanc acts as a pure REST server. It will not be possible to
// receive files or to do query/retrieve through the DICOM protocol.
"DicomServerEnabled" : true,
// The DICOM Application Entity Title
"DicomAet" : "ORTHANCPI",
// Check whether the called AET corresponds during a DICOM request
"DicomCheckCalledAet" : false,
// The DICOM port
"DicomPort" : 4242,
// The default encoding that is assumed for DICOM files without
// "SpecificCharacterSet" DICOM tag. The allowed values are "Ascii",
// "Utf8", "Latin1", "Latin2", "Latin3", "Latin4", "Latin5",
// "Cyrillic", "Windows1251", "Arabic", "Greek", "Hebrew", "Thai",
// "Japanese", and "Chinese".
"DefaultEncoding" : "Utf8",
// The transfer syntaxes that are accepted by Orthanc C-Store SCP
"DeflatedTransferSyntaxAccepted" : true,
"JpegTransferSyntaxAccepted" : true,
"Jpeg2000TransferSyntaxAccepted" : true,
"JpegLosslessTransferSyntaxAccepted" : true,
"JpipTransferSyntaxAccepted" : true,
"Mpeg2TransferSyntaxAccepted" : true,
"RleTransferSyntaxAccepted" : true,
// Whether Orthanc accepts to act as C-Store SCP for unknown storage
// SOP classes (aka. "promiscuous mode")
"UnknownSopClassAccepted" : false,
// **
// Security-related options for the HTTP server
// **
// Whether remote hosts can connect to the HTTP server
"RemoteAccessAllowed" : true,
// Whether or not SSL is enabled
"SslEnabled" : false,
// Path to the SSL certificate (meaningful only if SSL is enabled)
"SslCertificate" : "certificate.pem",
// Whether or not the password protection is enabled
"AuthenticationEnabled" : false,
// The list of the registered users. Because Orthanc uses HTTP
// Basic Authentication, the passwords are stored as plain text.
"RegisteredUsers" : {
// "alice" : "alicePassword"
},
// **
// Network topology
// **
// The list of the known DICOM modalities
"DicomModalities" : {
// **
// * Uncommenting the following line would enable Orthanc to
// * connect to an instance of the "storescp" open-source DICOM
// * store (shipped in the DCMTK distribution) started by the
// * command line "storescp 2000".
// **
// "sample" : [ "STORESCP", "localhost", 2000 ]
"Horos" : [ "HOROS", "192.168.123.200", 104 ],
"dcm4che" : [ "DCM4CHE", "192.168.123.201", 104 ]
// **
// * A fourth parameter is available to enable patches for a
// * specific PACS manufacturer. The allowed values are currently
// * "Generic" (default value), "StoreScp" (storescp tool from
// * DCMTK), "ClearCanvas", "MedInria", "Dcm4Chee", "SyngoVia",
// * "AgfaImpax" (Agfa IMPAX), "EFilm2" (eFilm version 2), and
// * "Vitrea". This parameter is case-sensitive.
// **
// "clearcanvas" : [ "CLEARCANVAS", "192.168.1.1", 104, "ClearCanvas" ]
},
// The list of the known Orthanc peers
"OrthancPeers" : {
// **
// * Each line gives the base URL of an Orthanc peer, possibly
// * followed by the username/password pair (if the password
// * protection is enabled on the peer).
// **
// "peer" : [ "http://localhost:8043/", "alice", "alicePassword" ]
// "peer2" : [ "http://localhost:8044/" ]
"OrthancMac" : [ "http://192.168.123.210:8042/" ]
},
// Parameters of the HTTP proxy to be used by Orthanc. If set to the
// empty string, no HTTP proxy is used. For instance:
// "HttpProxy" : "192.168.0.1:3128"
// "HttpProxy" : "proxyUser:proxyPassword@192.168.0.1:3128"
"HttpProxy" : "",
// Set the timeout for HTTP requests issued by Orthanc (in seconds).
"HttpTimeout" : 10,
// Enable the verification of the peers during HTTPS requests.
// Reference: http://curl.haxx.se/docs/sslcerts.html
"HttpsVerifyPeers" : true,
// Path to the CA (certification authority) certificates to validate
// peers in HTTPS requests. From curl documentation ("--cacert"
// option): "Tells curl to use the specified certificate file to
// verify the peers. The file may contain multiple CA
// certificates. The certificate(s) must be in PEM format."
"HttpsCACertificates" : "",
// **
// Advanced options
// **
// Dictionary of symbolic names for the user-defined metadata. Each
// entry must map an unique string to an unique number between 1024
// and 65535.
"UserMetadata" : {
// "Sample" : 1024
},
// Dictionary of symbolic names for the user-defined types of
// attached files. Each entry must map an unique string to an unique
// number between 1024 and 65535. Optionally, a second argument can
// provided to specify a MIME content type for the attachment.
"UserContentType" : {
// "sample" : 1024
// "sample2" : [ 1025, "application/pdf" ]
},
// Number of seconds without receiving any instance before a
// patient, a study or a series is considered as stable.
"StableAge" : 60,
// By default, Orthanc compares AET (Application Entity Titles) in a
// case-insensitive way. Setting this option to "true" will enable
// case-sensitive matching.
"StrictAetComparison" : false,
// When the following option is "true", the MD5 of the DICOM files
// will be computed and stored in the Orthanc database. This
// information can be used to detect disk corruption, at the price
// of a small performance overhead.
"StoreMD5ForAttachments" : true,
// The maximum number of results for a single C-FIND request at the
// Patient, Study or Series level. Setting this option to "0" means
// no limit.
"LimitFindResults" : 0,
// The maximum number of results for a single C-FIND request at the
// Instance level. Setting this option to "0" means no limit.
"LimitFindInstances" : 0,
// The maximum number of active jobs in the Orthanc scheduler. When
// this limit is reached, the addition of new jobs is blocked until
// some job finishes.
"LimitJobs" : 10,
// If this option is set to "false", Orthanc will not log the
// resources that are exported to other DICOM modalities of Orthanc
// peers in the URI "/exports". This is useful to prevent the index
// to grow indefinitely in auto-routing tasks.
"LogExportedResources" : true,
// Enable or disable HTTP Keep-Alive (deprecated). Set this option
// to "true" only in the case of high HTTP loads.
"KeepAlive" : false,
// If this option is set to "false", Orthanc will run in index-only
// mode. The DICOM files will not be stored on the drive. Note that
// this option might prevent the upgrade to newer versions of Orthanc.
"StoreDicom" : true,
// DICOM associations are kept open as long as new DICOM commands
// are issued. This option sets the number of seconds of inactivity
// to wait before automatically closing a DICOM association. If set
// to 0, the connection is closed immediately.
"DicomAssociationCloseDelay" : 5,
// Maximum number of query/retrieve DICOM requests that are
// maintained by Orthanc. The least recently used requests get
// deleted as new requests are issued.
"QueryRetrieveSize" : 10,
// When handling a C-Find SCP request, setting this flag to "true"
// will enable case-sensitive match for PN value representation
// (such as PatientName). By default, the search is
// case-insensitive, which does not follow the DICOM standard.
"CaseSensitivePN" : false,
// Register a new tag in the dictionary of DICOM tags that are known
// to Orthanc. Each line must contain the tag (formatted as 2
// hexadecimal numbers), the value representation (2 upcase
// characters), a nickname for the tag, possibly the minimum
// multiplicity (> 0 with defaults to 1), and possibly the maximum
// multiplicity (0 means arbitrary multiplicity, defaults to 1).
"Dictionary" : {
// "0014,1020" : [ "DA", "ValidationExpiryDate", 1, 1 ]
}
}
I copied the whole orthancpi directory with an USB card reader to different Raspberry Pi modules which were configured to run as headless servers with remote control, using various wifi adapters. The process is explained in my post Rasperry Pi revisited.
To start the OrthancPi server at boot, a file orthanc.desktop has been added to the /home/pi/.config/autostart/ folder. This is the content of this file
[Desktop Entry]
Type=Application
Name=ORTHANC
Exec=/home/pi/orthancpi/Orthanc /home/pi/orthancpi/configuration.json
StartupNotify=false
OrthancPi can also be configured to run as a Debian daemon.
An OrthancPi server will be used in the context of the RadioLogic project, a training tool for radiology. This tool will be used in classrooms without Internet access. The OrthancPi server works as wireless access point. To extend the WiFi range, a repeater can be used. The RadioLogic tool is web based and optimized to run on iPad’s which are connected to the OrthancPi WLAN. The following figure shows two OrthancPi servers with USB WiFi adapters using Ralink RT5370 chips.
A user guide for the OrthancPi is available at the RadioLogic website. Disk image files to set up an OrthancPi server in a plug and play way, with different WiFi adapters, are available at the same webpage.