How to compile Orthanc from source code on Ubuntu Server 22.04 LTS

Post Reply
User avatar
LHammonds
Site Admin
Site Admin
Posts: 1098
Joined: Fri Jul 31, 2009 6:27 pm
Are you a filthy spam bot?: No
Location: Behind You
Contact:

How to compile Orthanc from source code on Ubuntu Server 22.04 LTS

Post: # 1089Post LHammonds »

Overview

DICOM (Digital Imaging and Communications in Medicine) is the standard for the communication and management of medical imaging information and related data. Orthanc is a standalone DICOM server. It is designed to improve the DICOM flows in hospitals and to support research about the automated analysis of medical images. Orthanc lets its users focus on the content of the DICOM files, hiding the complexity of the DICOM format and of the DICOM protocol.

This article will cover how to get Orthanc installed and running on Ubuntu server and configured to act as a DICOM router to another PACS server.

Here is a diagram of how Orthanc will interact between radiology devices and the PACS server.

Image

Software Used in this Article This article will assume you have an Ubuntu Server setup similar to this tutorial.

Wherever you see RED in this document, you need to substitute it for what your company uses. Use the list below as a template you need to have answered before you continue.
  • Ubuntu Server name: srv-dicom1
  • Ubuntu Server IP address: 192.168.107.58
  • Ubuntu Admin ID: administrator
  • Ubuntu Admin Password: myadminpass
  • Orthanc Admin user: admin
  • Orthanc Admin Password: adminpassword
I also assume the reader knows how to use the VI editor. If not, you will need to beef up your skill set or use a different editor in place of it.
User avatar
LHammonds
Site Admin
Site Admin
Posts: 1098
Joined: Fri Jul 31, 2009 6:27 pm
Are you a filthy spam bot?: No
Location: Behind You
Contact:

Compile and Install Orthanc

Post: # 1104Post LHammonds »

Install Prerequisites

Install the prerequisites (listed in alphabetical order):

Code: Select all

sudo apt install build-essential cmake doxygen libboost-all-dev libcharls-dev libcurl4-openssl-dev libdcmtk-dev libgtest-dev libjpeg-dev libjsoncpp-dev liblua5.4-dev libpng-dev libpugixml-dev libsqlite3-dev libssl-dev libwrap0-dev mercurial uuid-dev zlib1g-dev
The following should already be installed on Ubuntu 22.04:

Code: Select all

unzip
python3
locales
Switch to the root user and create the default location for the source code and build:

Code: Select all

sudo su
mkdir -p ~/Orthanc/Build
mkdir -p ~/Orthanc/OrthancServer/ThirdPartyDownloads
Download Source Code

Get the latest version of Orthanc from its download page (1.11.1 at the time of this writing).

Code: Select all

wget https://www.orthanc-server.com/downloads/get.php?path=/orthanc/Orthanc-1.11.1.tar.gz -O ~/Orthanc/Orthanc.tar.gz
tar -xzvf ~/Orthanc/Orthanc.tar.gz -C ~/Orthanc --strip-components=1
rm ~/Orthanc/Orthanc.tar.gz
cd ~/Orthanc
Optional - After the 1st time you compile (with auto-download enabled), it will download the following files. The next time you compile, it will not have to download them from the Internet. And if you copy them to a fresh server and compile for the 1st time, it will not need to access the Internet if it finds them already there.

Code: Select all

ls ~/Orthanc/OrthancServer/ThirdPartyDownloads/
boost_1_69_0_bcpdigest-1.5.6.tar.gz
civetweb-1.14-fixed.tar.gz
curl-7.77.0.tar.gz
dcmtk-3.6.6.tar.gz
e2fsprogs-1.44.5.tar.gz
jpegsrc.v9c.tar.gz
jsoncpp-1.9.4.tar.gz
libiconv-1.15.tar.gz
libpng-1.6.36.tar.gz
lua-5.3.5.tar.gz
openssl-3.0.1.tar.gz
pugixml-1.9.tar.gz
sqlite-amalgamation-3270100.zip
zlib-1.2.11.tar.gz
Compile Source Code

Compile the source code according to the instructions:

Code: Select all

cd ~/Orthanc/Build
cmake -DSTATIC_BUILD=ON -DALLOW_DOWNLOADS=ON -DUSE_SYSTEM_CIVETWEB=OFF -DUSE_GOOGLE_TEST_DEBIAN_PACKAGE=ON -DDCMTK_LIBRARIES=dcmjpls -DCMAKE_BUILD_TYPE=Release ../OrthancServer/
make
make doc
make install
Code Bug in v1.11.1 Preventing Compile

The "make" command above failed with a "PTHREAD" error until I made the following code changes in each of these files:

Code: Select all

vi ~/Orthanc/Build/boost_1_69_0/boost/thread/pthread/thread_data.hpp
vi ~/Orthanc/Build/ConnectivityChecks-build/boost_1_69_0/boost/thread/pthread/thread_data.hpp
vi ~/Orthanc/Build/DelayedDeletion-build/boost_1_69_0/boost/thread/pthread/thread_data.hpp
Find this on line 60:

Code: Select all

#if PTHREAD_STACK_MIN > 0
Change to this:

Code: Select all

#ifdef PTHREAD_STACK_MIN
Code Reference

Install Destinations

The install copies files to the following locations:

Code: Select all

/usr/local/sbin/Orthanc
/usr/local/share/orthanc/plugins/
/usr/local/bin/OrthancRecoverCompressedFile
/usr/local/share/doc/orthanc/OrthancPlugin/
/usr/local/include/orthanc/OrthancCDatabasePlugin.h
/usr/local/include/orthanc/OrthancCPlugin.h
User avatar
LHammonds
Site Admin
Site Admin
Posts: 1098
Joined: Fri Jul 31, 2009 6:27 pm
Are you a filthy spam bot?: No
Location: Behind You
Contact:

Configuration

Post: # 1105Post LHammonds »

Configuration

The goal I am trying to achieve is an installation very similar to how Orthanc is installed from the Debian repository (apt install orthanc)...but with systemd as the service manager rather than init.d.

Create the Orthanc user and group:

Code: Select all

sudo mkdir -p /var/lib/orthanc/db-v6
sudo useradd --home /var/lib/orthanc --comment 'Orthanc Administrator' --user-group orthanc
sudo chown --recursive orthanc:orthanc /var/lib/orthanc
sudo chmod 775 /var/lib/orthanc
sudo chmod 755 /var/lib/orthanc/db-v6
Once compiled and installed, we now need to generate a default configuration file and folders.

Code: Select all

sudo chown --recursive orthanc:orthanc /usr/local/share/orthanc
sudo mkdir -p /var/log/orthanc
sudo chown orthanc:orthanc /var/log/orthanc
sudo chmod 775 /var/log/orthanc
sudo mkdir -p /etc/orthanc
sudo chown orthanc:orthanc /etc/orthanc
sudo chmod 775 /etc/orthanc
sudo Orthanc --config=/etc/orthanc/orthanc.json
sudo chown orthanc:orthanc /etc/orthanc/*.json
sudo chmod 664 /etc/orthanc/*.json
Edit the configuration file and change the following settings

Code: Select all

sudo vi /etc/orthanc/orthanc.json
"Name" : "srv-dicom1", "StorageDirectory" : "/var/lib/orthanc/db-v6", "IndexDirectory" : "/var/lib/orthanc/db-v6", "Plugins" : [ "/usr/local/share/orthanc/plugins" ], "DicomAet" : "SRVDICOM1", "RemoteAccessAllowed" : true, "AuthenticationEnabled" : true, "RegisteredUsers" : { "admin" : "myadminpass" }, "DicomModalities" : { "pacs" : [ "PACSPROD", "192.168.1.200", 104],
DICOM Router

Now we are going to turn Orthanc into a DICOM router by telling it to forward anything it receives to another PACS server and then immediately delete it from Orthanc.

Code: Select all

sudo touch /etc/orthanc/autoroute-pacs.lua
sudo chown orthanc:orthanc /etc/orthanc/autoroute-pacs.lua
sudo chmod 644 /etc/orthanc/autoroute-pacs.lua
sudo vi /etc/orthanc/autoroute-pacs.lua

Code: Select all

function OnStoredInstance(instanceId, tags, metadata)
  Delete(SendToModality(instanceId, 'pacs'))
end
Now modify the Orthanc configuration:

Code: Select all

sudo vi /etc/orthanc/orthanc.json
Find this:

Code: Select all

  "LuaScripts" : [
  ],
Change it to this:

Code: Select all

  "LuaScripts" : [
    "/etc/orthanc/autoroute-pacs.lua"
  ],
User avatar
LHammonds
Site Admin
Site Admin
Posts: 1098
Joined: Fri Jul 31, 2009 6:27 pm
Are you a filthy spam bot?: No
Location: Behind You
Contact:

Systemd Service

Post: # 1106Post LHammonds »

Systemd Service

Systemd will be used to handle the automatic startup and shutdown of the service when the OS boots up and shuts down which makes it very similar to manage like other services.

Create the service file and set correct ownership / permissions:

Code: Select all

sudo touch /lib/systemd/system/orthanc.service
sudo chown root:root /lib/systemd/system/orthanc.service
sudo chmod 644 /lib/systemd/system/orthanc.service
sudo vi /lib/systemd/system/orthanc.service

Code: Select all

[Unit]
Description=Orthanc DICOM Service
After=network.target
After=network-online.target
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=always
RestartSec=1
User=orthanc
ExecStart=/usr/local/sbin/Orthanc --logdir=/var/log/orthanc/ /etc/orthanc/

[Install]
WantedBy=multi-user.target
Now reload the systemd daemon so it can see the newly created service file.

Code: Select all

sudo systemctl daemon-reload
Enable the service so it starts automatically (which creates a link to /etc/systemd/system)

Code: Select all

sudo systemctl enable orthanc
Start the service and check the log (press CTRL+C to stop the realtime observation of the log):

Code: Select all

sudo systemctl start orthanc
sudo tail -f /var/log/orthanc/Orthanc.log
User avatar
LHammonds
Site Admin
Site Admin
Posts: 1098
Joined: Fri Jul 31, 2009 6:27 pm
Are you a filthy spam bot?: No
Location: Behind You
Contact:

Ubuntu Firewall Rules

Post: # 1107Post LHammonds »

Ubuntu Firewall Rules

Edit the firewall script that was created during the initial setup of the server (if you followed my instructions):

Code: Select all

sudo vi /var/scripts/prod/en-firewall.sh
Add the following lines:

Code: Select all

printf "Adding Orthanc rules\n"
ufw allow proto tcp to any port 8042 comment 'Dicom Web' 1>/dev/null 2>&1
ufw allow proto tcp to any port 4242 comment 'Dicom' 1>/dev/null 2>&1
Run the updated rules:

Code: Select all

sudo /var/scripts/prod/en-firewall.sh
Once activated, you can see the rules using this command:

Code: Select all

sudo ufw status
Example results:

Code: Select all

Status: active

To                         Action      From
--                         ------      ----
22                         ALLOW       192.168.1.0/24          # SSH via LAN
8042/tcp                   ALLOW       Anywhere                # Dicom Web
4242/tcp                   ALLOW       Anywhere                # Dicom
Once Orthanc is running, you will be able to see what ports its listening to and whether or not they are TCP or UDP.

Example:

Code: Select all

lsof -i -P -n | grep orthanc
Orthanc   17839         orthanc    7u  IPv4 138986      0t0  TCP *:4242 (LISTEN)
Orthanc   17839         orthanc    8u  IPv4 138987      0t0  TCP *:8042 (LISTEN)
User avatar
LHammonds
Site Admin
Site Admin
Posts: 1098
Joined: Fri Jul 31, 2009 6:27 pm
Are you a filthy spam bot?: No
Location: Behind You
Contact:

Transcoding to Jpeg2000 Lossless

Post: # 1108Post LHammonds »

Transcoding to Jpeg2000 Lossless

EDIT: This section has been aborted. It turns out that even if I compress the dicom to match the target system, the target system will re-encode no matter what so this would be a waste of time for my server and thus, just need to route the studies untouched.

At my location, our destination PACS system stores all incoming images in Jpeg 2000 lessless format. To help alleviate that extra step and save some time on the transmission of the large images over the wide-area network, Orthanc needs to be configured to handle. With version 1.7.0 and above, it has a built-in method to automatically transcode while injesting.

Our source images from modalities are Implicit VR Little Endian and the UID is 1.2.840.10008.1.2
The target Jpeg 2000 Lossless UID will be 1.2.840.10008.1.2.4.90

Related manual pages: Transcoding of DICOM files, Registry of DICOM UIDs
Regarding UID, the DICOM rule is the following: If using lossless (non-destructive) compression, the SOP Instance UID tag *can* stay the same after transcoding. On the other hand, If using lossy (destructive) compression, the SOP Instance UID tag *must* change (for medical traceability, as the information has changed).
Self Note: Need to find a link to the official rule that the above quote is referencing.

Settings to be applied in the orthanc.json:

Code: Select all

  //** 1.2.840.10008.1.2 = Implicit VR Little Endian (Default)
  //"IngestTranscoding" : "1.2.840.10008.1.2",

  //** 1.2.840.10008.1.2.4.90 = JPEG 2000 Compression (Lossless)
  "IngestTranscoding" : "1.2.840.10008.1.2.4.90",
  "DicomLossyTranscodingQuality" : 100
User avatar
LHammonds
Site Admin
Site Admin
Posts: 1098
Joined: Fri Jul 31, 2009 6:27 pm
Are you a filthy spam bot?: No
Location: Behind You
Contact:

Compile .deb Package

Post: # 1109Post LHammonds »

For a production environment, it might be better to create a .deb install file on a non-production "compiling machine" and transfer that .deb file to the target server and install the .deb file. The main item to consider is that the compiling machine and production server are running the same OS (e.g. Ubuntu Server 22.04 LTS)

Make sure you install the compilation package:

Code: Select all

sudo apt install checkinstall
On the compiling machine, run the below command but substitute your own settings for maintainer and pkgsource. Run this right after the "make" and "make doc" commands.

It will ask you a few questions, answer however you want. I set my description to "Lightweight, RESTful DICOM server for medical imaging"

NOTE: The parenthesis () and greater than > symbol in the command below have to be preceded (escaped) with a backslash \

Code: Select all

cd ~/Orthanc/Build
checkinstall -D --install=no --maintainer="LHammonds" --pkgsource="https://hammondslegacy.com" --pkgname="orthanc-loc" --pkgversion="1.11.1" --pkgrelease="SNAPSHOT" --arch="$(dpkg --print-architecture)" --pkglicense="GPLv3" --requires="adduser,dcmtk,locales,libcivetweb1 \(\>= 1.15\),lsb-base,tzdata,libboost-filesystem1.74.0 \(\>= 1.74.0\),libboost-iostreams1.74.0 \(\>= 1.74.0\),libboost-locale1.74.0 \(\>= 1.74.0\),libboost-regex1.74.0-icu70,libboost-thread1.74.0 \(\>= 1.74.0\),libc6 \(\>= 2.35\),libcurl4 \(\>= 7.81.0\),libdcmtk16 \(\>= 3.6.6\),libgcc-s1 \(\>= 3.3.1\),libjpeg8 \(\>= 8c\),libjsoncpp25 \(\>= 1.9.5\),liblua5.3-0,libpng16-16 \(\>= 1.6.37\),libpugixml1v5 \(\>= 1.12.1\),libsqlite3-0 \(\>= 3.37.2\),libssl3 \(\>= 3.0.2\),libstdc++6 \(\>= 11\),libuuid1 \(\>= 2.37.2\),zlib1g \(\>= 1:1.2.11\)" --provides="orthanc"
NOTE: I copied the requirements from what is listed for Orthanc 1.10.0 in the Official Ubuntu repository (apt show orthanc). They might not be accurate for 1.11.1 but have yet to see where to find that info so I simply set the minimum version to what I see installed on Ubuntu Server 22.04.1 LTS at the time I compiled. The command below is how it looks if you use the exact requirements for 1.10.0 in the Official Ubuntu repository:

checkinstall -D --install=no --maintainer="LHammonds" --pkgsource="https://hammondslegacy.com" --pkgname="orthanc" --pkgversion="1.8.0" --pkgrelease="SNAPSHOT" --arch="$(dpkg --print-architecture)" --pkglicense="GPLv3" --requires="adduser, dcmtk, locales, libcivetweb1 (>= 1.15), lsb-base, tzdata, libboost-filesystem1.74.0 (>= 1.74.0), libboost-iostreams1.74.0 (>= 1.74.0), libboost-locale1.74.0 (>= 1.74.0), libboost-regex1.74.0-icu70, libboost-thread1.74.0 (>= 1.74.0), libc6 (>= 2.34), libcurl4 (>= 7.16.2), libdcmtk16 (>= 3.6.6), libgcc-s1 (>= 3.3.1), libjpeg8 (>= 8c), libjsoncpp25 (>= 1.9.5), liblua5.3-0, libpng16-16 (>= 1.6.2-1), libpugixml1v5 (>= 1.6), libsqlite3-0 (>= 3.7.3), libssl3 (>= 3.0.0~~alpha1), libstdc++6 (>= 11), libuuid1 (>= 2.16), zlib1g (>= 1:1.2.0)" --provides="orthanc"


The end-result file will be something like this:

Code: Select all

-rw-r--r-- 1 root root 9884360 Aug 17 08:31 /root/Orthanc/Build/orthanc-loc_1.11.1-SNAPSHOT_amd64.deb
You can look at the package information with this command:

Code: Select all

dpkg-deb --info ~/Orthanc/Build/orthanc-loc_1.11.1-SNAPSHOT_amd64.deb

Code: Select all

 new Debian package, version 2.0.
 size 9884360 bytes: control archive=558 bytes.
       0 bytes,     0 lines      conffiles
     761 bytes,    10 lines      control
 Package: orthanc-loc
 Priority: extra
 Section: checkinstall
 Installed-Size: 34856
 Maintainer: LHammonds
 Architecture: amd64
 Version: 1.11.1-SNAPSHOT
 Depends: adduser,dcmtk,locales,libcivetweb1 (>= 1.15),lsb-base,tzdata,libboost-filesystem1.74.0 (>= 1.74.0),libboost-iostreams1.74.0 (>= 1.74.0),libboost-locale1.74.0 (>= 1.74.0),libboost-regex1.74.0-icu70,libboost-thread1.74.0 (>= 1.74.0),libc6 (>= 2.35),libcurl4 (>= 7.81.0),libdcmtk16 (>= 3.6.6),libgcc-s1 (>= 3.3.1),libjpeg8 (>= 8c),libjsoncpp25 (>= 1.9.5),liblua5.3-0,libpng16-16 (>= 1.6.37),libpugixml1v5 (>= 1.12.1),libsqlite3-0 (>= 3.37.2),libssl3 (>= 3.0.2),libstdc++6 (>= 11),libuuid1 (>= 2.37.2),zlib1g (>= 1:1.2.11)
 Provides: orthanc
 Description: Lightweight, RESTful DICOM server for medical imaging
Transfer the generated .deb file to the new Orthanc servers.

Code: Select all

scp ~/Orthanc/Build/orthanc-loc_1.11.1-SNAPSHOT_amd64.deb administrator@192.168.1.31:/tmp/.
scp ~/Orthanc/Build/orthanc-loc_1.11.1-SNAPSHOT_amd64.deb administrator@192.168.1.32:/tmp/.
scp ~/Orthanc/Build/orthanc-loc_1.11.1-SNAPSHOT_amd64.deb administrator@192.168.1.33:/tmp/.
On the Orthanc server, install from the .deb package that was copied to it.

Code: Select all

sudo dpkg -i /tmp/orthanc-loc_1.11.1-SNAPSHOT_amd64.deb
It will likely error out saying required dependencies are not installed. Example:

Code: Select all

Selecting previously unselected package orthanc-loc.
(Reading database ... 119619 files and directories currently installed.)
Preparing to unpack .../orthanc-loc_1.11.1-SNAPSHOT_amd64.deb ...
Unpacking orthanc-loc (1.11.1-SNAPSHOT) ...
dpkg: dependency problems prevent configuration of orthanc-loc:
 orthanc-loc depends on dcmtk; however:
  Package dcmtk is not installed.
 orthanc-loc depends on locales; however:
  Package locales is not configured yet.
 orthanc-loc depends on libcivetweb1 (>= 1.15); however:
  Package libcivetweb1 is not installed.
 orthanc-loc depends on libboost-filesystem1.74.0 (>= 1.74.0); however:
  Package libboost-filesystem1.74.0 is not installed.
 orthanc-loc depends on libboost-iostreams1.74.0 (>= 1.74.0); however:
  Package libboost-iostreams1.74.0 is not installed.
 orthanc-loc depends on libboost-locale1.74.0 (>= 1.74.0); however:
  Package libboost-locale1.74.0 is not installed.
 orthanc-loc depends on libboost-regex1.74.0-icu70; however:
  Package libboost-regex1.74.0-icu70 is not installed.
 orthanc-loc depends on libboost-thread1.74.0 (>= 1.74.0); however:
  Package libboost-thread1.74.0 is not installed.
 orthanc-loc depends on libdcmtk16 (>= 3.6.6); however:
  Package libdcmtk16 is not installed.
 orthanc-loc depends on libjsoncpp25 (>= 1.9.5); however:
  Package libjsoncpp25 is not installed.
 orthanc-loc depends on liblua5.3-0; however:
  Package liblua5.3-0 is not installed.
 orthanc-loc depends on libpugixml1v5 (>= 1.12.1); however:
  Package libpugixml1v5 is not installed.

dpkg: error processing package orthanc-loc (--install):
 dependency problems - leaving unconfigured
Errors were encountered while processing:
 orthanc-loc
After trying to install the .deb package, you can now run this command which will install the required packages and then install Orthanc:

Code: Select all

sudo apt -f install
Once the package is installed, you will need to finish the following sections above to complete the installation:
* Configuration
* Systemd Service
* Ubuntu Firewall Rules

You can see the destination folder (and files) by looking at the contents inside the .deb file with this command:

Code: Select all

sudo dpkg-deb --contents /tmp/orthanc-loc_1.11.1-SNAPSHOT_amd64.deb
It is the same destination locations as if compiled on this machine:

Code: Select all

/usr/local/sbin/Orthanc
/usr/local/share/orthanc/plugins/
/usr/local/bin/OrthancRecoverCompressedFile
/usr/local/share/doc/orthanc/OrthancPlugin/
/usr/local/include/orthanc/OrthancCDatabasePlugin.h
/usr/local/include/orthanc/OrthancCPlugin.h
To remove the manually installed package (such as prior to installing a newer version):

Code: Select all

sudo dpkg -r orthanc-loc
Normally, you remove configuration files like this:

Code: Select all

sudo dpkg --purge orthanc-loc
But the installer did not create any configuration files so you will need to manually remove the changes made after installing the .deb package....such as going through the following sections to reverse / delete changes made:
* Configuration
* Systemd Service
* Ubuntu Firewall Rules
Post Reply