0% found this document useful (0 votes)
859 views155 pages

MedDream DICOM Viewer Install Manual - 2

meddream

Uploaded by

Ramesh Koheda
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
859 views155 pages

MedDream DICOM Viewer Install Manual - 2

meddream

Uploaded by

Ramesh Koheda
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 155

UAB Softneta

K. Barsausko st. 59, LT 51423


Kaunas, Lithuania
[email protected]
www.softneta.com

MedDream (version 8.3.1)

Install manual of Viewing functionalities

(version 8.3.1, 2023-12-15)


© 2023, Softneta UAB, Kaunas
All rights reserved in the event of granting of patents or registration as a utility patent.
All names of companies and products mentioned in this manual may be trademarks or registered trademarks.
References to products of other manufacturers are for information purposes only. Such references are intended
neither as an approval nor a recommendation of these products. Softneta UAB accepts no liability for the
performance or use of such products.
Other brand names, software and hardware names used in this manual are subject to trademark or patent
protection. The quoting of products is for informational purposes only and does not represent a trademark misuse.
This Install Manual is protected by copyright. Unless expressly authorized in writing, dissemination, duplication
or other commercial exploitation of this documentation set or communication of its contents or parts of it is not
permitted. In case of infringement, the violator may be liable to pay compensation for damages.
Specifications due to technical developments are subject to change. This Install Manual is not subject to the
revision service. Please contact the manufacturer or authorized dealer to request the latest edition of Install
Manual.
i

Table of Contents
1 Introduction 1
1.1 Installation prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

2 Requirements 2
2.1 Server-side requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.1.1 Minimal hardware requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.1.2 Software requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1.3 Time synchronization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1.4 Licensing (Linux) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Client-side requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.3 Decommissioning of MedDream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

3 Integration with PACS 5


3.1 Integration modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.1.1 Direct access mode on a different host . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.1.2 Saving measurements, Key Objects, segmentations and screenshots . . . . . . . . . . . . 6
3.1.3 Multiple PACSes in parallel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2 Direct access to PACS database mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2.1 PacsOne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2.2 DCM4CHEE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.2.3 ClearCanvas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.2.4 Conquest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.3 Integration over Web or other APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.3.1 Orthanc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.3.2 DICOMweb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.3.3 Amazon S3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.4 DICOM mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.4.1 DICOM mode notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.4.2 MedDream configuration for DICOM mode . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.5 File system access mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.5.1 File system mode notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.5.2 MedDream configuration for File system mode . . . . . . . . . . . . . . . . . . . . . . . . 52
3.6 Non-DICOM file system mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.6.1 Non-DICOM mode notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.6.2 MedDream configuration for Non-DICOM file system mode . . . . . . . . . . . . . . . . . 54

4 Image Access from hospital information system (HIS) 55

5 Deployment 57
5.1 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.1.1 Essential configuration and the first run . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.1.2 System.json . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5.1.3 Built-in authentication and authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
5.1.4 Predefined login credentials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
5.1.5 The Reporting function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
5.1.6 Adjusting Java memory limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
5.1.7 Enabling SSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
5.1.8 The external links plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
5.1.9 Reference for remaining configuration parameters . . . . . . . . . . . . . . . . . . . . . . 83
5.1.10 Opening the H2 Console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
5.1.11 Using MySQL for Spring Batch and Quartz Scheduler . . . . . . . . . . . . . . . . . . . . 105
5.1.12 Changing the HTTP context path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
5.1.13 Adjusting a reverse proxy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
5.1.14 Caching studies via DICOM Listener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
5.1.15 Monitoring via Prometheus/Grafana . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


ii

5.1.16 Implementing per-user settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109


5.1.17 Custom columns in Patient History / Patient Studies . . . . . . . . . . . . . . . . . . . . . 110
5.1.18 Passing configuration via environment variables . . . . . . . . . . . . . . . . . . . . . . . . 113
5.1.19 Setting up Azure SSO with SAML 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
5.1.20 Setting up Keycloak SSO with SAML 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
5.1.21 Avoiding service restart after some configuration changes . . . . . . . . . . . . . . . . . . 116
5.2 Running as a service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
5.2.1 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
5.2.2 Linux (System-V init) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
5.2.3 Linux (systemd) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
5.2.4 Linux (upstart) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
5.3 Verification checklist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
5.4 Option: dockerized environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
5.5 Updating the license . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
5.6 Cleaning server-side caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
5.7 Creating a dump of an H2 database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
5.8 Restoring an H2 database from a dump . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
5.9 Using strong passwords in MySQL accounts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

6 Additional software 124


6.1 Browser plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
6.2 Writing an ISO file to a USB stick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
6.3 Alternative to MedDreamBurn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

7 Security considerations 125


7.1 Default passwords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
7.2 Search engines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
7.3 DCM4CHEE 2.x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
7.4 Embedding into IFRAME etc. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
7.5 php.ini . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
7.6 Browser’s cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
7.7 Firewalls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
7.8 Summary: Minimum relevant IT security requirements . . . . . . . . . . . . . . . . . . . . . . . . . 131

8 Localization 133

9 Rebranding 133
9.1 Changing the progress bar color . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

10 Troubleshooting 137
10.1 Preventive measures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
10.2 Antivirus software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
10.3 Log files of the Java-based core . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
10.4 Video conversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
10.5 Client side: browser download path selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
10.5.1 Google Chrome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
10.5.2 Mozilla Firefox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
10.5.3 Microsoft Edge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
10.5.4 Safari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
10.6 Client side: enabling clipboard operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
10.7 Client side: monitor calibration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
10.8 Symptom: on Linux the loading pauses just after logging in, possibly with wrong webpage colors . 142
10.9 Symptom: queries to MS SQL Server take seconds from Java but milliseconds from Management
Studio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
10.10Symptom: video not playable on Firefox under Windows . . . . . . . . . . . . . . . . . . . . . . . . 142
10.11Known limitations and their solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
10.11.1 Share functionality skips some objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

A Appendix: Configuration changes since 8.3.0 144

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


iii

A.1 application.properties, generic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144


A.1.1 Options that are handled differently . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
A.1.2 New options or values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
A.2 application.properties, PacsOne plugin 6.4.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
A.2.1 New options or values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

B Appendix: Upgrading 8.3.0 to 8.3.1 (Linux) 146

C Appendix: Upgrading 8.3.0 to 8.3.1 (Windows) 148

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


ii

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


1

1. Introduction
MedDream Viewer functionality (called “MedDream DICOM Viewer” later in this Manual) is a HTML based
package for PACS server which is designed to aid professionals in every day’s decision-making process,
connecting all the medical data into a unified and fast performing network. MedDream ensures a fast and reliable
way to search, present and analyze the medical data (images and video files) on various devices: computers,
smart phones, tablets and so forth.
MedDream covers: radiology, cardiology, oncology, gastroenterology and many other fields of medical
application. It seamlessly integrates with various medical imaging devices, such as: ultrasound (US),
magnetic resonance (MRI), positron emission tomography (PET), computed tomography (CT), endoscopy (ES),
mammography (MG), digital radiography (DR), computed radiography (CR), ophthalmology and so forth.
Core MedDream DICOM Viewer uses are:
• Replacement of hard copies, e.g., film archives, paper documents, etc.
• Remote access. MedDream provides a possibility to be mobile and work from any place in the world where
the Internet is accessible. More than one person can access and view medical records at one time. Such
functionality speeds up the collaboration among the professionals. So that a doctor in the hospital and a
doctor that is in a different location may view the medical data and discuss about it simultaneously. The
patient’s medical history, various studies and images are found much faster comparing to the conventional
paper-based methods.
• MedDream can be used as a standalone WEB Viewer or integrated into MedDream PACS, PacsOne
PACS, dcm4chee Archive, Conquest, ClearCanvas, Orthanc PACS systems. Moreover, MedDream can be
adapted to client’s PACS system and easily integrated into RIS/HIS workflow.
• MedDream has multiple functions such as search of studies, viewing, analyzing, saving, exporting,
forwarding images and videos, etc.
MedDream is dedicated only to show ePHI (Electronic protected health information) contained in study file.
Administrators, doctors and patients decide how to use ePHI.

Note: Softneta does not keep Electronic Protected Health Information (ePHI).

1.1. Installation prerequisites

Make sure the server conforms to the Server-side requirements in the next chapter.
Most installation tasks will require administrative rights on the server (for example, setup of a system service or
adjustment of file system permissions).
Before integrating with a particular system, read the corresponding part of the 3 Integration with PACS chapter
first. That way you’ll know in advance what integration-specific data or cooperation is needed from administrators
of that system. For example, direct integrations will require suitable database credentials, while Query/Retrieve
even requires to configure the PACS accordingly.

Warning: If you are updating to a newer version of MedDream or are applying a “patch” / “hotfix”, please
make a backup of the existing installation. Under Linux this also includes the related system services –
usually not in MedDream directory but elsewhere (depends on distribution).

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


2

Warning: When copying large multi-line examples of configuration or shell commands from this document,
pay attention to the typesetting symbols and , like here:
java -XX:MaxRAMPercentage=50.0 -DANTLR_USE_DIRECT_CLASS_LOADING=true -cp␣
˓→MedDream-8.1.0.jar org.springframework.boot.loader.PropertiesLauncher

After copying you need to 1) manually join the lines and remove characters that represent and , 2) add
a space where was present.
Unfortunately, broken lines with line continuation characters \ are not supported by all target environments;
for example, they are OK in Linux shells but not in Windows Command Prompt or PowerShell.

2. Requirements
2.1. Server-side requirements

2.1.1. Minimal hardware requirements

Concurrent connections CPU cores* RAM**


1 connection 4 cores 8 GB
2 connections 4 cores 8 GB
5 connections 4 cores 8 GB
10 connections 4 cores 12 GB
20 connections 6 cores 16 GB
30 connections 8 cores 32 GB
60 connections 16 cores 32 GB
60+ connections +1 core per 10 connections +1 GB per 5 connections

* Equivalent of 5th generation Intel i5 2GHz CPU core (Q1’15 or later).


** Additional RAM must be reserved for OS, Database, PACS and/or other services if installed in the same
machine.
The storage is used for software (fixed 1 GB size) and temporary data cache. Performance of the caching
storage directly affects image open speed, therefore SSD, RAM or high-speed disk storage is recommended for
it.

Note: It is recommended to allocate the fastest disk storage, with free space for 10 days worth of new
studies, for the MedDream cache in order to have a better viewing performance.

The network bandwidth will directly affect image open speed. At least 100 Mbit/s is recommended.

Note: Minimal hardware requirements depend on number of concurrent users, workload and image types. It is
recommended to allocate 20-80% more resources for unusual workload or specific data types.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


3

2.1.2. Software requirements

For security-related configuration, see 7.8 Summary: Minimum relevant IT security requirements.
The MySQL client library does not support server versions below 5.7. This includes any integrations or
authentication mechanisms based on MySQL, and the MySQL variant of reports/attachments storage.

2.1.2.1. Recommended operating systems

We recommend the following operating systems on server side:


• Windows Server 2019, Windows Server 2022
• Windows 10, Windows 11 (64-bit only) and above
• Linux: Debian 12, Ubuntu 20.04 LTS, CentOS 7.9-2009, Fedora 37. The minimum glibc version is 2.15 for
x86_64 and 2.27 for aarch64.

2.1.2.2. Java

MedDream is a Java-based application and requires a JRE. Currently supported Java runtime is Java 17 LTS.
We recommend builds from adoptium.net.
The build must be 64-bit, as under 32-bit builds most kinds of DICOM images will not be displayed.

2.1.2.3. FFmpeg

A 64-bit build of FFmpeg for Windows is included in the installation archive and used automatically on this
platform; a different path can be specified during installation.
In other cases, including Linux, FFmpeg must be installed separately.

2.1.3. Time synchronization

The system time needs to be reasonably accurate – for example, within one minute.
MedDream is designed as a single unprivileged application and therefore does not include means of updating
the system time. The time should be synchronized by the operating system instead. It is a responsibility of
the system administrator to set up a network time client and monitor its behavior.
A correct system date is important for adequate behavior of MedDream (the license might contain date-based
limits) and other parts of the infrastructure. Some network time clients even refuse to work when the date is off
by a too large amount.

2.1.4. Licensing (Linux)

Under Linux, the most popular form of MedDream license is bound to host name and MAC addresses of network
adapters. The hardware (or virtualization) solution must ensure that they are constant. Using this license in a
Docker container might be impossible unless the MAC is fixed via the --mac-address option of docker run.
Normally dockerized installations, especially cloud-based, imply that an Internet connection is available. For
those we offer a different kind of license that periodically queries our server (lic.softneta.com).

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


4

2.2. Client-side requirements

. Desktop Web Mobile iOS Web Mobile Android


Web
CPU Intel i3 4 core CPU or better — —
RAM* 8+ GB of RAM, 256+ MB of video memory 2+ GB 2+ GB
Storage space 10+ GB 2+ GB 2+ GB
Network 100+ Mbit/s 100+ Mbit/s 100+ Mbit/s
bandwidth**
Web Browsers Chrome 118+, Firefox 118+, Safari 16+, Safari 16+, Chrome 118+,
Microsoft Edge 118+ Chrome 118+ Firefox 118+

* for CT, MRI, PET-CT client side MPR/MIP rendering:


• 64bit CPU and 64 bit operating system;
• graphic board with >=1 GB video memory (hardware acceleration enabled in the browser);
• 12 GB of RAM to open more than 800 images;
• 16 GB of RAM to open more than 1500 images;
• 24 GB of RAM to open more than 3000 images (cardiac or functional imaging, MG Tomosynthesis).
* for MG Mammography:
• 64-bit CPU and 64 bit operating system;
• graphic board with >=1 GB video memory (hardware acceleration enabled in the browser);
• 16 GB of RAM.
* for MG Tomosynthesis:
• 64-bit CPU and 64 bit operating system;
• graphic board with >=1 GB video memory (hardware acceleration enabled in the browser);
• 16 GB of RAM.
* Depending on the total amount of RAM on user’s workstation, the browser is allowed to allocate the restricted
amount of memory, and therefore MedDream application may load not more than 16 GBytes of data. Due
to these limitations, browser may run out of memory, if the user loads several large computed tomography,
mammography or tomosynthesis studies.
** Network bandwidth will directly affect image open speed.

Note: Hardware acceleration should be enabled in web browser for better performance.

Note: MedDream enables users to view all data stored with a bit depth of up to 16 bits per color channel.
However, it displays 8 bits per color channel at a time due to web browser limitations (maximum display of 256
values per color channel). You can utilize the Window leveling tool to explore the entire data range within the
images.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


5

2.3. Decommissioning of MedDream

Note: A particular version of MedDream is supported for a limited time (see the Info window or User Manual).
When support is no longer provided, we strongly recommend to update to a supported version. Be aware that
the customer is responsible for outcome (including, but not limited to, personal data protection) from operating a
not supported version. Not supported software versions are used on customer’s own risk.

3. Integration with PACS


Support for various PACSes is implemented in form of plugins. Their .jar files are expected in the same directory,
sys/plugins.
They have no version numbers in the name in order to prevent hard-to-troubleshoot situations where multiple
versions of the same plugin are present. Currently, if there is a need to know the version number of the plugin,
then one can open the JAR file as a ZIP file and look for file META-INF/MANIFEST.MF; it will contain, among
other things, the Bundle-Version property.

Bundle-Version: 2.0.10.SNAPSHOT

Warning: Do not mix plugins from different MedDream versions. There is no backwards-compatibility.
Ideally the entire backend will crash immediately (during start) if there is even one incompatible plugin left
in sys/plugins directory. Note that plugins are loaded even if not referenced in application.properties: that
configuration only allows to use them afterwards. In the worst case some unpredictable behavior will happen
later during use.

3.1. Integration modes

MedDream can access studies from PACS using:


• Direct access to PACS database (PacsOne, DCM4CHEE, ClearCanvas, Conquest, etc).
• Web-based and other APIs (Orthanc, DICOMweb).
• DICOM 3.0 native interface (Query/Retrieve).
• Direct file system access where a PACS is not necessary. (However, for users’ convenience some third-
party user interface will still need to pass file/directory names to MedDream.)
Commercial integration solutions are also possible on request. In that case documentation with confidential
information will be available as separate versions of this Manual.
For best performance, it is recommended to use direct access to PACS database whenever available.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


6

3.1.1. Direct access mode on a different host

Warning: In the Direct access to PACS database mode, MedDream must either:
• be installed on the same host as PACS, or
• have access to studies’ files, and likely path remapping needs to be configured.

Some databases contain paths to DICOM files stored on the PACS host (not on some common network storage,
etc.) and it is not always possible to create identical mount points or network drive letters on the MedDream
host.
For this case most PACS plugins support the setting mappedStorageLocation (or with similar name) that
specifies substrings in the path to be replaced with different substrings.
An example with PacsOne plugin: ...].mappedStorageLocation=/volume1/DICOMNL\=O:\|/volume2/
DICOMNL\=P:\. Here /volume1/DICOMNL\ is replaced with O:\ under which the network resource shared by
a Linux system is mounted on a Windows system; in the same fashion /volume2/DICOMNL\ is replaced with P:\.
For best results, please take a look at Java logs for original paths.
Due to limitations of Windows, a service might fail to access a network drive mapped in an interactive session
(even under the same user, even with the “Enable to interact with desktop” turned on). In this case, avoiding a
drive letter should give better results – just remap PACS-local directories to CIFS paths that would otherwise be
attached to a drive letter (...].mappedStorageLocation=/volume1/DICOMNL\=\\server\share\DICOMNL/).

Note: In case of some transient database connection problems, PacsOne saves the received file not under
the configured short-term directory but under /var (Linux) or C:\ (Windows). This results in paths like C:\
2022-04-06-WED\... that will not be accessible from another machine by default. As sharing the entire directory,
even with restrictive file system permissions, is not desired due to security considerations, you should be able
to work around by sharing and remapping particular per-day directories: C:\2022-04-06-WED –> \\server\
anotherShare\2022-04-06-WED etc. This is a recommended temporary solution when doctors need a particular
study up quickly.
A script for easier moving of these files to the intended location is not available yet. To avoid this situation until a
new PacsOne version fixes its behavior, make sure PacsOne is also restarted after restarting MySQL, especially
when it’s on a different host; in particular, always stop the PacsOne service during any MySQL maintenance.

3.1.2. Saving measurements, Key Objects, segmentations and screenshots

To save Key Objects, Presentation States (measurements), segmentations and secondary capture screenshots,
the following parameters must be added to the configuration of every PACS integration plugin:
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].storeScpIp=127.0.
0.1
IP address (or hostname) of the Storage Server.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].storeScpPort=104
Storage Server Port.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
storeScpAet=PACSONE
Storage Server AE Title.
The local AE Title is configured globally by com.softneta.meddream.dcmsnd.bind as before (default value is
MEDDREAM). The PACS must be configured to accept C-STORE sessions from this AE Title.
Since 7.9, every plugin can have a distinct local AE title:

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


7

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
storeScuAet=UPLOADER
If this parameter is commented out or empty, then the global value is used.
All four parameters mentioned above are needed for the Query/Retrieve plugin, too, unless it also has
storageApiEnabled=true; in that case, plugin’s own parameters remoteAET, remoteHost, remotePort and
localAET are used instead.

3.1.3. Multiple PACSes in parallel

With most plugins multiple PACSes can be defined simultaneously, then used in the Search window to open
studies (also called “Multi-PACS setup”).

Warning: Opening the same study from different PACSes at the same time is not fully supported. In
particular, the Viewer window doesn’t indicate from which PACS a particular study is opened. This will lead
to confusion, especially in case of different versions of the study (for example, an additional series from a
workstation is present or not).

3.2. Direct access to PACS database mode

3.2.1. PacsOne

In case of PacsOne Server (http://pacsone.net/), MedDream implements direct database access mode.
A similar configuration called “Standard DB integration” uses the same plugin and a minimalistic database
structure unrelated to the real PacsOne Server; the database is to be filled by a custom solution implemented
by the customer. Please contact [email protected] for example scripts etc.

Note: “Standard DB integration” doesn’t support saving of annotations and screenshots by itself, the whole
solution is read-only with respect to database and file system. Some customer’s solution is needed to receive
the objects over DICOM C-STORE and update database/files accordingly. The DICOM C-STORE is the only
upload mechanism available at the moment.

Since 8.3.1 MedDream supports downloading of DICOM files that have been stored on AWS S3, including
PacsOne’s long-term storage. Gzip encoding applied by server is transparently removed.

3.2.1.1. PacsOne notes

Note: applet.php for MedDream is not included in the installation archive any more. To obtain it, please
contact [email protected].

applet.php is regularly tested with PHP versions from 5.4 to 7.1, though newer ones might also work. It requires
the php_curl PHP module.

Warning: PacsOne and mD Java Core processes must run as the same user because newer versions of
PacsOne create subdirectories with permissions too strict for different users. Please ensure that on Linux
operating systems PacsOne and mD Core services use the same user or belong to the same group.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


8

Warning: PacsOne must store the received DICOM files in the “DicomPart10” format. The other format,
“Native”, is not fully supported by MedDream (and you might have problems with other DICOM-related
software). This setting is chosen during installation and later can be verified as follows:
• Windows: in the registry, REG_SZ StorageFormat under HKEY_LOCAL_MACHINE\SOFTWARE\
RainbowFish Software\PacsOne\${AeTitle};
• Linux: the setting StorageFormat in file(s) *.ini near PacsOne.exe.

PacsOne doesn’t have an index on series.modality. If searches with a particular modality are unacceptably slow
compared to the “All” choice, then you’ll need to use the following MySQL command:

ALTER TABLE series ADD INDEX (modality);

Until 6.0, the HIS integration by Patient ID was using a certain kind of fuzzy matching that includes coerced values
of Patient ID. For example, /?patient=12345 will also list studies with Patient ID “12345[some_original_value]”.
Since 6.0 this is turned off by default. If you still need the legacy behavior, then configure the “PacsOne” plugin
with strictSearchIsEnabled=false. This also changes the Patient History window.
Since MySQL 5.7, the ONLY_FULL_GROUP_BY mode is on by default. Consequently, MedDream’s Search
function uses a compatible and much slower query by default. If performance is paramount, we advise to disable
ONLY_FULL_GROUP_BY and configure the “PacsOne” plugin with useModalityAggregation=false.
The new Reporting function is incompatible with PacsOne’s “studynotes” and “attachment” tables. It is no more
possible to use PacsOne for accessing reports created in MedDream, and vice versa.

3.2.1.2. MedDream configuration for PacsOne

1. Perform steps in the 5.1.1 Essential configuration and the first run chapter.
2. If you intend to reuse PacsOne user management, then configure this kind of authentication in
application.properties file:

spring.profiles.include=auth-pacsone
authorization.defaultLoginPermissions=SEARCH,PATIENT_HISTORY,\
UPLOAD_DICOM_LIBRARY
#authorization.users[0].userName=user1
#authorization.users[0].role=DOCUMENT_VIEW,BOUNDING_BOX_EDIT
#authorization.users[0].accessibleStorages=st1,st2
authorization.remapRoles.Doctors=SMART_DRAW_EDIT
authentication.database.databaseName=DB_NAME
authentication.database.jdbcUrl=jdbc:mysql://DB_HOST:DB_PORT/DB_NAME

(for example, jdbc:mysql://127.0.0.1:3306/${authentication.database.databaseName} –


we encourage placeholders to minimize human errors).
The defaultLoginPermissions setting globally covers permissions not available in PacsOne user
management. Also please remember that PacsOne’s “Export” privilege is mapped to both
EXPORT_ISO and EXPORT_ARCH. The users[] setting can apply permissions to individual
users.
In 8.4+ you can also use authorization.remapRoles.* to assign additional permissions to a
particular group created in PacsOne GUI (“Doctors” in this example). User’s membership in a
group like this is supported only for remapRoles; MedDream will ignore PacsOne privileges
assigned to the group, it still reads only privileges of that user.
Every user will automatically have either REPORT_VIEW or REPORT_UPLOAD permission,
depending on the PacsOne “upload” privilege. It is not possible to have users without access to
Reporting.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


9

A different authentication method can still be configured according to 5.1.3 Built-in authentication
and authorization.

Note: By default, application.SAMPLE.properties enables auth-inmemory and this is done on


another line. There is no error message if you assign to spring.profiles.include multiple times,
and the outcome might be counter-intuitive. Make sure to comment the unneeded line out.

3. Edit application.properties file and update the options related to PacsOne plugin. The documentation
below is for plugin version 6.4.0.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].type=PacsOne
Use this specific value of type when connecting to PacsOne.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
id=PacsOneRouter
Identifies the plugin/configuration pair in the search window drop-down menu. You can
connect to multiple PacsOne instances by using different values of id and remaining options.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchApiEnabled=true
(optional) Specifies if this plugin/configuration pair returns a study list for the Search window
and provides study metadata. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
imageApiEnabled=true
(optional) Specifies if this plugin/configuration pair retrieves image data. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
forwardApiEnabled=false
(optional) Specifies if PacsOne-specific Forward functionality in the plugin is to be used.
Default is false: MedDream itself reads DICOM files via the plugin (the same way as when
displaying images) and sends them to the recipient, using the same C-STORE client as for
sending new PR/KO objects.
With true, MedDream only creates a forwarding job that is handled by the PacsOne server;
as a result, studies are sent by the PACS service (often on a separate machine). A
single plugin must be configured. A related setting, com.softneta.meddream.dcmsnd.
forwardingMethod=plugin, is required. Database tables “dbjob” and “journal” must be
writeable by the MySQL user identified by username and password below.
In both cases the list of forward destinations is taken from system.json; fetching destinations
from PacsOne database is not supported.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
eventApiEnabled=true
(optional) Specifies if this plugin/configuration pair implements “Clear cache” functionality.
Default is true if dicomCacheDirectory is not empty, and vice versa.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
url=jdbc:mysql://127.0.0.1:3306/PACS_DB_NAME
JDBC connection string. Please note that Oracle is not supported (PacsOne Server for
MySQL is the only supported version).

Note: SSL requirements can be disabled by adding the following arguments:


– verifyServerCertificate=false Disables server certificate verification.
– useSSL=false Disables SSL usage.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


10

– requireSSL=false Disables the SSL requirement.

The plugin also supports PostgreSQL (jdbc:postgresql://127.0.0.1:5432/DB_NAME),


Microsoft SQL Server (jdbc:sqlserver://127.0.0.1:1433;database=DB_NAME) and IBM
DB2 (jdbc:db2://<HOST>:<PORT>/<DATABASE_NAME>:defaultSchema=<SCHEMA>;) for the
“Standard DB integration” cases.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
username=UserName
Username for connecting to the database.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
password=UserPassword
Password for connecting to the database.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
mappedStorageLocation=D:/DICOM=Y:\\DICOM1|E:/DICOM=Y:\\DICOM2
(optional) Defines replacement paths for MedDream installed on a different host than the
PACS and accessing images through mapped network drives.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
useModalityAggregation=true
(optional) Defines if modalities will be aggregated in database query results. Aggregation
ensures that all modalities are visible in the Modality column but this could cause performance
degradation compared to older PHP-based MedDream versions. If set to false, then SQL
mode must not contain ONLY_FULL_GROUP_BY. More information about SQL mode can be
found at: https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html.
true is incompatible with Microsoft SQL Server (“Standard DB integration”) and will result in
errors.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
strictSearchIsEnabled=
(optional) true forces exact matching by Patient ID and Accession Number everywhere,
including the Search window. false forces wildcard matching everywhere, including HIS
integration by Patient ID or Accession Number, and the Patient History window.
null or unset is the default. Before 8.0.0 this meant exact matching for Patient History and
HIS integration, wildcard matching for Search window. Starting from 8.0.0, HIS integration
scenarios by Patient ID use a query origid = <value> OR origid LIKE <value>[%. It
will match both exact Patient ID and its typical coerced version, for example “PAT001” and
“PAT001[SENDERAE-123456]”. An exact match now requires true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
strictUserAetIsEnabled=true
(optional) If true, the user will see only studies from assigned AEs (in PacsOne GUI, see
“Assign Dicom Studies Received From This AE To Web Users” under configuration of a
particular AE).
The user identity is taken from the Login page. The HIS integration scenario with a non-empty
“user.id” in the token was not tested, while the unsafe URL integration won’t benefit from this
filter due to the same user identity (authentication.his.username).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
defaultStartDate=20181107
(optional) Default “from” date in YYYYMMDD format when empty in the user interface.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
defaultEndDate=20181108

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


11

(optional) Default “to” date in YYYYMMDD format when empty in the user interface.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomCacheDirectory=${com.softneta.meddream.tempDir}/dcm/amz1
(optional) A cache directory for files downloaded from AWS S3. Not configured by default,
therefore subsequent access will be slower and will waste AWS traffic.
A cached file is reused forever, there is no support for If-Modified-Since semantics. You’ll
need to set up a separate entry under com.softneta.temp-cleaner.tempItems[] (see
Temporary files cleaner ).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
awsS3Marker=aws_s3
(optional) A magic value that indicates an S3 path instead of a local filesystem path. The
default value is aws_s3, likely hardcoded in PacsOne.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
awsS3Separator=:
(optional) The character that separates awsS3Marker from the remaining path. The default
value is :, likely hardcoded in PacsOne.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
awsS3ConnectionInfoCacheTimeInSec=600
(optional) AWS S3 bucket and region identifiers extracted from the database will be reused
for this many seconds (600 by default).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
encoding=ISO-8859-1
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
encodingTo=ISO-8859-8
(optional) Specify encoding of database strings when it’s not UTF-8.
– encoding=ISO-8859-1, encodingTo=:

* search query is converted from UTF-8 to ISO-8859-1


* search results are converted from ISO-8859-1 to UTF-8
– encoding=ISO-8859-1, encodingTo=ISO-8859-8:

* search results are converted from ISO-8859-1 to ISO-8859-8


* search query is converted from ISO-8859-8 to ISO-8859-1
– encoding=, encodingTo=ISO-8859-8:

* search results are converted from UTF-8 to ISO-8859-8


* search query is converted from ISO-8859-8 to UTF-8
encoding and encodingTo are empty: UTF-8 is assumed everywhere (the outcome might
still be influenced by JVM system encoding).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomPersonName=false
(experimental) Since 8.0.0 plugins are expected to return the full DICOM-formatted patient
name, like “last^first^middle^prefix^suffix=ideographic=phonetic”, for proper reformatting in
Core (also see personNameConfiguration in system.json.) false turns this off and is
normally not required.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
optimized=true

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


12

(experimental) Use different queries for better performance when the database has been
optimized accordingly (see 3.2.1.4 Optimizing the database (MySQL/MariaDB)).
4. Restart Core for changes to take effect, and navigate to http://127.0.0.1/. Use login credentials
that are valid for chosen method (for example, PacsOne users in case of spring.profiles.
include=auth-pacsone).

3.2.1.3. Integration into PacsOne web interface

After you successfully log into MedDream and are able to access studies on PacsOne, the system can
additionally be configured to open MedDream from PacsOne web interface.

Warning: All users of PacsOne will have the same set of MedDream permissions, configurable in
USER_PRIVILEGES (applet.php) or by authorization.defaultHisPermissions (application.properties). If
some users must not have access to, say, Forward or Reporting, then this restriction is necessary for
everyone.

1. Extract the directory “token-service” from installation archive into a separate directory on the server
(example result: /opt/token-service/token-service.xml). From now on it will be called the installation
directory of the Token Service.
2. Make a backup of PacsOne’s php/applet.php.
3. Copy and Replace MedDream’s applet.php over the PacsOne version of the file.
4. Verify whether MEDDREAM_URL, and especially MEDDREAM_STORAGE_ID, at the beginning are correct.
SSO_VALIDATOR_URL will need correction, too, if the Token Service is configured with a different port
(server.port in its own application.properties).
• If you added MedDream to a legacy PacsOne installation and Apache is proxying it as /meddream,
then MEDDREAM_URL is good already.
• If MedDream is running on a different port without proxying, then MEDDREAM_URL can include the
full address, like //localhost:8080/.
• If you are using MedDreamPACS, which offers MedDream at / and the PACS web interface at /Pacs,
then just use / for MEDDREAM_URL.
5. Start the Token Service from a separate console window: change to its installation directory, then run java
-jar token-service.jar. Wait until the message “Application . . . started” appears.
6. In the PacsOne web interface, find some studies, tick at least one checkbox and click the “Show” button.

Note: Default values of security.frameOptionsPolicy and security.contentSecurityPolicy disallow


embedding MedDream in an IFRAME, which is used by applet.php. The browser is refusing to display the
embedded viewer and its console shows an error.
The quickest initial solution is to disable both in MedDream’s application.properties:

security.frameOptionsPolicy=NONE

Afterwards you can experiment with security.frameOptionsPolicy=ALLOW-FROM and security.


frameOptionsWhitelist=<server IP address or hostname>.
The Token Service has its own application.properties, not relevant to this issue.

Note: The “Show” button will appear on patient, study, series and image levels, however MedDream 7.5+
supports the study level only and PacsOne doesn’t allow to hide the button selectively.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


13

For later convenience the token validator should run as a service. The installation directory already provides
helper files token-service.debian, token-service.redhat, token-service.xml, token-service-jar-wrapper.*, token-
service.NET?.exe, a separate version of application.properties. Please follow the 5.2 Running as a service
chapter and do not forget to use the corresponding file names.

Warning: It is recommended to remove or rename PacsOne’s risdirect.php. Our applet.php is not designed
for it, will not work in such a scenario and this combination might cause a slight security risk.

3.2.1.4. Optimizing the database (MySQL/MariaDB)

The setting optimized=true depends on certain database optimizations and improves search performance.
• The list of modalities in study is taken from a ready to use column, study.modality_list, instead of
collecting distinct values from related series. This column is not present in PacsOne database schema
(and not in Standard DB Integration schema, too), it must be added manually. We offer a couple of triggers
that update this column automatically.
• If the user enters a search key that starts with “*”, then the search will match anywhere in the text (slower),
instead of only at beginning of the text. Not all involved columns are indexed by default.
Update the schema:

ALTER TABLE `series`


ADD INDEX `modality` (`modality`)
USING BTREE;

ALTER TABLE `study` ADD `modality_list` VARCHAR(64);


ALTER TABLE `study`
ADD INDEX `private` (`private`),
ADD INDEX `readingphysician` (`readingphysician`),
ADD INDEX `requestingphysician` (`requestingphysician`),
ADD INDEX `description` (`description`),
ADD INDEX `studydate_time` (`studydate`, `studytime`),
ADD INDEX `sourceae` (`sourceae`),
ADD INDEX `modality_list` (`modality_list`)
USING BTREE;

ALTER TABLE `patient`


ADD INDEX `firstName` (`firstname`),
ADD INDEX `lastName` (`lastname`),
ADD INDEX `middleName` (`middlename`)
USING BTREE;

Fill the study.modality_list column for existing studies:

UPDATE study SET modality_list = (SELECT GROUP_CONCAT(DISTINCT modality SEPARATOR ' ') FROM␣
˓→series WHERE series.studyuid = study.uuid);

Add the triggers that will do the same for future studies:

CREATE TRIGGER after_series_insert AFTER INSERT ON series FOR EACH ROW


UPDATE study SET modality_list = (SELECT GROUP_CONCAT(DISTINCT series.modality SEPARATOR '
˓→') FROM series WHERE series.studyuid = NEW.studyuid) WHERE study.uuid = NEW.studyuid;

CREATE TRIGGER after_study_insert BEFORE INSERT ON study FOR EACH ROW


SET NEW.modality_list = (SELECT GROUP_CONCAT(DISTINCT series.modality SEPARATOR ' ') FROM␣
˓→series WHERE series.studyuid = NEW.uuid);

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


14

3.2.2. DCM4CHEE

For DCM4CHEE (https://www.dcm4che.org/) MedDream implements the direct database access mode.

3.2.2.1. DCM4CHEE notes

Warning: Support for DCM4CHEE 4 was not ported from PHP due to very limited demand.
For DCM4CHEE 2, compatibility is regularly tested only with DCM4CHEE 2.4.17.
In this PACS, when patient name and other demographics are changed in its GUI, the corresponding DICOM
files are not updated on disk (only their copies exported via various interfaces are). But, MedDream does not
merge both sources of data; for example, Info Labels always fetch the attributes from the file, and will therefore
show outdated information. The setting com.softneta.meddream.newObjectsUseMetadataFromPacs can
only compensate for a single aspect of the issue, however there are more. If patient demographics
are often corrected at the PACS instead of the modality, we recommend to use Q/R or DICOMweb
integration instead. MedDream 8.1 alleviates that to some extent by adding Q/R support to the DCM4CHEE
plugin: if patient demographics were updated on the PACS, then corresponding DICOM files will be
downloaded via a C-MOVE request.

3.2.2.2. MedDream configuration for DCM4CHEE 5.x

1. Perform steps in the 5.1.1 Essential configuration and the first run chapter.
2. Choose and configure a universal authentication method according to 5.1.3 Built-in authentication and
authorization.
3. Edit application.properties file and update the options related to DCM4CHEE 5.x plugin. The
documentation below is for plugin version 6.2.0.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
type=Dcm4chee5
Use this specific value of type when connecting to DCM4CHEE 5.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
id=MainArchive
Identifies the plugin/configuration pair in the search window drop-down menu. You can
connect to multiple DCM4CHEE instances by using different values of id and remaining
options.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchApiEnabled=true
(optional) Specifies if this plugin/configuration pair returns a study list for the Search window
and provides study metadata. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
imageApiEnabled=true
(optional) Specifies if this plugin/configuration pair retrieves image data. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
url=jdbc:mysql://127.0.0.1:3306/PACS_DB_NAME
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
url=jdbc:postgresql://127.0.0.1:5432/PACS_DB_NAME
JDBC connection string. Supported DBMSes are MySQL and PostgreSQL.
In case of connection problems it might be necessary to add some more parameters to this
string: useJDBCCompliantTimezoneShift=true for a time zone shift, serverTimezone=UTC

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


15

for a specific timezone, useSSL=false to disable SSL, etc. (The first parameter-value
pair is preceded by “?”, the remaining pairs – by “&”.) See https://dev.mysql.com/doc/
connector-j/5.1/en/connector-j-reference-configuration-properties.html for MySQL, or https:
//jdbc.postgresql.org/documentation/head/connect.html for PostgreSQL.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
username=UserName
Username used to connect to the database.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
password=UserPassword
Password used to connect to the database.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
encoding=ISO-8859-1
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
encodingTo=ISO-8859-8
(optional) Specify encoding of database strings when it’s not UTF-8.
– encoding=ISO-8859-1, encodingTo=:

* search query is converted from UTF-8 to ISO-8859-1


* search results are converted from ISO-8859-1 to UTF-8
– encoding=ISO-8859-1, encodingTo=ISO-8859-8:

* search results are converted from ISO-8859-1 to ISO-8859-8


* search query is converted from ISO-8859-8 to ISO-8859-1
– encoding=, encodingTo=ISO-8859-8:

* search results are converted from UTF-8 to ISO-8859-8


* search query is converted from ISO-8859-8 to UTF-8
encoding and encodingTo are empty: UTF-8 is assumed everywhere (the outcome might
still be influenced by JVM system encoding).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
aggregateDataByDatabase=true
(optional) Different approaches to collect distinct series-level values of Modality and Source
AET for every study in the search results. false might improve performance in some cases
(was not tested extensively).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
storage=fs1=c:\\mnt\\NAS1;fs2=c:\\mnt\\NAS2
Filesystem root directories, as configured in the LDAP tree via entries named
“dcmStorageID”. The plugin doesn’t read this configuration from LDAP at the moment.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
pacsVersion=5.7
(optional) Two-component DCM4CHEE version number that defines what database fields
are available. Namely, 5.7 adds the Number of Frames attribute; 5.23 stores a person name
in 3 fields instead of 15 and renames series.src_aet to series.sending_aet; 5.31 relates the
tables “patient” and “patient_id” in a different fashion. If version of your PACS is not 5.7 - 5.22
(expected by default), then you’ll need to adjust this parameter to avoid SQL errors.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomPersonName=false

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


16

(experimental) Since 8.0.0 plugins are expected to return the full DICOM-formatted patient
name, like “last^first^middle^prefix^suffix=ideographic=phonetic”, for proper reformatting in
Core (also see personNameConfiguration in system.json.) false turns this off and is
normally not required.
4. Restart Core for changes to take effect, and navigate to http://127.0.0.1/. Use login credentials that
are valid for chosen method.

Q/R support for updated DICOM files

The plugin can detect whether patient demographics are changed: it parses AttributeModificationDateTime in
the “dicomattrs.attrs” database record referenced by the “patient” table, and compares with a value cached on
disk. If a newer value is found, then the cached one is updated and a C-MOVE request downloads updated
DICOM files to the local C-STORE SCP. Therefore MedDream can read up-to-date files from its own cache. If
patient demographics were not changed, then MedDream reads the original DICOM files by their paths in the
database.
This mechanism is a compromise between direct integration (the fastest) and Q/R (provides up-to-date DICOM
files). The slower mode will be used only for studies with updated patient demographics.

Note: Make sure that MedDream, PACS and DBMS are on the same time zone, or else the changes might not
be detected correctly.

The timestamps are compared only when the following options are configured:
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].localAET=MEDDREAM
The AE Title of the C-MOVE client, and the destination of C-MOVE operations.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
remoteAET=DCM4CHEE
The AE Title of the remote machine.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].remoteHost=127.0.
0.1
IP address or hostname of the remote machine.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].remotePort=11112
Port number of the remote machine.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
patientUpdateCacheDir=${com.softneta.meddream.tempDir}/timestamps
Directory for caching timestamps of patient demographics records. As a combination of plugin’s
.id and Study UID is hashed and distributed among subdirectories, you can use the same
patientUpdateCacheDir for multiple instances of the plugin.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].cacheDir= ${com.
softneta.dicomStoreService.saveDirectory}/DCM4CHEE/
A directory for DICOM files from remoteAET received by the local C-STORE SCP.
The remaining options are for slight adjustments of the behavior:
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].retryDelay=1000
Period in milliseconds for checking whether the DICOM file has been received.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].timeout=10000
Maximum total duration in milliseconds for waiting for a received file.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


17

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
fetchStudyAfterStructure=false
Start the C-MOVE command (if needed according to timestamps) as early as possible: just after
fetching the study structure, not on actual request to fetch a DICOM file.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
useSessionCache=false
When true, every session has its own subdirectory under cacheDir that is cleaned automatically
when the session ends (cleaning also requires options eventApiEnabled=true and com.
softneta.preparation.useSessionCache=true).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
useSessionPatientUpdateCache=false
When true, every session has its own subdirectory under patientUpdateCacheDir
that is cleaned automatically when the session ends (cleaning also requires options
eventApiEnabled=true and com.softneta.preparation.useSessionCache=true).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
eventApiEnabled=false
Set this to true together with useSessionCache or useSessionPatientUpdateCache (and also
com.softneta.preparation.useSessionCache) for automated cleaning of per-session caches.
Since 8.3.0, true is the default value when Q/R mode is configured (options localAET,
remoteAET, remoteHost, remotePort, cacheDir, patientUpdateCacheDir are present).
Furthermore, EventAPI also implements the “Clear caches” functionality at the plugin side.
When set to false, the plugin will support neither “Clear caches” nor automated cleaning of per-
session caches. If explicitly set to true, however Q/R mode is not configured, the plugin won’t
attempt any cleaning, too.

3.2.2.3. MedDream configuration for DCM4CHEE 2.x

1. Perform steps in the 5.1.1 Essential configuration and the first run chapter.
2. (Option 1) Choose and configure a universal authentication method according to 5.1.3 Built-in
authentication and authorization.
3. (Option 2) If you intend to (partially) reuse DCM4CHEE user management, then configure this kind of
authentication in application.properties file:

spring.profiles.include=auth-dcm4chee
authentication.database.username=APP_USER
authentication.database.password=APP_PASS
authentication.database.jdbcUrl=jdbc:mysql://DB_HOST:DB_PORT/DB_NAME
authorization.defaultLoginPermissions=EXPORT_ARCH,EXPORT_ISO,FORWARD,\
DOCUMENT_VIEW
authorization.remapRoles.Doctor=SEARCH
authorization.remapRoles.WebAdmin=ADMIN
authorization.users[0].userName=user
authorization.users[0].role=UPLOAD_DICOM_LIBRARY,REPORT_UPLOAD

.jdbcUrl supports not only MySQL but also PostgreSQL (jdbc:postgresql://


DB_HOST:DB_PORT/DB_NAME) and MS SQL Server (jdbc:sqlserver://DB_HOST:DB_PORT;
database=DB_NAME). .username and .password are credentials of an application user for
reading the database tables; you can use the same credentials for the plugin below. Oracle is
not supported for auth-dcm4chee; Oracle-based PACS integration will need to use a different
authentication method.
.defaultLoginPermissions lists common permissions. In this example, the DCM4CHEE’s
predefined “Doctor” role additionally gets SEARCH, and the predefined user “user” gets

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


18

UPLOAD_DICOM_LIBRARY and REPORT_UPLOAD. Because “user” belongs to “Doctor”


by default, it now has UPLOAD_DICOM_LIBRARY, REPORT_UPLOAD, SEARCH and
everything from defaultLoginPermissions. Similarly, the predefined user “admin” who has
“WebAdmin” and “Doctor” roles in DCM4CHEE, now has ADMIN, SEARCH, etc (except
UPLOAD_DICOM_LIBRARY and REPORT_UPLOAD).
The full list of permissions can be found in 5.1.3 Built-in authentication and authorization. That
chapter also describes a few universal authentication methods.

Note: By default, application.SAMPLE.properties enables auth-inmemory and this is done on


another line. There is no error message if you assign to spring.profiles.include multiple times,
and the outcome might be counter-intuitive. Make sure to comment the unneeded line out.

4. Edit application.properties file and update the options related to DCM4CHEE 2.x plugin. The
documentation below is for plugin version 5.1.0.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
type=Dcm4chee2
Use this specific value of type when connecting to DCM4CHEE 2.x.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].id=RouterPacs
Identifies the plugin/configuration pair in the search window drop-down menu. You can
connect to multiple DCM4CHEE instances by using different values of id and remaining
options.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchApiEnabled=true
(optional) Specifies if this plugin/configuration pair returns a study list for the Search window
and provides study metadata. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
imageApiEnabled=true
(optional) Specifies if this plugin/configuration pair retrieves image data. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
url=jdbc:mysql://127.0.0.1:3306/PACS_DB_NAME
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
url=jdbc:postgresql://127.0.0.1:5432/PACS_DB_NAME
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
url=jdbc:sqlserver://127.0.0.1:1433;database=PACS_DB_NAME
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
url=jdbc:oracle:thin://127.0.0.1:1521/xe
JDBC connection string. Supported DBMSes are MySQL, PostgreSQL, Microsoft SQL
Server and Oracle.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
username=UserName
Username used to connect to the database.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
password=UserPassword
Password used to connect to the database.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
defaultStoragePath=C:/DCM4CHEE_INSTALL_DIR/server/default

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


19

Base directory for relative paths. By default DCM4CHEE stores the files relative to a certain
location below the installation directory (see the example), unless one sets up in advance an
absolute filesystem prefix via addRWFileSystem() in JMX Console.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
charset=latin1
(optional) Defines the character set used in the database. If not empty, conversion from this
character set to UTF-8 is attempted; otherwise the data is passed as is (default). utf8 might
work in case of double encoding.

Note: The PACS GUI (/dcm4chee-web, /dcm4chee-web3, etc) is able to correctly display
data even if the database server was configured incorrectly before sending the images and
therefore parts of the database accessed by the plugin now contain garbled text or question
marks (information is permanently lost already). DCM4CHEE has a certain workaround
against this situation; there is no equivalent of it in the plugin.

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
enableStatistics=false
(optional) true enables query statistics such as query time and so on. You might also want
to set logging.level.org.hibernate=DEBUG in application.properties to get more details.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
mappedStorageLocations=D:/DICOM=Y:\\DICOM1|E:/DICOM=Y:\\DICOM2
(optional) Defines replacement paths for MedDream that is installed on a different host than
the PACS, and is accessing images through mapped network drives or network paths.
We recommend to configure defaultStoragePath with a ready to use value, instead of using a
PACS-local value and adding a separate replacement rule here. Of course the corresponding
folder must be shared on the PACS, too.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
addPatientBirthDateToDescription=false
(optional) If true, Study Description is prefixed by Patient’s Birth Date. This is for display only
– searching by this date is not possible.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomPersonName=false
(experimental) Since 8.0.0 plugins are expected to return the full DICOM-formatted patient
name, like “last^first^middle^prefix^suffix=ideographic=phonetic”, for proper reformatting in
Core (also see personNameConfiguration in system.json.) false turns this off and is
normally not required.
5. Restart Core for changes to take effect, and navigate to http://127.0.0.1/. Use login credentials that
are valid for chosen method.

Q/R support for updated DICOM files

The plugin can detect whether patient demographics are changed: it compares the database field
“patient.updated_time” with “patient.created_time” and a value cached on disk. If a newer value is found, then
the cached one is updated and a C-MOVE request downloads updated DICOM files to the local C-STORE SCP.
Therefore MedDream can read up-to-date files from its own cache. If patient demographics were not changed,
then MedDream reads the original DICOM files by their paths in the database.

Note: Make sure that MedDream, PACS and DBMS are on the same time zone, or else the changes might not
be detected correctly.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


20

This mechanism is a compromise between direct integration (the fastest) and Q/R (provides up-to-date DICOM
files). The slower mode will be used only for studies with updated patient demographics.
The timestamps are compared only when the following options are configured:
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].localAET=MEDDREAM
The AE Title of the C-MOVE client, and the destination of C-MOVE operations.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
remoteAET=DCM4CHEE
The AE Title of the remote machine.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].remoteHost=127.0.
0.1
IP address or hostname of the remote machine.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].remotePort=11112
Port number of the remote machine.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
patientUpdateCacheDir=${com.softneta.meddream.tempDir}/timestamps
Directory for caching timestamps of patient demographics records. As a combination of plugin’s
.id and Study UID is hashed and distributed among subdirectories, you can use the same
patientUpdateCacheDir for multiple instances of the plugin.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].cacheDir=${com.
softneta.dicomStoreService.saveDirectory}/DCM4CHEE/
A directory for DICOM files from remoteAET received by the local C-STORE SCP.
The remaining options are for slight adjustments of the behavior:
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].retryDelay=1000
Period in milliseconds for checking whether the DICOM file has been received.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].timeout=10000
Maximum total duration in milliseconds for waiting for a received file.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
fetchStudyAfterStructure=false
Start the C-MOVE command (if needed according to timestamps) as early as possible: just after
fetching the study structure, not on actual request to fetch a DICOM file.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
useSessionCache=false
When true, every session has its own subdirectory under cacheDir that is cleaned automatically
when the session ends (cleaning also requires options eventApiEnabled=true and com.
softneta.preparation.useSessionCache=true).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
useSessionPatientUpdateCache=false
When true, every session has its own subdirectory under patientUpdateCacheDir
that is cleaned automatically when the session ends (cleaning also requires options
eventApiEnabled=true and com.softneta.preparation.useSessionCache=true).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
eventApiEnabled=false
Set this to true together with useSessionCache or useSessionPatientUpdateCache (and also
com.softneta.preparation.useSessionCache) for automated cleaning of per-session caches.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


21

Since 8.3.0, true is the default value when Q/R mode is configured (options localAET,
remoteAET, remoteHost, remotePort, cacheDir, patientUpdateCacheDir are present).
Furthermore, EventAPI also implements the “Clear caches” functionality at the plugin side.
When set to false, the plugin will support neither “Clear caches” nor automated cleaning of per-
session caches. If explicitly set to true, however Q/R mode is not configured, the plugin won’t
attempt any cleaning, too.

3.2.3. ClearCanvas

For ClearCanvas (https://clearcanvas.ca/) MedDream implements the direct database access mode.

3.2.3.1. ClearCanvas notes

Support was tested with ClearCanvas 2.0 and 13.2.

Warning: Because the commercial version of ClearCanvas became end-of-life in 2020, support is tested
only ocassionally. MedDream 8.0.0 was not tested.

As IIS occupies the port 80, MedDream will need to run on a different port (the server.port setting). If
MedDream URL looks “not nice” because of that, then you can use IIS as a reverse proxy; please contact
[email protected] for instructions.

3.2.3.2. MedDream configuration for ClearCanvas

1. Perform steps in the 5.1.1 Essential configuration and the first run chapter.
2. Choose and configure a universal authentication method according to 5.1.3 Built-in authentication and
authorization.
3. Edit application.properties file and update the options related to ClearCanvas plugin. The
documentation below is for plugin version 5.1.0.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
type=ClearCanvas
Use this specific value of type when connecting to ClearCanvas.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].id=OldArchive
Identifies the plugin/configuration pair in the search window drop-down menu. You can
connect to multiple ClearCanvas instances by using different values of id and remaining
options.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchApiEnabled=true
(optional) Specifies if this plugin/configuration pair returns a study list for the Search window
and provides study metadata. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
imageApiEnabled=true
(optional) Specifies if this plugin/configuration pair retrieves image data. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
url=jdbc:sqlserver://127.0.0.1:1433;database=ImageServer
URL should be specified in format: jdbc:sqlserver://<HOST>\\<INSTANCE>:<PORT>;
database=<DATABASE_NAME>

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


22

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
username=UserName
Username used to connect to the database.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
password=UserPassword
Password used to connect to the database.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
mappedStorageLocation=C:\\FS=Z:\\Studies
(optional) Defines pair of path strings that should be replaced in order to use mapped
storages. Syntax for defining strings: “oldPathPart=newPathPart”.
In case of multiple rules, separate them by pipe character and enter more specific ones first:
E:\\DICOM2=\\\\CLRCANVAS-SRV\\DICOM2\|E:\\DICOM=Z:\\DICOM.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
strictSearchIsEnabled=
(optional) true forces exact matching by Patient ID and Accession Number everywhere,
including the Search window. false forces wildcard matching everywhere, including HIS
integration by Patient ID or Accession Number, and the Patient History window. null or unset
is the default: exact matching for Patient History and HIS integration, wildcard matching for
Search window.
4. Restart Core for changes to take effect, and navigate to http://127.0.0.1:MEDDREAM_PORT/. Use login
credentials that are valid for chosen method.

3.2.4. Conquest

For Conquest (https://ingenium.home.xs4all.nl/dicom.html) MedDream implements the direct database access


mode.

3.2.4.1. Conquest notes

MedDream does not support the proprietary “V2 (allows NKI compression)” image format. All images that were
received by Conquest with this setting on, including those of the example patient “HEAD EXP2”, will be unusable.

3.2.4.2. MedDream configuration for Conquest

1. Perform steps in the 5.1.1 Essential configuration and the first run chapter.
2. Choose and configure a universal authentication method according to 5.1.3 Built-in authentication and
authorization.
3. Edit application.properties file and update the options related to Conquest plugin. The documentation
below is for plugin version 5.1.1.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
type=Conquest
Use this specific value of type when connecting to Conquest.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
id=ResearchPacs
Identifies the plugin/configuration pair in the search window drop-down menu. You
can connect to multiple Conquest instances by using different values of id and
remaining options.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


23

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchApiEnabled=true
(optional) Specifies if this plugin/configuration pair returns a study list for the Search
window and provides study metadata. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
imageApiEnabled=true
(optional) Specifies if this plugin/configuration pair retrieves image data. Default is
true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
url=jdbc:mysql://127.0.0.1:3306/PACS_DB_NAME
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
url=jdbc:postgresql://127.0.0.1:5432/PACS_DB_NAME
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
url=jdbc:sqlserver://127.0.0.1:1433;database=PACS_DB_NAME
JDBC connection string. Supported DBMSes are MySQL, PostgreSQL, Microsoft
SQL Server, dBASE 3.
MS SQL server isn’t directly supported by Conquest. This is a special case
when Conquest uses an ODBC source backed by the SQL Server, and
MedDream connects to the server directly.
Please contact [email protected] if you would like to use dBASE 3
integration.
In case of connection problems it might be necessary to add some more parameters
to this string, like useSSL=false to disable SSL. (The first parameter-value
pair is preceded by “?”, the remaining pairs – by “&”.) See https://dev.mysql.
com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html
for MySQL, or https://jdbc.postgresql.org/documentation/head/connect.html
for PostgreSQL, or https://docs.microsoft.com/en-us/sql/connect/jdbc/
setting-the-connection-properties?viewFallbackFrom=sql-server-previousversions
for Microsoft SQL Server.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
username=UserName
Username used to connect to the database.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
password=UserPassword
Password used to connect to the database.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
pathToDicomIni=E:\\Conquest\\dicom.ini
Full path to the Conquest configuration file dicom.ini. MedDream will read
MAGDeviceXXX=... lines from it.
There is no “mappedStorageLocation” configuration option like in other plugins. In
case when MedDream is on a different host, one can copy dicom.ini to a file on
MedDream host, leave only MAGDeviceX lines and update them with shared paths
that are accessible on MedDream host. For example, MAGDevice1=E:\DICOM might
change to MAGDevice1=\\conquest-srv\dicomstorage1.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
useModalityAggregation=true
(optional) Aggregate results in the DBMS (not in the plugin). Performance might
become worse.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


24

false by default, and can’t be set to true for MS SQL Server or dBASE 3.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
encoding=ISO-8859-1
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
encodingTo=ISO-8859-8
(optional) Specify encoding of database strings when it’s not UTF-8.
– encoding=ISO-8859-1, encodingTo=:

* search query is converted from UTF-8 to ISO-8859-1


* search results are converted from ISO-8859-1 to UTF-8
– encoding=ISO-8859-1, encodingTo=ISO-8859-8:

* search results are converted from ISO-8859-1 to ISO-8859-8


* search query is converted from ISO-8859-8 to ISO-8859-1
– encoding=, encodingTo=ISO-8859-8:

* search results are converted from UTF-8 to ISO-8859-8


* search query is converted from ISO-8859-8 to UTF-8
If encoding and encodingTo are empty (default), then UTF-8 is assumed everywhere
(the outcome might still be influenced by JVM system encoding).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
encodingF=cp850
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
encodingFTo=ISO-8859-13
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
encodingFTest=true
(optional) Like encoding and encodingTo but for file system paths. Conquest uses
the Patient ID attribute in subdirectory names, and national characters in the attribute
might make the files inaccessible.
If empty (default), then no character set conversion is performed.
encodingFTest=true attempts to guess the encoding until the file becomes
accessible. You will need to look for hints in “Test Encoding” log messages (INFO
level), then configure encodingF and encodingFTo accordingly.
4. Restart Core for changes to take effect, and navigate to http://127.0.0.1/. Use login credentials that
are valid for chosen method.

3.3. Integration over Web or other APIs

3.3.1. Orthanc

For Orthanc (https://www.orthanc-server.com/) MedDream uses its custom Web API. DICOM files are also
downloaded through it, and can be cached for better performance.
Direct database access wasn’t implemented as it would likely offer little performance gain due to database
schema complexity. You might try the DICOM mode as an alternative.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


25

3.3.1.1. Orthanc notes

The API is not used to authenticate users because tested versions of Orthanc offer only global credentials (for a
single user). These credentials must still be entered in plugin configuration, though.
When using preparation triggered by forwarding of images to the DICOM Listener, you should use the
onStableStudy event in Orthanc for forwarding. Immediate forwarding (before the import to Orthanc database
has finished), like based on the onStoreInstance event, will result in problems as MedDream won’t be able to
get recent study metadata this early. The example Lua script can be obtained from [email protected].

3.3.1.2. MedDream configuration for Orthanc

1. Perform steps in the 5.1.1 Essential configuration and the first run chapter.
2. Choose and configure a universal authentication method according to 5.1.3 Built-in authentication and
authorization.
3. Edit application.properties file and update the options related to Orthanc plugin. The documentation
below is for plugin version 5.0.1.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].type=Orthanc
Use this specific value of type when connecting to Orthanc.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
id=Telemedicine
Identifies the plugin/configuration pair in the search window drop-down menu. You can
connect to multiple Orthanc instances by using different values of id and remaining options.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchApiEnabled=true
(optional) Specifies if this plugin/configuration pair returns a study list for the Search window
and provides study metadata. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
imageApiEnabled=true
(optional) Specifies if this plugin/configuration pair retrieves image data. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
eventApiEnabled=false
(optional) Set this to false in order to disable support for “Clear caches”. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
baseUrl=http://127.0.0.1:8042
Base URL that points to the root of Orthanc Web API. (Endpoints /tools/find, /instances
etc will be appended automatically.)
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
username=UserLogin
Username for Basic Authentication.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
password=UserPassword
Password for Basic Authentication.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomCacheDirectory=${com.softneta.meddream.tempDir}/dcm/Telemedicine
(optional) A directory for caching images and study structure. Without this setting a
file is downloaded anew every time and it’s not possible to examine the contents for
troubleshooting. Study structure is cached together with a “last study update” timestamp from

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


26

Orthanc; this ensures that an updated structure is always fetched from the server (excess
caching is prevented).
This plugin supports URIs (starting with file://). Making them relative to tempDir or another
setting is encouraged to minimize human errors.
Multiple instances of this plugin should have different directories in order to not mix up
potentially different versions of the file with the same Study/Series/SOP Instance UIDs.
As of MedDream 7.5.1+, this directory is not cleaned automatically and you need to configure
a separate entry under com.softneta.temp-cleaner.tempItems[] (see Temporary files
cleaner ).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
cacheDicomFiles=true
(optional) If false, dicomCacheDirectory is used only for caching the study structure.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
pythonPlugin=false
(optional) true enables a faster method of fetching the study structure. However the Python
plugin and a custom script from Softneta must be configured in Orthanc; see the next chapter.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
strictSearchIsEnabled=true
(optional) true forces exact matching by Patient ID and Accession Number everywhere,
including the Search window. false forces wildcard matching everywhere, including HIS
integration by Patient ID or Accession Number, and the Patient History window. null or unset
is the default: exact matching for Patient History and HIS integration, wildcard matching for
Search window.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchPoolSize=10
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
imagePoolSize=10
(optional) Maximum number of threads for fetching search results or metadata, and
downloading DICOM files, respectively. Increasing the value might improve performance,
however it also increases probability of timeouts and then raising searchRequestRepeat /
imageRequestRepeat is advised.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchRequestRepeat=15
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
imageRequestRepeat=5
(optional) In case of download failure the request will automatically be retried this number of
times. Each retry is delayed by 300 ms, 600 ms, 900 ms and so on.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
nonStrictSearchPattern=00100020:*{value}*;00080050:*{value}*
(optional) Specifies where to put wildcard characters when implementing a non-strict search.
The value in the example is used by default, and yields the same behavior as before.
Entries are separated with ;. Format of the entry is <tag code>:<value pattern>. The
<value pattern> part must contain a placeholder {value} that will be replaced with the
search key; furthermore, space characters in the key are replaced with *. Currently
recognized values for <tag code> are 00100020 and 00080050.
This would match only values beginning with the search key: 00100020:{value}*;
00080050:{value}*.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


27

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchSymbols=*,?
(optional) Comma-separated list of wildcard characters. They aren’t allowed in strict search
scenarios, and will yield an error message.
The default value with two characters from the Standard is a security improvement: it makes
sure that the PACS won’t return studies to which the end user has no acccess. An empty
string means pre-8.0 behavior.
In non-strict scenarios, including strictSearchIsEnabled=false or keys like Study Description,
these characters are used to decide that the search key is good enough — namely, it
doesn’t need formatting by nonStrictSearchPattern and spaces aren’t to be replaced with
asterisks. When the end user is using the Search window, (s)he can explicitly add wildcards
where deemed appropriate: for example, PID001 is sent to the PACS as *PID001*, PID 001
– *PID*001*, PID001* – PID001*, PID?001 – PID?001.
4. Restart Core for changes to take effect, and navigate to http://127.0.0.1/. Use login credentials that
are valid for chosen method.

3.3.1.3. Orthanc Python plugin

The Python plugin in Orthanc allows scripting custom behavior. A script from Softneta (available below) returns
study metadata significantly faster than the dedicated method of Orthanc API.

Note: Orthanc 1.6.0 or newer is required.

Prepare the script file

Save the following into a file softneta.py:

import json
import orthanc
def GetStudyInfo(output, uri, **request):
studyId = request['groups'][0]
info = []
instances = orthanc.RestApiGet('/studies/%s/instances?expand' % studyId)
series = orthanc.RestApiGet('/studies/%s/series' % studyId)
for serie in json.loads(series):
tags = serie['MainDicomTags']
tags['OrthancSeriesID'] = serie['ID']
tags['ParentStudy'] = serie['ParentStudy']
info1 = []

for instance in json.loads(instances):


if serie['ID'] == instance['ParentSeries']:
tags1 = instance['MainDicomTags']
tags1['OrthancInstanceID'] = instance['ID']
metadata = orthanc.RestApiGet('/instances/%s/metadata?expand' \
% instance['ID'])
for (key, value) in json.loads(metadata).items():
tags1[key] = value

info1.append(tags1)
tags['Instances'] = info1
info.append(tags)
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


28

(continued from previous page)

output.AnswerBuffer(json.dumps(info), 'application/json')
orthanc.RegisterRestCallback('/studies/(.*)/info', GetStudyInfo)

Install the plugin

Orthanc in Docker
The easiest and fastest way to have Orthanc with Python plugin is to use a Docker image that already includes
the plugin: https://hub.docker.com/r/jodogne/orthanc-python.
For example, if you are installing MedDream with Orthanc and want to use the Python plugin, then use the
following commands:

docker network create orthanc


docker run --restart=always --network=orthanc --name orthanc -v /mnt/orthanc-db/:\
/var/lib/orthanc/db/ -itd -p 4242:4242 -p 8042:8042 jodogne/orthanc-python
docker run --restart=always --network=orthanc --name meddream -itd -p 80:8080 -e \
integration=study meddream/orthanc-dicom-viewer:8.1.0

Orthanc under Windows


Install Python 3.7-3.8 on the Orthanc machine (for example, Python 3.8.8 64bit from https://www.python.org/
downloads/windows/). Make sure to check Add Python 3.X to PATH in the installer.
Download the plugin depending on installed Python and Orthanc versions from https://www.orthanc-server.com/
browse.php?path=/plugin-python. Pay special attention to 32 or 64bit, and what minimum Orthanc version is
required by the chosen plugin version. At the time of this writing, plugin 3.1 didn’t work properly with Orthanc
1.9.3.
Copy the DLL to the Orthanc “Plugins” directory, for example, C:\Program Files\Orthanc
Server\Plugins\OrthancPython-Win64-Python3.8-1.0.dll. Then restart the Orthanc service.
Orthanc under Linux
You should install the orthanc-python package from your native Debian/Ubuntu distribution if available, or
compile the plugin from sources.

Enable the plugin and install the script

Orthanc in Docker
Verify that Python plugin is activated by opening your plugins page, for example: http://localhost:8042/app/
explorer.html#plugins.
Copy softneta.py to any suitable location in Docker container, for example:

docker cp softneta.py orthanc:/usr/local/share/orthanc/plugins/softneta.py

In the configuration file orthanc.json, verify path to the plugins directory and add the path to your script, for
example:

"Plugins" : [
"/usr/share/orthanc/plugins", "/usr/local/share/orthanc/plugins"
],
"PythonScript" : "/usr/local/share/orthanc/plugins/softneta.py",

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


29

It might be easier to copy orthanc.json from the container to your environment (docker cp orthanc:/etc/
orthanc/orthanc.json orthanc.json), edit and then copy it back (docker cp orthanc.json orthanc:/etc/
orthanc/orthanc.json).
Afterwards the container must be restarted (docker restart orthanc).
Orthanc under Windows
Verify that Python plugin is activated by opening your plugins page, for example: http://localhost:8042/app/
explorer.html#plugins.
Copy softneta.py to any suitable location, for example, C:\Orthanc\softneta.py.
In the configuration file orthanc.json, verify path to the plugins directory and add the path to your script, for
example:

"Plugins" : [ "../Plugins/" ],
"PythonScript" : "C:\\Orthanc\\softneta.py",

Afterwards the Orthanc service must be restarted.


Orthanc under Linux
Verify that Python plugin is activated by opening your plugins page, for example: http://localhost:8042/app/
explorer.html#plugins.
Copy softneta.py to any suitable location, for example, /usr/local/share/orthanc/plugins/softneta.py.
In the configuration file orthanc.json, verify path to the plugins directory and add the path to your script, for
example:

"Plugins" : [
"/usr/share/orthanc/plugins", "/usr/local/share/orthanc/plugins"
],
"PythonScript" : "/usr/local/share/orthanc/plugins/softneta.py",

Afterwards the Orthanc service must be restarted.

Testing the script

1. Open any study in Orthanc and copy the value of “uuid” parameter from the browser address
bar. For example, http://localhost:8042/app/explorer.html#study?uuid=dddddddd-cccccccc-bbbbbbb-
00000000-aaaaaaaa.
2. Open a new tab and try to access the following URL (update the UUID with value from step 1): http:
//localhost:8042/studies/dddddddd-cccccccc-bbbbbbb-00000000-aaaaaaaa/info.
For example, if the study address was http://localhost:8042/app/explorer.html#study?uuid=c4dfb8ab-
762b8b76-9a068673-4dbba15b-24167200, then the test URL shall be http://localhost:8042/studies/
c4dfb8ab-762b8b76-9a068673-4dbba15b-24167200/info.
You should be able to see some JSON-formatted information.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


30

3.3.2. DICOMweb

Universal HTTP-based communication over RESTful protocols like QIDO-RS and WADO-RS, and the legacy
WADO-URI protocol.

3.3.2.1. DICOMweb notes

WADO-RS does not provide means to request a particular set of attributes. Study metadata from a server
inclined to return all attributes can be enormous. It is advised to minimize the amount of data:
• Some non-standard parameter, like “dataset=meddream”, could be implemented in the server to support
optimal and reduced attribute sets at the same time.
• The server could be configured for a reduced set if MedDream is the sole client.
• Some PACSes might return a smaller set of attributes via SearchForInstances of QIDO-RS, compared
to RetrieveMetadata of WADO-RS. In that case, specify a full URL in studyMetaUrl (with as many
“includefield” parameters as needed) and leave the wadoRsUrl option empty.
The DICOM Standard does not offer an attribute for the date/time when the study was received by the PACS.
Similarly there is some confusion regarding which attribute should indicate Application Entity Title of the sender.
As a result, typical PACSes do not return this data and MedDream search columns “Received On” and “Source
AE” remain empty. If you’ll find out what tags a particular PACS uses, then they can be configured via plugin
options studyReceivedDateTag and sourceAeTitleTag.
The plugin supports the following authentication choices:
• no authentication;
• HTTP Basic Authentication;
• a custom HTTP POST (or, alternatively, GET) to a configurable address that accepts HTML FORM
variables “login” and “password”, and returns HTTP 200/202 with a configurable cookie. This cookie is
included in all subsequent requests and automatically refreshed when needed;
• Google Cloud service authentication for using a Google Cloud Healthcare data store instead of a PACS. It
is enough to specify a JSON file downloaded from Cloud Console that contains keys and other parameters;
• Microsoft Azure authentication (based on client ID, client secret and OAuth2 URL that includes the tenant
ID).
When configuring a custom query in URLs, do not attempt to override some parameters added by the plugin
dynamically; as the plugin does not check for duplicates, the server will likely accept the second occurrence (the
duplicate from the plugin) instead.
Google Healthcare requires a reasonably accurate machine clock. A very large difference (tens of minutes) with
respect to Google servers will result in an “Invalid JWT” error. Azure might have a similar effect because the
token lifetime is just one hour.

3.3.2.2. Compatibility

Search operation uses SearchForStudies of QIDO-RS protocol, the header “Accept: application/dicom+json” is
used by default (can be overridden). Attributes recognized in the response are:
• (0008,0020) Study Date
• (0008,0030) Study Time
• (0008,0050) Accession Number
• (0008,0061) Modalities In Study
• (0008,1030) Study Description
• (0010,0010) Patient Name

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


31

• (0010,0020) Patient ID
• (0020,000D) Study Instance UID
• configurable custom attribute for AE Title(s) of senders contributing to the study
• configurable custom attribute for study reception date/time
Most of them can also be used as query keys.
A certain filter, if enabled, checks the value of (0020,1208) Number Of Study Related Instances and silently
aborts if the attribute is not present.
Fetching study metadata uses RetrieveMetadata of WADO-RS protocol, the header “Accept:
application/dicom+json” is used by default (can be overridden). Alternatively, it is possible to configure a
full URL that results in an equivalent list of instances and their attributes, like SearchForInstances of QIDO-RS.
Attributes recognized in every SOP instance are:
• (0002,0010) Transfer Syntax UID
• (0008,0020) Study Date
• (0008,0016) SOP Class UID
• (0008,0018) SOP Instance UID
• (0008,0030) Study Time
• (0008,0050) Accession Number
• (0008,0060) Modality
• (0008,0090) Referring Physician’s Name
• (0008,1030) Study Description
• (0008,103E) Series Description
• (0010,0010) Patient Name
• (0010,0020) Patient ID
• (0010,0030) Patient Birth Date
• (0020,000E) Series Instance UID
• (0020,0010) Study ID
• (0020,0011) Series Number
• (0020,0013) Instance Number
• (0028,0008) Number Of Frames
• configurable custom attribute for AE Title(s) of senders contributing to the study
Download of a DICOM file can use WADO-URI protocol or RetrieveInstance of WADO-RS protocol. WADO-RS
can return the file directly or wrapped in a “multipart/related” MIME container, however only the first body in
the container, regardless of headers, is considered. The default Accept header is “application/dicom; transfer-
syntax=*” (Google Cloud mode) or just “application/dicom” (others); the value can be overridden regardless of
integration.
Uploading annotations and screenshots can use StoreInstances of STOW-RS protocol (disabled by default in
favor of the global C-STORE based mechanism). The default header is “Accept: application/dicom+json” (can
be overridden).
DICOM XML format for metadata and other responses is not supported.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


32

3.3.2.3. MedDream configuration for DICOMweb

1. Perform steps in the 5.1.1 Essential configuration and the first run chapter.
2. Choose and configure a universal authentication method according to 5.1.3 Built-in authentication and
authorization.
3. Edit application.properties file and update the options related to DICOMweb plugin. The
documentation below is for plugin version 6.2.0; examples are from integrations with DCM4CHEE 5.25,
Orthanc 1.5.8 with OrthancDicomWeb 1.0, PacsOne 7.2 and Google Cloud Healthcare as of June 2022.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].type=Dicomweb
Use this specific value of type when connecting via DICOMweb.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
id=MainArchiveDW
Identifies the plugin/configuration pair in the search window drop-down menu. You can
connect to multiple PACSes by using different values of id and remaining options.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchApiEnabled=true
(optional) Specifies if this plugin/configuration pair returns a study list for the Search window
and provides study metadata. Default is true.
When targeting an older PacsOne installation that supports WADO-URI only, you can
use false here and choose a different plugin (PacsOne or even QR) with same id and
imageApiEnabled=false as the counterpart.
Speaking of any PACS, this plugin’s Image API can be used as an alternative if sharing
DICOM files over the network is somehow not possible and slower operation is not an issue.

Note: An equivalent of the legacy PHP-based $pacs = 'WADO' integration can be


constructed from the QR plugin (Search API) and this plugin (Image API with wadoUriUrl).

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
imageApiEnabled=true
(optional) Specifies if this plugin/configuration pair retrieves image data. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
eventApiEnabled=false
(optional) true, together with useSessionCache=true and com.softneta.preparation.
useSessionCache=true, enables cleaning of per-session cache subdirectories when the
sessions end, and support for “Clear caches” at the plugin side.
Default is true since 8.3.0.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
storageApiEnabled=true
(optional) Specifies if this plugin/configuration pair is used to store annotations and
screenshots (instead of the universal C-STORE based mechanism). Default is false.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
qidoRsUrl=http://127.0.0.1:8080/dcm4chee-arc/aets/DCM4CHEE/rs?fuzzymatching=true
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
qidoRsUrl=http://127.0.0.1:8042/dicom-web
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
qidoRsUrl=https://healthcare.googleapis.com/v1/projects/P1/locations/L2/datasets/
D3/dicomStores/S4/dicomWeb?fuzzymatching=true

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


33

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
qidoRsUrl=https://my-azure-test-123.dicom.azurehealthcareapis.com/v1?
fuzzymatching=true
Base URL of QIDO-RS API. Can include a query for additional or non-standard parameters.
(The endpoint /studies and relevant dynamic parameters will be appended automatically.)
In this example, DCM4CHEE 5, Google Cloud and Azure require the “fuzzymatching”
parameter or else searching by Patient Name is not possible at all.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
wadoRsUrl=http://127.0.0.1:8080/dcm4chee-arc/aets/DCM4CHEE/rs
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
wadoRsUrl=http://127.0.0.1:8042/dicom-web
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
wadoRsUrl=https://healthcare.googleapis.com/v1/projects/P1/locations/L2/datasets/
D3/dicomStores/S4/dicomWeb
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
wadoRsUrl=https://my-azure-test-123.dicom.azurehealthcareapis.com/v1
Base URL of WADO-RS API. Can include a query for additional or non-standard parameters.
(The endpoint /studies will be appended automatically.)
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
studyMetaUrl=http://127.0.0.1:8080/dcm4chee-arc/aets/DCM4CHEE/rs/studies/{study}/
metadata
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
studyMetaUrl=http://127.0.0.1:8042/dicom-web/studies/{study}/instances?
includefield=00100010&includefield=00100020&includefield=00100030&
includefield=00080020&includefield=00080030&includefield=00080090&
includefield=00280008
Alternative to wadoRsUrl. This is a full URL, not its base part; you must specify the query
part, too, if needed. The placeholder {study} can appear anywhere.
The second example in fact means QIDO-RS instead of WADO-RS. This makes no difference
for the plugin, as long as the response format is the same.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
metaAcceptHeader=application/json
(optional) Overrides the default Accept header application/dicom+json for search and
study structure.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
metaCustomHeader=x-test-1: value1
(optional) Adds custom header(s) for search and study structure. Multiple entries are also
possible, by using | as separator: x-test-1: value1|x-test-2: value2|....
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
wadoUriUrl=http://127.0.0.1:8080/dcm4chee-arc/aets/DCM4CHEE/wado
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
wadoUriUrl=http://127.0.0.1:8042/wado
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
wadoUriUrl=http://127.0.0.1/wado.php
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
wadoUriUrl=http://127.0.0.1/wado.php?username=UserLogin&password=UserPassword
Base URL of WADO-URI API. Can include a query for additional or non-standard parameters.
(The relevant dynamic parameters will be appended automatically.)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


34

Google Cloud Healthcare and Azure DICOM service do not support WADO-URI, use
dicomFileUrl instead.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomFileUrl=http://127.0.0.1:8042/wado?requestType=WADO&studyUID={study}
&seriesUID={series}&objectUID={image}&contentType=application%2Fdicom
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomFileUrl=http://127.0.0.1:8080/dcm4chee-arc/aets/DCM4CHEE/rs/studies/{study}/
series/{series}/instances/{image}
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomFileUrl=https://healthcare.googleapis.com/v1/projects/P1/locations/L2/datasets/
D3/dicomStores/S4/dicomWeb/studies/{study}/series/{series}/instances/{image}
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomFileUrl=https://my-azure-test-123.dicom.azurehealthcareapis.com/v1/studies/
{study}/series/{series}/instances/{image}
Alternative to wadoUriUrl. This is a full URL, not its base part; you must specify the query
part, too, if needed. Placeholders {study}, {series} and {image} can appear anywhere.
The examples 2. . . 4 in fact mean WADO-RS instead of WADO-URI. This makes no difference
for the plugin, as long as the PACS still returns the DICOM file directly – or in the
“multipart/related” format that is also indicated by the Content-Type header. (DCM4CHEE
5 supports only multipart from RetrieveInstance, see fileAcceptHeader.)
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
fileAcceptHeader=application/dicom
(optional) Overrides the default Accept header for file downloads (application/
dicom; transfer-syntax=* if googleCloudConfigFile is configured, or application/dicom
otherwise).
To request a multipart format from PACSes that don’t support other formats, try multipart/
related; type="application/dicom".
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
fileCustomHeader=x-test-1: value1
(optional) Adds custom header(s) for file downloads. Multiple entries are also possible, by
using | as separator: x-test-1: value1|x-test-2: value2|....
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
stowRsUrl=http://127.0.0.1:8042/dicom-web
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
stowRsUrl=http://127.0.0.1:8080/dcm4chee-arc/aets/DCM4CHEE/rs
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
stowRsUrl=https://healthcare.googleapis.com/v1/projects/P1/locations/L2/datasets/
D3/dicomStores/S4/dicomWeb
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
stowRsUrl=http://127.0.0.1/stowrs.php
Base URL of STOW-RS API. Can include a query for additional or non-standard parameters.
(The relevant dynamic parameters will be appended automatically.)
Azure DICOM service doesn’t support the optional Study Instance UID that is automatically
appended to this URL; use uploadUrl instead.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
uploadUrl=http://127.0.0.1:8042/dicom-web/studies/{study}
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
uploadUrl=http://127.0.0.1:8080/dcm4chee-arc/aets/DCM4CHEE/rs/studies/{study}

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


35

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
uploadUrl=https://healthcare.googleapis.com/v1/projects/P1/locations/L2/datasets/
D3/dicomStores/S4/dicomWeb/studies/{study}
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
uploadUrl=http://127.0.0.1/stowrs.php/studies/{study}
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
uploadUrl=https://my-azure-test-123.dicom.azurehealthcareapis.com/v1/studies
Alternative to stowRsUrl. This is a full URL, not its base part. The {study} placeholder can
appear anywhere. By the way, this parameter provides an opportunity to omit the standard
“/studies/{study}” part because the latter is always automatically appended to stowRsUrl.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
sendAcceptHeader=application/json
(optional) Overrides the default Accept header (application/dicom+json) for uploading
annotations and screenshots.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
sendCustomHeader=x-test-1: value1
(optional) Adds custom header(s) for uploading annotations and screenshots. Multiple
entries are also possible, by using | as separator: x-test-1: value1|x-test-2:
value2|....
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
username=UserLogin
(optional) Username for Basic Authentication, custom form authentication or Azure
authentication (in the latter case this parameter expects the client ID, like 123e4567-e89b-
12d3-a456-426652340000).
Not needed for default configuration of DCM4CHEE 5. Definitely needed for Orthanc with
AuthenticationEnabled=true. Needed for PacsOne by default unless credentials are included
in the URL (less secure).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
password=UserPassword
(optional) Password for Basic Authentication, custom form authentication or Azure
authentication (in the latter case this parameter expects the client secret, like
SW4gdGhlIGJlZ2lubmluZyB3YXMgdGhlIFdvcmQ=).
Not needed for default configuration of DCM4CHEE 5. Definitely needed for Orthanc with
AuthenticationEnabled=true. Needed for PacsOne by default unless credentials are included
in the URL (less secure).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
loginUrl=http://server/path
(optional) URL for a custom form authentication with username parameter login and
password parameter password. If empty and azureAuthUrl is also empty, then Basic
Authentication or no authentication (depending on whether both username and password
are configured) is used instead.
Obviously not applicable to DCM4CHEE, Orthanc or PacsOne.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
loginWithGET=true
(optional) When true, loginUrl is used to perform a GET request instead of POST.
Credentials (login and password) are automatically added to the URL.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
loginCookie=MySessionCookie

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


36

(optional) Cookie name for a custom form authentication. Default value is “suid”.
Obviously not applicable to DCM4CHEE, Orthanc or PacsOne.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
azureAuthUrl=https://login.microsoftonline.com/936da01f-9abd-4d9d-80c7-02af85c822a8/
oauth2/token
(optional) Enables the Azure authentication (loginUrl must be empty). The URL must be
in form shown above; the GUID is to be replaced with your tenant ID on Azure platform.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
googleCloudConfigFile=C:\MedDreamPACS-Premium\MedDream\gc-login.json
(optional) Turns on Google Cloud Healthcare integration mode: a certain authentication and
a different default Accept header for file downloads. Do not forget to use dicomFileUrl instead
of wadoUriUrl.
The file must contain a service account private key in JSON format, as created by the IAM &
Admin console.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
<name>.tag=1048624
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
<name>.type=string
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
<name>.level=STUDY
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
<name>.strict=false
(optional) Remapping of attributes sent to the PACS as query/return keys and collected from
the response. Also see 5.1.17 Custom columns in Patient History / Patient Studies for the
overall idea.
Fully tested values of <name> for this plugin are sourceAe, receivedDate, custom1 . . .
custom10. More will be documented in the future.
.tag specifies the tag of a DICOM attribute – an integer in decimal notation, e. g.,
(0123,4567) => 0x01234567 => 19088743. The columns “sourceAe” (was configured
via sourceAeTitleTag before MedDream 8.2) and “receivedDate” (was configured via
studyReceivedDateTag) are ignored by default as their .tag is zero.
.type specifies additional processing of the value. object (default) means none. number is
converted to Integer or Double. For string, missing value is replaced with “”. For date, a date
formatted as yyyMMdd is converted to yyyy-MM-dd. For time, a time formatted as HHmmss
is converted to HH:mm:ss. personName, when dicomPersonName=false, replaces every “^”
with a space. You can safely use string with the columns “sourceAe” and “receivedDate”
mentioned above.
.level specifies where to request the attribute and expect it in the response. Default is STUDY,
can be changed to SERIES or IMAGE.
.strict (false by default) can disable adding of wildcards by default when this attribute is used
as a search key. The overall scenario and strictSearchIsEnabled can still override it. See
also nonStrictSearchPattern, searchSymbols.
Migration for “sourceAe” and “receivedDate” from pre-8.2 versions looks as follows:

#com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
˓→sourceAeTitleTag=1048624

com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
˓→sourceAe.tag=1048624

com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


37

(continued from previous page)


˓→sourceAe.type=string

#com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
˓→studyReceivedDateTag=19106219

com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
˓→receivedDate.tag=19106219

com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
˓→receivedDate.type=string

In 8.2+ it’s still possible to specify any study-level attribute for .columns.sourceAe.tag or
.columns.receivedDate.tag that the PACS is able to return. sourceAe should also work as
a search key; receivedDate is only a return key. But, the column in search results will
still have the original name which might confuse insufficiently trained end users. The only
workaround (when using a single plugin) is to rename the text in the translation file; for
English it’s ...,"sourceAE":"Source AE",... or ...,"receivedOn":"Received On",...
in sys/locales/en/translation.*.json.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
multipleModalitySupport=true
(optional) false will yield an error message when the user selects multiple modalities. Use
this if the PACS does not support multiple modalities and search results confuse the users
(nothing is found).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
multivalueSeparatorIsComma=false
(optional) Since 4.3.0, the Modality filter is comma-separated by default, as recent versions
of the Standard require this more clearly and more PACSes are following it. Earlier the
Standard was referring to Query/Retrieve semantics; some PACSes (or their older versions)
might still expect a backslash-separated filter in QIDO-RS queries, and you’ll need to use
false in those cases.
A couple of tested PACSes return no results when this setting is incorrect and more than one
modality is selected in the Search window. But, this still won’t help if multiple modalities aren’t
supported at all (see multipleModalitySupport).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomCacheDirectory=${com.softneta.meddream.tempDir}/dcm/MainArchiveDW
(optional) A directory for caching images. Without this setting a file is downloaded anew
every time and examining its contents for troubleshooting becomes difficult.
This plugin supports URIs (starting with file://). Making them relative to tempDir or another
setting is encouraged to minimize human errors.
Multiple instances of this plugin should have different directories in order to not mix up
potentially different versions of the file with the same Study/Series/SOP Instance UIDs.
As of MedDream 7.5.1+, this directory is not cleaned automatically and you need to configure
a separate entry under com.softneta.temp-cleaner.tempItems[] (see Temporary files
cleaner ). useSessionCache below mitigates the situation to some extent.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
useSessionCache=true
(optional) Enables per-session cache subdirectories. Default is false.
The main benefit is that together with eventApiEnabled=true and com.softneta.
preparation.useSessionCache=true, a session subdirectory is cleaned automatically when
the session ends (for example, the user logs off). As a result, the DICOM files are cached for
the shortest time possible. The temporary files cleaner is then needed mainly for unforeseen
situations like application crashes or server restarts.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


38

On the other hand, when one user opens a particular study, then afterwards other users won’t
experience faster loading of the same study as the entire study is downloaded again for each
of them.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
strictSearchIsEnabled=false
(optional) true forces exact matching by Patient ID and Accession Number everywhere,
including the Search window. false forces wildcard matching everywhere, including HIS
integration by Patient ID or Accession Number, and the Patient History window. null or unset
is the default: exact matching for Patient History and HIS integration, wildcard matching for
Search window.
true is required for Google Cloud Healthcare due to its limitations. Furthermore, Google
Cloud does not support searching by Study Description and MedDream is unable to handle
this gracefully.
true is required for Azure DICOM service, too. As of August 2022, the service supports
fuzzy matching only for the Patient Name attribute and all other attributes must match exactly
(wildcards are considered a literal part of the query).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
badUtf8Filter=true
(optional) true enables a workaround for incorrectly encoded UTF-8 characters in JSON
responses related to qidoRsUrl, wadoRsUrl and studyMetaUrl.
The issue should be fixed in the PACS instead, as the workaround costs some performance
overhead. Enable it only if search operations, or attempts to open a certain study, are failing
and the application log contains a JsonMappingException complaining about “Invalid UTF-8”.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
sCSeriesLowerPriority=true
(optional) true shifts series with Secondary Capture objects (classes . . . 1.1.7, . . . 1.1.7.*)
further in the thumbnail strip by adding 10000 to the Series Number attribute of those objects.
This is disabled by default.
Since 8.3.1 the alternative is the Core setting com.softneta.study.
lowerPrioritySeriesModalities: it works for all plugins, selects series by value of
Modality and moves them more effectively (there is no hardcoded increment of Series
Number that might be insufficient for some studies).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
allowDuplicateObject=NO
(optional) Graceful handling of duplicate objects in the same series.
MedDream uses the SOP Instance UID as a unique key when downloading a DICOM
file, therefore the study structure (and response from wadoRsUrl/studyMetaUrl) can’t have
multiple entries with the same SOP Instance UID. But, it is possible to selectively ignore
some of them.
If the PACS always returns a more recent copy earlier, then you can safely choose KEEP:
MedDream will use the first entry and ignore further duplicates.
If the PACS always returns a more recent copy later, then you can safely choose REPLACE:
MedDream will update the object attributes from every duplicate, effectively using the last
entry.
The risk behind a wrong choice is that MedDream will prepare itself for the value of an
attribute found in the study structure, but later the PACS will return a DICOM file with a
different value of the same attribute. Results might be unpredictable as MedDream is not
tested with this kind of misinformation.
The default value is NO and duplicates will cause an error like before version 4.9.0.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


39

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
logResponseAmount=256
(optional) Change how many bytes of the server response are logged at DEBUG level.
The default value of zero corresponds to 512 for file downloads and 524288 for
search/metadata. A configured value replaces both limits at once.
A common usage is to reduce size of the application logs due to a smaller value, like 32. A
value larger than 512K can help when troubleshooting a crash related to parsing of JSON
data.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomPersonName=true
(experimental) Return Patient Name and Referring Physician Name with DICOM separators
(^) and include all five components. If false, return only last name and first name separated
by a space. The ideographic and phonetic component groups are never returned, though.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
multivalueSeparatorIsComma=true
(optional) When false, multiple values of a search key (e. g., Modalities In Study) are
delimited with backslashes and not commas. This might be needed by older PACSes.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
nonStrictSearchPattern=00100020:*{value}*;00080050:*{value}*
(optional) Specifies where to put wildcard characters when implementing a non-strict search.
The value in the example is used by default, and yields the same behavior as before.
Entries are separated with ;. Format of the entry is <tag code>:<value pattern>. The
<value pattern> part must contain a placeholder {value} that will be replaced with the
search key; furthermore, space characters in the key are replaced with *. Currently
recognized values for <tag code> are 00100020 and 00080050.
This would match only values beginning with the search key: 00100020:{value}*;
00080050:{value}*.
This forces exact matching for Patient ID and Accession Number even with
strictSearchIsEnabled=false: 00100020:{value};00080050:{value}.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchSymbols=*,?
(optional) Comma-separated list of wildcard characters. They aren’t allowed in strict search
scenarios (except otherStrictSearchTags), and will yield an error message.
The default value with two characters from the Standard is a security improvement: it makes
sure that the PACS won’t return studies to which the end user has no acccess. An empty
string means pre-8.0 behavior.
In non-strict scenarios, including strictSearchIsEnabled=false or keys like Study Description,
these characters are used to decide that the search key is good enough — namely, it
doesn’t need formatting by nonStrictSearchPattern and spaces aren’t to be replaced with
asterisks. When the end user is using the Search window, (s)he can explicitly add wildcards
where deemed appropriate: for example, PID001 is sent to the PACS as *PID001*, PID 001
– *PID*001*, PID001* – PID001*, PID?001 – PID?001.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
otherStrictSearchTags=524384,19088743
(optional) Override which non-integration attributes are used as strict search filters. Tag
numbers must be in decimal notation and separated by commas.
Supported values are Modality (specified by 524384, which is the same as 0x00080060) and
Source AE Title (specified by the same nonzero value as in sourceAeTitleTag).

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


40

Modality is included by default, therefore you can use an empty string for a non-strict search
by modality. Keep in mind afterwards that some standard modality codes include each other,
like “US” will also match “IVUS”, “OP” will also match “OPV”, etc. This will be useful for
PACSes that are unable to find, say, “MR” in a list like “KO,MR,PR”.
Both attributes are partially subject to searchSymbols. A query key is allowed to contain this
kind of wildcard character; if there is one, and otherStrictSearchTags does not configure
a strict search for the key, then leading and trailing * characters are added unconditionally –
without using nonStrictSearchPattern.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchPageSize=500
(optional) Maximum value of the QIDO-RS “limit” parameter (hard limit on search results)
when MedDream’s legacy value, 1000, is too large for the server.
If less than 1000, then MedDream performs multiple requests with corresponding “offset” and
“limit” parameters until up to 1000 results are collected in total.
By default it’s 200 when azureAuthUrl is not empty, and 1000 otherwise.
A value not in range 1. . . 1000 yields a warning and is replaced with a default. The Azure
DICOM server, in turn, supports a shorter range – 100. . . 200.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchSkipsSingleObjOfMods=KO,PR
(optional) Search results will not contain records where Modalities In Study has a single
value matching any entry in this comma-separated list and Number Of Study Related
Instances is 1.
This option was created as a workaround for a certain PACS that lists studies consisting of a
single certain SR object, yet is unable to return study metadata for it and the error message
confuses the end users.
It could also be used to hide studies consisting of a single non-image object like MedDream’s
own KO, PR or RTSTRUCT: studies like these will result in a message about an empty study.
4. Restart Core for changes to take effect, and navigate to http://127.0.0.1/. Use login credentials that
are valid for chosen method.

3.3.2.4. HIS-provided dynamic values in configuration strings

The parameters qidoRsUrl, wadoRsUrl, studyMetaUrl, wadoUriUrl, dicomFileUrl, stowRsUrl, uploadUrl and
googleCloudConfigFile can have 4 placeholders “custom1” . . . “custom4” for integration-specific dynamic
values:
• {custom1}
• {custom1:DEFAULT_VALUE}
• {custom1:}
• ...
• {custom4:DEFAULT_VALUE}
(in the 3rd example, the default value is an empty string).
Only those four are supported. Other documented placeholders – “{study}”, “{series}” and “{image}” – are
handled elsewhere. Any other (unknown) placeholder name will result in a fatal error.
Dynamic values come from the “storageConfiguration” part of the HIS integration token. The corresponding
parameters there are called DICOMWEB_CUSTOM_1 . . . DICOMWEB_CUSTOM_4.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


41

If the default value isn’t specified together with the placeholder, then a corresponding dynamic value must be
provided in the token. This means that when MedDream is used both interactively and from HIS, the default
values are unavoidable.
For example, the setting ...[0].googleCloudConfigFile=/opt/meddream/gc-{custom1:interactive}.json
refers to a file “gc-interactive.json” for scenarios with MedDream login and search, while a token

{
"items": [ ],
"storageConfiguration": [ { "storage": "gc1", "parameters": [
{ "name": "DICOMWEB_CUSTOM_1", "value": "his" }
] } ]
}

requests to use a file “gc-his.json” instead.

Note: The bundled token service doesn’t recognize DICOMWEB_CUSTOM_* by default and needs the
following configuration string in its own application.properties file:

validate.storage-configurations.parameter-list=DICOMWEB_CUSTOM_1,DICOMWEB_CUSTOM_2,\
DICOMWEB_CUSTOM_3,DICOMWEB_CUSTOM_4

3.3.3. Amazon S3

S3 is a generic cloud object storage solution from Amazon.


By itself S3 doesn’t provide metadata that is needed by MedDream early – during initial stages of study loading.
In comparison, the “File system mode” somewhat gets away by extracting a minimum amount of metadata from
files that are immediately available on a rather quick local file system, therefore the initial delay remains bearable.
With S3, however, the latency is too high; neither an s3fs mount, nor a custom client for iterating objects below
the given prefix, can result in acceptable responsiveness of MedDream.
We suggest a custom manifest in JSON format (a ready to use “study structure”) to speed up the collection of
metadata.
1. MedDream is started with the “study” parameter (legacy URL-based HIS integration), or with an equivalent
token (token-based HIS integration).
2. An HTTP GET request downloads the JSON manifest for a particular Study Instance UID that was passed
in Step 1.
3. Based on the manifest, MedDream displays the initial empty study structure and related metadata. Image-
level URLs to DICOM files listed in the manifest are cached in memory every time a manifest is downloaded.
4. DICOM files are downloaded on demand (depending on whether the thumbnail is visible, or if the “Preload”
function is used, etc.) and cached on disk. The cached copies are reused later until the Temporary files
cleaner removes them.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


42

3.3.3.1. Manifest specification

The following JSON file illustrates the supported metadata. Attributes are grouped into study level and
instance+series levels (MedDream afterwards uses series-level attributes in the latter for proper grouping into
series).
The plugin ignores the Content-Type response header and always parses the payload as JSON.

{
"instanceUid": "1.2.3",
"studyDate": "20140710",
"studyTime": "084944.000",
"studyReceivedDate": "",
"studyId": "1",
"studyDescription": "PLC CT CHE-ABD-PEL-CORONARY CAL SCORE-VIRTUAL COLONOSCOPY",
"accessionNumber": "1000801048",
"referringPhysicianName": "DOE^JOSEPH^X.",
"modalitiesInStudy": "CT",
"sourceAETitle": "",
"patientId": "200091016",
"patientName": "DOE^JOHN",
"patientBirthDate": "19710107",
"sops": [
{
"seriesInstanceUid": "4.5.6.70",
"seriesDescription": "Cardiac 3.0 Cardiac/Score",
"modality": "CT",
"seriesNumber": "2",
"sopClassUid": "1.2.840.10008.5.1.4.1.1.2",
"transferSyntaxUid": "1.2.840.10008.1.2",
"instanceNumber": "4",
"sop": "8.9.10.100",
"frameCount": 1,
"dicomUrl": "https://some-server.s3.us-east-2.amazonaws.com/dicom/1.2.3/4.5.6.70/8.9.
˓→10.100.dcm?X-Amz-Credential=...&X-Amz-Signature=..."

},
{
"seriesInstanceUid": "4.5.6.71",
"seriesDescription": "Body 5.0",
"modality": "CT",
"seriesNumber": "3",
"sopClassUid": "1.2.840.10008.5.1.4.1.1.2",
"transferSyntaxUid": "1.2.840.10008.1.2",
"instanceNumber": "2",
"sop": "8.9.10.100",
"frameCount": 1,
"dicomUrl": "https://some-server.s3.us-east-2.amazonaws.com/dicom/1.2.3/4.5.6.71/8.9.
˓→10.101.dcm?X-Amz-Credential=...&X-Amz-Signature=..."

}
]
}

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


43

JSON field Required? Meaning


instanceUid Y (0020,000D) Study Instance UID
studyDate . (0008,0020) Study Date
studyTime . (0008,0030) Study Time
studyReceivedDate . Implementation-specific: when the study has been received
studyId . (0020,0010) Study ID
studyDescription . (0008,1030) Study Description
accessionNumber . (0008,0050) Accession Number
referringPhysicianName . (0008,0090) Referring Physician’s Name
modalitiesInStudy . Either (0008,0061) Modalities In Study, or unique values of
(0008,0061) Modality from all objects
sourceAETitle . Implementation-specific: AE Title of the sender
patientId . (0010,0020) Patient ID
patientName . (0010,0010) Patient’s Name
patientBirthDate . (0010,0030) Patient’s Birth Date
sops Y List of objects (at least one) in the study
seriesInstanceUid Y (0020,000E) Series Instance UID
seriesDescription . (0008,103E) Series Description
modality . (0008,0060) Modality
seriesNumber Y (0020,0011) Series Number
sopClassUid Y (0008,0016) SOP Class UID
transferSyntaxUid Y (0002,0010) Transfer Syntax UID
instanceNumber Y (0020,0013) Instance Number
sop Y (0008,0018) SOP Instance UID
frameCount . (0028,0008) Number Of Frames
dicomUrl Y URL for downloading the entire DICOM file

3.3.3.2. Amazon S3 notes/limitations

The Search window is not supported. If enabled, its contents will remain empty. This is a typical HIS integration.
There is no specific authentication/authorization between MedDream and S3, or between MedDream and
the manifest service. In general, DICOM files in the S3 bucket must be either readable anonymously (the
s3:ListBucket permission should be denied, though), or accessible due to X-Amz-Credential and similar
options in the URL. The implementer can choose any convention that results in short-lived URLs. The manifest
service should be accessible only by MedDream – due to a firewall, to an IP address whitelist, or just by listening
on a loopback address in the same machine.
Currently it is not possible to configure a REST-like URL, or the entire URL including the query part, for
downloading the manifest. The query part ?studyInstanceUID=<UID> is blindly added to the configured endpoint
address. This prevents hosting of a static manifest on the same S3 bucket.
Other manifest formats, like Basic Directory IOD (DICOMDIR), are not supported at the moment.
The downloaded DICOM files are always cached on disk, and the corresponding configuration option (cache
directory) is mandatory.
Do not configure the two settings common to most plugins, searchApiEnabled and imageApiEnabled. The
values are true by default, and false will not work properly: particularly, ImageAPI of this plugin depends on
URLs cached by its SearchAPI.
Saving annotations will not work unless the customer’s solution includes a DICOM Storage SCP that propagates
the changes both to the S3 and the manifest service.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


44

3.3.3.3. MedDream configuration for Amazon S3

1. Perform steps in the 5.1.1 Essential configuration and the first run chapter.
1. Configure the HIS integration (preferably token-based) in application.properties file:

spring.profiles.include=auth-his
#authentication.his.validHisParams=study
authentication.his.token-service-address=http://127.0.0.1:8088/v2/validate
authorization.defaultHisPermissions=EXPORT_ISO,EXPORT_ARCH,FORWARD,\
UPLOAD_DICOM_LIBRARY,DOCUMENT_VIEW,BOUNDING_BOX_VIEW

2. Make sure caching of the study structure is commented out or disabled:

com.softneta.cache.studyStructureSec=0

Now the manifest service will be always queried when reloading a study. This is important
if URLs to DICOM objects expire after a short time.
2. Edit application.properties file and update the options related to Amazon S3 plugin. The
documentation below is for plugin version 3.0.1.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].type=AmazonS3
Use this specific value of type.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].id=S3
Identifies the plugin/configuration pair. You can use multiple manifest services etc. by using
different values of id and remaining options.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
eventApiEnabled=false
(optional) false will turn off “Clear caches” support in the plugin. True by default.
Note that this is not related to automatic cleaning of the cache when the session ends. This
plugin, unlike some others, doesn’t support the useSessionCache setting and its cache is
always global.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
studyStructureServiceUrl=http://internal-production-alp.us-east-2.elb.amazonaws.
com/Integration/GetStructureByStudy
The endpoint that returns a manifest JSON given the Study Instance UID. A query ?
studyInstanceUID=... is added automatically.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomCacheDirectory=${com.softneta.meddream.tempDir}/dcm/AmazonS3
Cache directory for received files.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
dicomUrlMappingItemsCount=300000
(optional) Size of the URL cache. The default value is 250000.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


45

3.4. DICOM mode

MedDream is able to communicate over DICOM 3.0 native interface (Upper Layer Protocol, ULP) with any PACS
that supports Query/Retrieve and Storage.

3.4.1. DICOM mode notes

The Query/Retrieve SCU identifies itself as “MEDDREAM” by default. (Do not forget to configure the PACS to
accept connections from this AET.) This can be changed by the localAET setting of the plugin. Binding to a
particular port is usually not required, and Java-based MedDream still doesn’t support that.
The plugin also contains its own Store SCU that is used to send annotations and screenshots back to the PACS.
(With other plugins, a common DICOM SCU in Java Core is used, see 3.1.2 Saving measurements, Key Objects,
segmentations and screenshots.) If you choose this, then:
• the plugin-level settings storeScpIp, storeScpPort and storeScpAet (for the common DICOM SCU) are
not needed – the plugin uses the same remoteHost, remotePort and remoteAET as for Query/Retrieve;
• its Calling AE Title is configured by the localAET plugin setting, instead of storeScuAet or com.softneta.
meddream.dcmsnd.bind;
• uploading via the plugin also requires its setting storageApiEnabled=true.
The local Store SCP (receives files during a C-MOVE session) is implemented not in the plugin but in Java
Core, and can function in parallel to any other plugin if needed. It must bind to a port (we recommend 11116)
and by default listens on 127.0.0.1 (com.softneta.dicomStoreService.address can specify a single address
or 0.0.0.0, a wildcard for any available IP address). The mandatory settings are:
• com.softneta.dicomStoreService.localAETitle – accepted Called AE Title (also multiple comma-
separated values, or even empty),
• com.softneta.dicomStoreService.port,
• com.softneta.dicomStoreService.acceptAETitles – known Calling AE Titles,
• com.softneta.dicomStoreService.saveDirectory – base directory for received files.

3.4.2. MedDream configuration for DICOM mode

1. Perform steps in the 5.1.1 Essential configuration and the first run chapter.
2. Choose and configure some universal authentication method according to 5.1.3 Built-in authentication and
authorization.
3. Edit application.properties file and update the options related to Query/Retrieve plugin. The
documentation below is for plugin version 6.0.0.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].type=QR
Use this specific value of type when connecting to a PACS over the DICOM 3.0 protocol.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
id=AnonStudies
Identifies the plugin/configuration pair in the search window drop-down menu.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchApiEnabled=true
(optional) Specifies if this plugin/configuration pair returns a study list for the Search window
and provides study metadata. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
imageApiEnabled=true

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


46

(optional) Specifies if this plugin/configuration pair retrieves image data. Default is true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
eventApiEnabled=false
(optional) true by default. If set to true (or commented out) together with
useSessionCache=true and com.softneta.preparation.useSessionCache=true, the per-
session cache is cleared automatically when session ends.
If set to true (or commented out), support for “Clear caches” at the plugin side is enabled. In
case of “useSessionCache” settings mentioned above, will clean the user-specified part of
both per-session and global caches.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
storageApiEnabled=true
(optional) Specifies if this plugin/configuration pair is used to send
PR/KO/segmentation/screenshot objects back to its PACS (instead of using the mechanism
common to all plugins). Default is false.
You can try this option when there are some problems with PR/KO sending, as the Store
SCU in the plugin is a bit different. The parameters storeScpAet, storeScpIp, storeScpPort
and storeScuAet are then not used.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
remoteAET=PACSONE
The AE Title of the remote machine.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
remoteHost=127.0.0.1
IP address or hostname of the remote machine.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
remotePort=104
Port number of the remote machine.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
localAET=MEDDREAM
The AE Title of the DICOM C-FIND/C-MOVE/C-STORE clients implemented in this plugin.
Also used as the C-MOVE destination.
Multiple values (separated by comma) can be entered if the local Store SCP is configured
with multiple Called AE Titles. This might improve performance due to parallel sessions.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
cFindLocalAET=MDR
(optional) If not empty, overrides localAET for C-FIND sessions (C-MOVE sessions always
remain unchanged).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
cacheDir=${com.softneta.dicomStoreService.saveDirectory}/PACSONE/
A directory with images that are received by local C-STORE SCP in the background. The
trailing slash/backslash is mandatory.
The last subdirectory must be equal to remoteAET, as the local SCP adds one automatically
to the configured base directory.
This plugin supports URIs (starting with file://). Making them relative to receiver’s
saveDirectory is encouraged to minimize human errors.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].timeout=90000
(optional) DICOM file receive timeout in milliseconds (starting from the C-MOVE request).

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


47

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
retryDelay=1000
(optional) DICOM file existence check period in milliseconds.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
strictSearchIsEnabled=true
(optional) true forces exact matching by Patient ID and Accession Number everywhere,
including the Search window. false forces wildcard matching everywhere, including HIS
integration by Patient ID or Accession Number, and the Patient History window. null or unset
is the default: exact matching for Patient History and HIS integration, wildcard matching for
Search window.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
multipleModalitySupport=true
(optional) false will yield an error message when the user selects multiple modalities. Use
this if the PACS does not support multiple modalities and search results confuse the users.
If explicitly configured with true, the plugin performs a workaround for a certain PACS: a
filter by modality “ECG” will also match a non-standard modality “ECGEP”. Keep the option
commented out if this is undesired.
When this option is commented out (default), both the error message and the modality
workaround are turned off.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
defaultStartDate=20181107
(optional) Default “from” date in YYYYMMDD format when empty in the user interface. This is
for some PACSes that require the Study Date search key in every C-FIND request.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
defaultEndDate=20181108
(optional) Default “to” date in YYYYMMDD format when empty in the user interface. This is for
some PACSes that require the Study Date search key in every C-FIND request.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
studyLevelRequest=false
(optional) Value for query attribute (0008,0052) Query/Retrieve Level: STUDY if true (default),
SERIES if false.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchCharset=ISO_IR 144
(optional) Convert search keys from UTF-8 to this encoding. Default is empty (no
conversion).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
structureResultCharset=ISO_IR 144
(optional) If the PACS didn’t specify result encoding, then convert search results from this
encoding to UTF-8. Default is empty (no conversion).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
useSessionCache=true
(optional) Enables session-scope caching. When true, every session gets its own
cache subdirectory (the plugin moves, or copies, globally received files to session-related
subdirectories). It is forcefully cleaned when the session ends (cleaning also requires
eventApiEnabled and com.softneta.preparation.useSessionCache).
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].cmove.
requestSeriesFirstInstances=0

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


48

(optional) If nonzero, performs an image-level C-MOVE for this number of objects at


beginning of each series, and then proceeds with remaining images via either study- or
series-level C-MOVE.
This might help to display the thumbnails faster. For example, when MedDream displays only
the first image of every CT series, then cmove.requestSeriesFirstInstances=1 ensures that
the thumbnail of series #2 doesn’t need to wait until the entire series #1 is received, and so
on.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].cmove.
requestAllSeriesIfInstanceCountLowerThen=0
(optional) If a series contains less objects than specified here, then it is not downloaded
partially (via an instance-level C-MOVE); it is instead downloaded completely, via a series-
level C-MOVE.
The value must be equal to, or larger than, cmove.requestSeriesFirstInstances. Otherwise it
will be increased accordingly.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].cmove.
requestAfterStructure=false
(optional) If true (default), a C-MOVE of the entire study or every series begins in background
automatically when the study structure is being returned to the frontend.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
requestStructureInEveryLevel=1000
(optional) When to collect the study structure incrementally (particularly, instance attributes
are enumerated separately for each series). The default attempt to fetch attributes
from multiple levels might cause some PACSes to hit a hardcoded number of query
results and the only partial workaround is to enumerate instances from a single series
at once. This will, of course, not help if even a single series is larger than the limit;
requestStructureInstanceLevelResultLimit might then help further.
An integer means retrying in incremental mode after finding out that the study structure
contains this many images. This special number is to be found experimentally: every large
study then looks “truncated” at the same size. (The true size can be found by starting study-
level C-MOVE from a third-party tool and counting the number of received files.)
true forces the incremental mode regardless of study size. This decision should be based on
performance measurements as default behavior might be more efficient with some PACSes.
Default is zero and means “never”.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
requestStructureInstanceLevelResultLimit=1000
(optional) Refines behavior of requestStructureInEveryLevel. If any query in
incremental mode again hits this limit (not necessarily the same as specified by
requestStructureInEveryLevel), then values of the Instance Number attribute are analyzed
for gaps and missing ones are enumerated via queries with a filter on Study Instance UID /
Series Instance UID / Instance Number. A gap is assumed at the beginning if the minimum
Instance Number is not 1. Another gap is always assumed at the end, starting from the
maximum Instance Number plus one. Every gap is queried by increasing values of Instance
Number, and this terminates prematurely on empty result.
Default is zero and disables this additional filter on Instance Number.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].cmove.
filterModalities=CT,SR
(optional) Alternative to cmove.requestSeriesFirstInstances: a comma-separated list of
Modality values that identify important series to be C-MOVE’d before the remaining ones.
Requires cmove.requestAfterStructure=true, cmove.requestAfterStructureLevel=SERIES
and nonzero cmove.filterModalitiesIfStudyHasMoreInstance.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


49

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].cmove.
filterModalitiesIfStudyHasMoreInstance=500
(optional) The cmove.filterModalities logic is enabled only when number of instances in the
study exceeds this amount.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].cmove.
requestAfterStructureLevel=SERIES
(optional) If “SERIES”, fetches each of the missing or incomplete series separately (performs
a series-level C-MOVE). “STUDY” will fetch the entire study at once.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
nonStrictSearchPattern=00100020:*{value}*;00080050:*{value}*
(optional) Specifies where to put wildcard characters when implementing a non-strict search.
The value in the example is used by default, and yields the same behavior as before.
Entries are separated with ;. Format of the entry is <tag code>:<value pattern>. The
<value pattern> part must contain a placeholder {value} that will be replaced with the
search key; furthermore, space characters in the key are replaced with *. Currently
recognized values for <tag code> are 00100020 and 00080050.
This would match only values beginning with the search key: 00100020:{value}*;
00080050:{value}*.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
searchSymbols=*,?
(optional) Comma-separated list of wildcard characters. They aren’t allowed in strict search
scenarios, and will yield an error message.
The default value with two characters from the Standard is a security improvement: it makes
sure that the PACS won’t return studies to which the end user has no acccess. An empty
string means pre-8.0 behavior.
In non-strict scenarios, including strictSearchIsEnabled=false or keys like Study Description,
these characters are used to decide that the search key is good enough — namely, it
doesn’t need formatting by nonStrictSearchPattern and spaces aren’t to be replaced with
asterisks. When the end user is using the Search window, (s)he can explicitly add wildcards
where deemed appropriate: for example, PID001 is sent to the PACS as *PID001*, PID 001
– *PID*001*, PID001* – PID001*, PID?001 – PID?001.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
allowDuplicateObjects=NO
(optional) Handling of objects with the same SOP Instance UID found in same series.
Objects like these signal a serious flaw in the PACS, especially if they have different attributes:
you are no more sure which version of the object will be sent to MedDream later when
requested by the same SOP Instance UID (attributes in the structure might be misleading).
NO (default) disallows the duplicates and the study doesn’t open.
KEEP ignores any duplicates, therefore attributes of the first occurrence are preserved. If the
PACS wants to return all versions of the object and they are properly sorted in descending
order by reception time, then this is the safe value.
REPLACE updates the attributes of the earlier entry. If the PACS wants to return all versions
of the object and they are properly sorted in ascending order by reception time, then this
is the safe value.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
<name>.tag=1048624
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
<name>.type=string

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


50

• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
<name>.level=STUDY
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.
<name>.strict=false
(optional) Remapping of attributes sent to the PACS as query/return keys and collected from
the response. Also see 5.1.17 Custom columns in Patient History / Patient Studies for the
overall idea.
Fully tested values of <name> for this plugin are sourceAe, receivedDate, report, custom1
. . . custom10. More will be documented in the future.
.tag specifies the tag of a DICOM attribute – an integer in decimal notation. The columns
“sourceAe” (was configured via sourceAeTitleTag before MedDream 8.2) and “receivedDate”
(was configured via studyReceivedDateTag) are ignored by default as their .tag is zero. The
column report is a new functionality for read-only reports implemented by the customer and
also ignored by default.
.type specifies additional processing of the value. object (default) means none. number is
converted to Integer or Double. For string, missing value is replaced with “”. For date, a date
formatted as yyyMMdd is converted to yyyy-MM-dd. For time, a time formatted as HHmmss
is converted to HH:mm:ss. personName, when dicomPersonName=false, replaces every “^”
with a space. You can safely use string with the columns “sourceAe”, “receivedDate” and
“report” mentioned above.
.level specifies where to request the attribute and expect it in the response. Default is STUDY,
can be changed to SERIES or IMAGE.
.strict (false by default) can disable adding of wildcards by default when this attribute is used
as a search key. The overall scenario and strictSearchIsEnabled can still override it. See
also nonStrictSearchPattern, searchSymbols.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
reportURL=http://127.0.0.1:8088/report/{studyUid}
(optional) A URL (or file system path) template for accessing customer-implemented reports
(see 5.1.5.4 Remote reports for details). A placeholder {studyUid} is replaced with Study
Instance UID, and {storageId} – with .id of this plugin configuration.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
maxConnections=5
(optional) Limit on C-MOVE sessions from a particular plugin instance (a single “storage”),
shared between all concurrent user connections. 1000 by default.
Does not affect C-FIND sessions so far; their number will depend on concurrent users as
before.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
blacklistedSopClasses=1.2.840.113619.4.30
(optional) Comma-separated list of SOP Class UID values (empty by default) to be filtered
out from the study structure. Similar to “blackListedSopClasses” in system.json but at a lower
level: even PR, KO, etc can be completely hidden from MedDream this way.
Objects with a matching attribute might also avoid a C-MOVE to MedDream. However, if not
all images from a series were blacklisted but the plugin decides to do a series-level C-MOVE,
or not all series were blacklisted but the plugin decides to do a study-level C-MOVE, then the
PACS will still attempt to send the object among the “good” ones.
The main purpose of this setting is to avoid C-MOVE sessions of objects (or series, or even
studies) consisting entirely of listed objects. For example, a sub-association related only
to private SOP Classes unsupported by the local C-STORE SCP usually fails with an error
that is reported back to MedDream and interferes with loading of the study. In contrast, if

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


51

that association also contains supported objects, transfer of the latter succeeds with just a
warning which MedDream ignores.
4. Restart Core for changes to take effect, and navigate to http://127.0.0.1/. Use login credentials that
are valid for configured method.

3.5. File system access mode

This MedDream mode allows to view single DICOM files, or directories containing DICOM files (of a single study
or multiple studies). In fact, no PACS is necessary.
However there is no search functionality. A HIS (or equivalent application) must track studies/images
together with corresponding paths and offer hyperlinks to MedDream.

3.5.1. File system mode notes

MedDream is opened with a relative path to a single file, or to a directory. Absolute paths are not allowed due to
security concerns.
If a directory is specified, then DICOM files are collected directly below it by default. Number of scanned
subdirectories can be increased by the maxDepth plugin option.

Warning: As of 7.7.0+, there is only a limited support for copies of the same DICOM file (same
Study/Series/SOP Instance UIDs) in different directories. These directories must be accessed via separate
sessions with different /?file=. . . values (or their token-based equivalents); a single session must use different
multiple entries in the “file” parameter. Accessing at once via a common value, like a parent directory, is not
possible. The most obvious situation is where all files are kept together without subdirectories, and at least
one file is duplicate; duplicates will then be ignored, warnings will only be seen in the log, it might be counter-
intuitive which file is parsed first and therefore treated as a reference for finding duplicates.
The Reporting function is not recommended at all: it will treat such copies as different studies, their reports
might become mixed up after restarting the backend and reopening the studies again. Saving of key objects
and measurements might be problematic, too.

The specified directory must contain DICOM files only. Filtering by name pattern or extension is not
supported. Typical “DICOMDIR” files (the Basic Directory IOD, SOP Class “1.2.840.10008.1.3.10”) will be
ignored if encountered during a directory scan, and are specifically disallowed as a target of the “file” parameter
(using them as an alternative to directory scanning is not implemented).
This plugin supports a custom HIS integration parameter “file”. Due to architectural shortcuts, it also supports
the ubiquitous parameter “study”. But, the latter is not intended for HIS integration; if used this way, it will work
only for a short time (until a particular in-memory cache expires) after successfully opening the corresponding
studies via “file”.
Do not set searchApiEnabled or imageApiEnabled in plugin configuration to false, as this plugin can’t be
combined with others, even with other plugin instances of the same type.
The login form is not needed to view images and can therefore remain disabled together with the Search window.
However both features are needed to access the Settings dialog if the USER_SETTINGS permission is not
suitable. For that one must log in interactively as a user with the “ADMIN” permission.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


52

3.5.2. MedDream configuration for File system mode

1. Perform steps in the 5.1.1 Essential configuration and the first run chapter.
1. Configure the HIS integration in application.properties file:

spring.profiles.include=auth-his
authentication.his.validHisParams=file
authentication.his.maxObjects=10
authorization.defaultHisPermissions=EXPORT_ISO,EXPORT_ARCH,FORWARD,\
UPLOAD_DICOM_LIBRARY,DOCUMENT_VIEW,BOUNDING_BOX_VIEW

The “maxObjects” setting allows to limit the number of studies that is allowed to open at once. If the
directory specified in /?file=. . . contains more, the operation will fail. This prevents situations where
too many objects would render the frontend unusable.
2. Plan how MedDream settings will be changed:
• (Option 1) Choose and additionally configure some universal authentication method according
to 5.1.3 Built-in authentication and authorization, then add both “ADMIN” and “SEARCH”
permissions to some users. These users will be able to log in, ignore zero results in the Search
window, then go to the Settings window. There is little sense in having users without the “ADMIN”
permission, due to absent studies in the Search window.
• (Option 2) Add the “ADMIN” permission to authorization.defaultHisPermissions.
Remember that all users will then be able to change MedDream settings and might thus interfere
with each other’s work. As a short-time measure, however, this option might still be more attractive
than the first one.
• (Option 3) Add the “USER_SETTINGS” permission to authorization.defaultHisPermissions.
Afterwards every user will be able to change his own copy of the settings file, and will need
administrator’s help to get the common settings back.
3. Edit application.properties file and update the options related to the plugin “FileSystem”. The
documentation below is for plugin version 7.0.0.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
type=FileSystem
Always set this to FileSystem.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
id=File-System-Plugin
Any alphanumeric string that identifies this plugin instance.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
rootDirectory=C:\\dicoms\\files
Full path to the base directory below which the DICOM files can be found.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].maxDepth=1
(optional) The number of subdirectories traversed when collecting files. Minimum allowed
value and default value is 0.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
cacheMaxSize=1000
(optional) Maximum number of studies in the in-memory cache. Minimum allowed value is
1, default is 1000.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
cacheMaxAgeSec=7200
(optional) Maximum age, in seconds, of study records in the in-memory cache. Minimum
allowed value is 1, default is 7200 (2 hours).

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


53

The actual value might appear higher as record expiration is triggered by a write activity. If
new studies aren’t opened, then memory usage will stay unchanged.
4. Test the functionality by browsing to http://127.0.0.1/?file=PATH_TO_YOUR_FILE
For example, the directory C:\PACS\dcm4chee\server\default\archive contains DCM4CHEE
2.x archive tree, with deeper levels named like year\month\day\hour\.... This directory
is specified by rootDirectory. Then PATH_TO_YOUR_FILE could be 2012/2/4/0/43D7AA94/
2569DF62/9242C40A.

3.6. Non-DICOM file system mode

The “FileSystem-Non-Dicom” plugin allows to view directories with non-DICOM files in a fashion similar to the
traditional “filesystem” mode. A directory always results in a single study. Every file there appears as a series
with a single viewable object. Patient demographics and other metadata must be provided in a dedicated JSON
file.
There is no indexing, too, therefore the Search window can not be used.

3.6.1. Non-DICOM mode notes

MedDream is opened with a full path to a directory. The legacy “unsafe” method via /?file=. . . is not supported
so far, one must use token-enabled integration. Example token:

{
"items": [
{
"studies": {
"file" : "f:/tmp/study49405968726",
"storage": "fs2"
}
}
]
}

Viewable objects are files with extensions “png”, “bmp”, “jpeg”, “tiff”, “pdf”, “mp4”, “txt”. Files are sorted by name
and are displayed in this order. Filtering by name pattern or extension is not supported. Any subdirectories
will crash the plugin.
The metadata file must be named study-patient.json. Example contents:

{
"date": "2021-10-04",
"time": "14:36:30",
"description": "Second opinion (scanned document)",
"patientName": "John Doe",
"patientId": "123",
"sensitive": false,
"restricted": false,
"dob": "1975-04-12",
"gender": "M"
}

The fields “sensitive” and “restricted” are reserved in MedDream 8.1.0+. The value “true” will cause specific
behavior in later versions, and should not be used until then to avoid surprises.
The Modality attribute (visible in, for example, the Export window) is always set to “nonDicom”. However the
Export window, Forward window and some other functions do not work with non-DICOM studies.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


54

The plugin currently caches some data until application restart, for every unique value of the “file” parameter.
Contrary to the FileSystem plugin, the same directory with updated content will not be rescanned. You must
use unique values of “file” every time (for example, generate the directory name randomly).
Do not set searchApiEnabled or documentApiEnabled in plugin configuration to false, as this plugin can’t be
combined with others, even with other plugin instances of the same type.
This plugin supports a custom HIS integration parameter “file”. Due to architectural shortcuts, it also supports
the ubiquitous parameter “study”. But, the latter is not intended for HIS integration, its value is random and
becomes unusable after restarting the JAR.

3.6.2. MedDream configuration for Non-DICOM file system mode

1. Perform steps in the 5.1.1 Essential configuration and the first run chapter.
1. Configure the HIS integration in application.properties file:

spring.profiles.include=auth-his
authentication.his.token-service-address=http://127.0.0.1:8082/v2/validate
#authorization.defaultHisPermissions=USER_SETTINGS
#authorization.defaultHisPermissions=ADMIN

2. Plan how MedDream settings will be changed:


• (Option 1) Choose and additionally configure some universal authentication method according
to 5.1.3 Built-in authentication and authorization, then add both “ADMIN” and “SEARCH”
permissions to some users. These users will be able to log in, ignore zero results in the Search
window, then go to the Settings window. There is little sense in having users without the “ADMIN”
permission, due to absent studies in the Search window.
• (Option 2) Add the “ADMIN” permission to authorization.defaultHisPermissions.
Remember that all users will then be able to change MedDream settings and might thus interfere
with each other’s work. As a short-time measure, however, this option might still be more attractive
than the first one.
• (Option 3) Add the “USER_SETTINGS” permission to authorization.defaultHisPermissions.
Afterwards every user will be able to change his own copy of the settings file, and will need
administrator’s help to get the common settings back.
3. Edit application.properties file and update the options related to the plugin “Filesystem-Non-Dicom”.
The documentation below is for plugin version 4.0.2.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
type=Filesystem-Non-Dicom
Always set this to Filesystem-Non-Dicom.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].id=NonDicom
Any alphanumeric string that identifies this plugin instance.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
eventApiEnabled=true
(optional) If true (not configured is the same as false), then the session subdirectory
under cacheDirectory is removed automatically. Also needs com.softneta.preparation.
useSessionCache=true.
• Example: com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].
cacheDirectory=${com.softneta.meddream.tempDir}/nd
A directory for some temporary data.
4. Generate a token with "file":"{PATH_TO_YOUR_DIRECTORY}".
5. Test the functionality by browsing to http://127.0.0.1/?token={YOUR_TOKEN}.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


55

4. Image Access from hospital information system


(HIS)
In MedDream 7.6.0+, the legacy “unsafe” integration (an object identifier in the URL is sufficient to display it)
supports a few filters.
• http://localhost/?study=1.2.392.200036.9107.500.110113,1.2.840.114350.2.171.2.798268.2.
567817820.1&storage=MainArchive,RouterPacs
Opens the specified study (or studies) at once. Multiple values can be separated with commas.
The storage parameter (optional) restricts the search to specified PACS plugins; the comma-
separated list must contain values of the .id parameter in plugin configuration.
• http://localhost/?accnum=0000000005
Opens all studies resolved by this single Accession Number at once in the Viewer. No multiple
values.
• http://localhost/?patient=TT054270
Opens all studies of this single patient either in the Patient Studies window for subsequent
choice (default), or at once in the Viewer. No multiple values.
There is a risk that the number of studies is too large – for example, “0” is often assigned to
Patient ID during anonymization and would therefore match a lot of studies. Such an operation
will fail due to exceeded authentication.his.maxObjects. This limit applies both to the Patient
Studies window and to opening multiple resulting studies immediately.
The setting authentication.his.patient-integration-open-studies=false disables the
Patient Studies window. After that all resulting studies will open in Viewer immediately.
Currently there is no support for the legacy integration by Patient ID that used to result in a filtered
Search window. The Patient Studies window is quite limited in comparison.
• http://localhost/?patient=5702887&accnum=0000000005
Opens all studies resolved by this filter at once. No multiple values.
• http://localhost/?file=DIR-WITH-MULTIPLE-STUDIES
• http://localhost/?file=STUDY-DIR
• http://localhost/?file=STUDY-DIR/102.dcm,295.dcm
Opens multiple studies, a single study or single image(s). Multiple values can be separated by
commas; however MedDream will treat them as separate studies and won’t join images, even
from adjacent files, into the same study.
A single series is obviously possible if files are grouped into series subdirectories.
The parameters study, patient and accnum are supported by almost all PACS plugins. Rare exceptions are listed
under a particular PACS integration in 3 Integration with PACS chapter.
Additional limitations: only HTTP GET method (old MedDream versions supported POST as a safer alternative).
To enable this integration mode, add auth-his to the spring.profiles.include parameter, specify
URL parameters in authentication.his.valid-his-params, maximum number of resulting studies in
authentication.his.maxObjects and list permissions in authentication.his.defaultHisPermissions. For
example,

spring.profiles.include=auth-pacsone,auth-his
authentication.his.valid-his-params=study
authentication.his.maxObjects=2
#authentication.his.useSameSession=true
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


56

(continued from previous page)


#authentication.his.patient-integration-open-studies=false
authorization.defaultHisPermissions=EXPORT_ARCH,DOCUMENT_VIEW,BOUNDING_BOX_VIEW

spring.profiles.include=auth-pacsone,auth-his
authentication.his.valid-his-params=study,accnum
authentication.his.maxObjects=2
#authentication.his.useSameSession=true
#authentication.his.patient-integration-open-studies=false
authorization.defaultHisPermissions=EXPORT_ARCH,DOCUMENT_VIEW,BOUNDING_BOX_VIEW

spring.profiles.include=auth-pacsone,auth-his
authentication.his.valid-his-params[0]=patient,accnum
authentication.his.maxObjects=2
#authentication.his.useSameSession=true
#authentication.his.patient-integration-open-studies=false
authorization.defaultHisPermissions=EXPORT_ARCH,DOCUMENT_VIEW,BOUNDING_BOX_VIEW

spring.profiles.include=auth-pacsone,auth-his
authentication.his.valid-his-params[0]=study
authentication.his.valid-his-params[1]=patient,accnum
authentication.his.valid-his-params[2]=patient
authentication.his.valid-his-params[3]=storage
authentication.his.maxObjects=2
#authentication.his.useSameSession=true
#authentication.his.patient-integration-open-studies=false
authorization.defaultHisPermissions=EXPORT_ARCH,DOCUMENT_VIEW,BOUNDING_BOX_VIEW

(Formally the first example needs ...valid-his-params[0]=study, too. Luckily “[0]” is optional in this situation.)
The second example allows either “study” or “accnum” in the same installation. The third one defines a
combination of “patient” and “accnum” – not the same as either “patient” or “accnum”. The fourth contains
multiple parameters/combinations at once, and also allows to specify a particular PACS plugin via the “storage”
parameter.
The “maxObjects” parameter is zero by default, which means no limit and no protection against excessive amount
of studies.
The “useSameSession” parameter allows to have multiple viewer windows during “unsafe” HIS integration. By
default, a newly opened viewer window also replaces the session, therefore a window from the earlier session
may get “Access denied” errors.

Warning: The “storage” parameter is treated as optional, and is silently ignored if not enabled in valid-his-
params.
If missing or ignored, MedDream searches for objects via all available PACS plugins.

However it is recommended to use the new token-based integration mode instead:


• a token validator service (its reference implementation is bundled with MedDream for integration into
PacsOne web interface) accepts object identifiers and returns a generated token. More combinations
of object identifiers and storage names are supported;
• MedDream HIS integration links include only a single parameter called “token”;
• when MedDream loads, it obtains object identifiers (study, accession number, . . . ) from the token service.
For more information, including specification of the token service, see a separate document “MedDream
integration MANUAL” available at https://www.softneta.com/documentation/installation-integration-guide/
integration-via-url/.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


57

MedDream can also be integrated via its Communication API – a JavaScript-based wrapper over
the legacy/token URL method. See the Communication API specification; you can obtain it from
[email protected].
There is a third method where the image-displaying part of the frontend is added to your application as a React
component, and you implement all buttons by yourself. See the Viewport API specification, also available from
[email protected].

5. Deployment
This chapter is dedicated to PACS-independent part of the deployment. Normally you should start reading at
support for a specific PACS under 3 Integration with PACS, as those parts refer to this chapter anyway.
In case of Linux, this chapter assumes that the user has root permissions and appropriate part of MedDream
installation archive was extracted into /opt/meddream (the file /opt/meddream/MedDream-*.jar exists).

5.1. Configuration

5.1.1. Essential configuration and the first run

The main configuration file is application.properties in the directory of MedDream-*.jar.


After any changes it is required to restart the Java application.

Note: During an upgrade it’s recommended to use application.SAMPLE.properties (shipped with MedDream)
as a template and update every setting based on contents of your old configuration file. This will prevent
misunderstandings like parameters renamed or removed between versions.

1. Revise the following most important configuration parameters:


• Application TCP/IP port

server.port = APPLICATION_PORT

Allows to choose a different port if the default one is occupied. Example: server.port=80.
• Under Linux, FFmpeg installation is required to create video thumbnails and convert some less-
supported formats.

com.softneta.thumbnails.ffMpegExecutable = PATH_TO_FFMPEG

The default value is a simple name of the executable, ffmpeg. In most cases it is enough
under Linux.
Starting from 8.0.0, under Windows the value “ffmpeg”, even if configured explicitly, is
automatically replaced with “./sys/ffmpeg/ffmpeg.exe”. If the installation was relying on PATH
earlier, then one can specify the value “ffmpeg.exe” to avoid the mentioned replacement. The
best choice is to update this parameter with a full path to ffmpeg.exe.
• wkhtmltopdf (https://wkhtmltopdf.org/downloads.html) is required to include reports in exported
studies. You can skip this if reports aren’t used at all, or aren’t included during export.
Under Linux the binary is normally found in PATH. Under Windows the recommended install
locations are C:\Program Files\wkhtmltopdf and C:\Program Files (x86)\wkhtmltopdf; you can
also download the 7z Archive and just copy the EXE file to sys/report/wkhtmltopdf.exe. If your
system must use a different location, then you can specify it in application.properties:

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


58

com.softneta.export.htmlToPdf = D:/wkhtmltopdf
com.softneta.export.htmlToPdf = /opt/wkhtmltopdf

For Linux, also see https://sasablagojevic.com/setting-up-wkhtmltopdf-on-docker-alpine-linux.


Particularly, when creating a Docker image based on adoptopenjdk/openjdk8:alpine-slim,
one can use the command apk add --update --no-cache wkhtmltopdf xvfb ttf-dejavu
ttf-droid ttf-freefont ttf-liberation. After the installation it is advised to check for
missing fonts and other typical problems by running

wkhtmltopdf --enable-local-file-access default.html test.pdf

in the directory sys/report.


If wkhtmltopdf is unavailable, or its dependencies like QtWebKit are missing, then a possible
alternative is weasyprint (https://doc.courtbouillon.org/weasyprint/stable/first_steps.html or
https://kozea.github.io/WeasyPerf/samples/doc/doc.html). Because it’s a Python module,
under Windows you should have Python binaries (one of “py”, “python”, “python3”) reachable
via PATH.
You can even use a custom solution that accepts two command line parameters: a path to
the HTML file and a path to the final PDF file. In that case the htmlToPdf setting must point
to an executable file with the extension “exe”, “bat” or “sh”.
• Remaining values
During the first start these can usually remain unchanged. See 5.1.9 Reference for remaining
configuration parameters.
2. Start the Java application manually with a console command java -cp MedDream-8.3.1.jar
--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED --add-opens=java.
base/jdk.internal.misc=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED
--add-opens=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED --add-opens=jdk.
internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED --add-opens=java.base/sun.reflect.
generics.reflectiveObjects=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED
--add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED
--add-exports=java.desktop/sun.awt.image=ALL-UNNAMED org.springframework.boot.loader.
PropertiesLauncher.
The -DANTLR_USE_DIRECT_CLASS_LOADING option is needed because of a certain
problem with Reporting function.
Also see 5.1.6 Adjusting Java memory limits if your DICOM files are large and Java therefore
needs more memory than JRE offers by default.
Furthermore, path to the subfolder lib must again be given via -Djava.library.path. In most cases
a relative value ./lib is sufficient.
Lastly, path to the subfolder sys/plugins must be given via -Dloader.path. This is a temporary
requirement for using any of the included PACS integrations plugins because of a different
loading mechanism that is also compatible with OSGi plugins from the previous version.
A full example: java -cp MedDream-8.3.1.jar -Xmx1024m -Dloader.path=./sys/plugins
-Djava.library.path=./lib -DANTLR_USE_DIRECT_CLASS_LOADING=true --add-opens=jdk.
management/com.sun.management.internal=ALL-UNNAMED --add-opens=java.base/
jdk.internal.misc=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED
--add-opens=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED --add-opens=jdk.
internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED --add-opens=java.base/sun.
reflect.generics.reflectiveObjects=ALL-UNNAMED --add-opens=java.base/java.
io=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.
base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.time=ALL-UNNAMED --add-exports=java.desktop/sun.
awt.image=ALL-UNNAMED org.springframework.boot.loader.PropertiesLauncher.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


59

At this point it should just start up without errors, and the message “Application . . . started” will eventually
appear.
The login form at http://localhost:APPLICATION_PORT/ is disabled by default (results in a “403 Forbidden”
message when application.properties is composed from scratch) unless 5.1.3 Built-in authentication and
authorization is configured. On the other hand, application.SAMPLE.properties already configures the “in-
memory” authentication by default, with a predefined password. As the optimal method might be PACS-
dependent, you can configure it a bit later, together with the plugin for a particular PACS.

5.1.1.1. Additional steps for Linux

1. FFmpeg is required in order to display thumbnails of MPEG2 DICOM files and non-BD-compatible MPEG4
videos (Transfer Syntax UID 1.2.840.10008.1.2.4.102). If your distribution does not provide ffmpeg, avconv
package may be used. In that case a symlink to avconv binary is required:
ln -s /usr/bin/avconv /usr/bin/ffmpeg
2. To display non-BD-compatible MPEG4 videos (Transfer Syntax UID 1.2.840.10008.1.2.4.102), latest
version of FFmpeg might be required.
3. If Java application will run under a non-root user, then adjust file system permissions:

chown LIMITED_USER:LIMITED_GROUP -R /opt/meddream


find /opt/meddream -type d -exec chmod 775 {} \;
find /opt/meddream -type f -exec chmod 664 {} \;

Running Java application as root is OK for initial tests, however in production environment it
should run under some limited user instead, ideally the one who can access all DICOM files in
read only mode. A compromise would be to run the JVM under the same user as the PACS
process.
This adjustment step makes sure that a process running under a limited user can access its files,
especially the ones created earlier under name of root. In the simplest case you can examine
the log file after starting the process under a different user, as even the log file will likely be
non-writeable.

5.1.2. System.json

The file system.json (sys/settings/system.json by default) is automatically created if missing when the Java
application starts. Several key features require this file to be updated during installation; the application must be
restarted afterwards.
An example of the entire file is shown below. When updating, take care to preserve the syntax (quotes, commas,
brackets, etc.); a text editor with JSON syntax checking is recommended.

{
"disableMultiFrameVideoAutoLoad": false,
"features": {
"patientHistory": false,
"keyObjectAndPresentationStateQuickSave": true,
"keyObjects": true,
"presentationState": true,
"searchSettings": true,
"viewerSettings": true,
"reportSettings": true,
"hangingProtocolsSettings": true,
"export": true,
"archive": true,
"search": true,
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


60

(continued from previous page)


"reports": true,
"remoteReports": true,
"liveShare": false,
"hangingProtocols": "V1",
"openTabsTrackingMethod": "NONE",
"prepareInstances": false,
"batchImageRequests": true,
"thumbnailsPerSeries": "FIRST",
"summaryThumbnailsFor": ["CT", "MR", "PT", "NM"],
"preloadSeries": "OFF",
"boundingBoxAnnotations": true,
"viewToClipboard": "IMAGE",
"pngPSToClipboard": "NONE",
"viewToDICOM": true,
"mistMpr3D": true,
"clearCache":true,
"measurementsPropagation": true,
"digitalSubtraction": "NONE"
},
"blackListedSopClasses": [
"1.2.840.10008.5.1.4.1.1.66",
"1.2.840.10008.5.1.4.1.1.4.2"
],
"forwardPacs" : [
{
"storeScpIp": "127.0.0.1",
"storeScpPort": 104,
"storeScpAet": "PACS",
"description": "An example destination for Forward",
"sender": "PacsOneRouter,MainArchive"
},
{
"storeScpIp": "192.168.200.65",
"storeScpPort": 5678,
"storeScpAet": "OSIRIX",
"description": "Osirix workstation",
"sender": "MainArchive"
}
],
"languages" : ["lt","en","ru"],
"dicomLibraryConfiguration": {
"dicomLibrarySender": "[email protected]",
"dicomLibrarySubject": "My special study",
"languages": ["en","de"]
"language": "en"
},
"formatIntegrationLinkInViewer": false,
"textureInterpolationType": 1,
"requestsConfig": {
"maximumMetadataStreams": 5,
"maximumPixelStreams": 15,
"maximumMultiFrameStreams": 4,
"batchSizeMb": 5,
"multiFrameBatchSizeMb": 2
},
"workersConfig": {
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


61

(continued from previous page)


"maxWorkers": "50%",
"maxSegmentationWorkers": "50%"
},
"cacheSupervisorConfig": {
"enabled": true,
"runFrequencyInSec": 10
},
"scrollingConfig": {
"modality":["CT", "MR", "PT", "OPT", "NM", "MG", "OCT"],
"sopClass":[]
},
"notificationsConfiguration": {
"autoCloseAfterSec":10
},
"personNameConfiguration": {
"formatIn":"",
"formatOut":null
},
"searchHistoryByPatientId": true,
"dontAutoOpenTheseAnnotations": ["Lunit"],
"fusionConfig": {
"modality": ["CT", "MR", "PT"],
"sopClass": []
},
"segmentationConfig" {
"smartPaintPreloadOptions": "wait-for-toolbar",
"messagingLevel": "minimal"
}
"windowPosition": [{
"name": "patient-history",
"width": 1245
"height": 800
}
],
"instancesProgressivePreloadConfig": {
"preloadCount": 5,
"supportedModalities": ["CT", "MR", "PT", "NM"],
"supportedSOPClasses": [],
"enableSeriesManualPreload": true
}
}

• disableMultiFrameVideoAutoLoad: false
(reserved) Disables multiframe and video autoload. Used for automated testing purposes, do
not change this setting.
• patientHistory: false
If true, the viewer window will load patient history and the corresponding button is enabled.
Disabled by default.
• keyObjects: true
The viewer window will load key objects.
• keyObjectAndPresentationStateQuickSave: true
The viewer window will display the Key Object And Presentation State Quick Save button.
• presentationState: true

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


62

The viewer window will load presentation state objects.


• searchSettings: true
Enable search settings page in the settings window.
• viewerSettings: true
Enable viewer settings page in the settings window.
• reportSettings: true
Enable report settings page in the settings window.
• hangingProtocolsSettings: true
Enable hanging protocol settings page in the settings window.
• export: true
Globally enable the Export/ISO (Burn) function. If disabled, it won’t be available even to users
who have the EXPORT_ISO permission.
• archive: true
Globally enable the Export/Archive (Save Active . . . ) function. If disabled, it won’t be available
even to users who have the EXPORT_ARCH permission.
• search: true
Globally enable or disable the Search window. If disabled, the window will be replaced with an
error message even for users who have the SEARCH permission.
The window is enabled by default to make the installation simpler. However currently it
implements no per-user filters and allows access to every patient on the PACS. Do not forget
to disable it if not needed.
For example, if MedDream will open only via HIS integration, true is still recommended as an
initial choice, as interactive login usually provides a faster way to verify whether images can be
displayed. In this case do not forget to switch to false after testing.
• reports: true
Globally enable or disable the Reporting window. If disabled, it won’t be available even to users
who have the REPORT_VIEW or REPORT_UPLOAD permission.
• remoteReports: true
Globally enable or disable the “remote reports” functionality that replaces the Reporting window
(remoteReports=true is incompatible with reports=true). If disabled, it won’t be available even to
users who have the REPORT_VIEW permission. Also see 5.1.5.4 Remote reports.
• liveShare: false
Globally disable or enable the LiveShare functionality.

Note: With true, you must also enable the liveshare Spring profile and configure the legacy
HIS integration with at least the parameter “study”, in application.properties:

spring.profiles.include = liveshare,auth-his
authentication.his.valid-his-params = study

• “hangingProtocols”: “V1”
Globally enable or disable the Hanging Protocols functionality.
In MedDream 8.3+ the allowed values are "V1" (same as true), "V2", "NONE" (same as false).
However “V2” should not be used as functionality isn’t ready for general public yet.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


63

• openTabsTrackingMethod: “NONE”
Possibility to enable more strict tracking of open tabs. Ideally, when all tabs are closed by
pressing the “X” button, MedDream should log off as if “Logoff” were chosen from the menu.
The string “SOCKETS” enables websocket-based tracking. It is also needed to add track-tabs
to spring.profiles.include (application.properties).

Note: There is a grace period of 10 seconds. If you open MedDream once more during that
time, then the session remains.
Without this period, a single tab could get logged off even when reloading its contents (pressing
the F5 button).

• prepareInstances: false
If true, the series preload will make sure each image is prepared. This might increase
performance up to 20%.
• batchImageRequests: true
Enables batch downloading of image pixels; this may result in multiple images per request and
therefore reduce the overhead. Assign false for pre-7.7.0 behavior.
• thumbnailsPerSeries: “FIRST”
By default MedDream 7.7.0+ attempts to speed up loading of CT, PT and MR studies by
displaying only the summary thumbnail in every series. Assign “ALL” for pre-7.7.0 behavior.
Another possible value is “MIDDLE”. It requires com.softneta.preparation.thumbnailCreation =
all. Unfortunately, as the preparation is performed per-instance and as soon as possible (without
waiting until the entire study is sent), it is not feasible to determine which object is at the middle;
all thumbnails must be available for thumbnailsPerSeries=MIDDLE.
• summaryThumbnailsFor: [“CT”, “MR”, “PT”, “NM”]
List of Modality values to which the thumbnailsPerSeries setting applies. Before 7.9.0 the
values CT”, “PT” and “MR” were hardcoded in the frontend.

Note: When the backend is configured with com.softneta.preparation.thumbnailCreation =


first (by default), then the set of values in summaryThumbnailsFor should include values of
com.softneta.preparation.thumbnailCreationModalities (not all thumbnails are created for those
modalities, in order to have faster processing). Generally, summaryThumbnailsFor can be a
larger set, however it mustn’t be smaller. Otherwise the frontend will request thumbnails that
aren’t routinely produced by the backend; studies will open slower because of these unexpected
requests.

• preloadSeries: “OFF”
When that summary thumbnail is enabled, then it can also trigger preload of its series. “NONE”
– no preload, “OFF” – the end user must click on the summary thumbnail to trigger the preload,
“ON” – the preload starts automatically.
• boundingBoxAnnotations: true
Globally enables the Segmentation toolbar button and the Bounding Box tool below it. The user
must also have the BOUNDING_BOX_EDIT permission to see the button. Furthermore, the
button is disabled by default in the Settings window (Viewer / Toolbar properties / Segmentation
Tools / Bounding Box).
• viewToClipboard: “IMAGE”
Functionality of the button “Copy image to the clipboard”. “IMAGE” – the button copies an
image of the active viewport (with burned-in Info Labels, measurements, etc.); “JSON_IMAGE”

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


64

– it copies a certain JSON structure with measurements and Base64-encoded image as in the
“IMAGE” case; “NONE” – the button is not displayed.
• pngPSToClipboard: “NONE”
Functionality of the button “Export original image to the clipboard”. “IMAGE” – the button copies
the active image of original size and without any burned-in information (as with “PNG” and
“Active Image” in the Export window); “JSON_IMAGE” – it copies a certain JSON structure with
measurements and Base64-encoded image as in the “IMAGE” case; “NONE” – the button is not
displayed.

Note: Additional requirements for displaying the button are: 1) modality DX, CR, RX, CT or MR;
2) not a video or multiframe file.

• viewToDICOM: true
Globally enable the button “Save viewport content as secondary capture DICOM”. The button
also needs the COPY_TO_DICOM permission. If one or another is missing, then the button is
not visible and only secondary capture images saved earlier can be accessed.
This feature is needed by the Montage functionality, too.
• mistMpr3D: true
Globally enable or disable the 3D view (4th viewport) of the “Oblique MIST” functionality.
• clearCache: true
Globally enable or disable the “Clear cache” functionality. When enabled, the user must also
have the CLEAR_CACHE permission.
• measurementsPropagation: true
Show copy/paste buttons when creating a measurement. Enabled by default.
• digitalSubtraction: “NONE”
Enable the Digital Subtraction Angiography functionality. “NONE” (default): the functionality is
disabled. “AUTO”: the functionality is applied automatically. “MANUAL”: a button is displayed if
the images contain necessary information, and the end user can start DSA manually.
• blackListedSopClasses: [“1.2.840.10008.5.1.4.1.1.66”]
Thumbnails of images with these SOP Classes will not be shown in the viewer.
This list is appended to a hardcoded list of non-image objects from DICOM Standard. (By the
way, the above . . . 1.1.66 SOP Class is already there.) Main purpose of this setting is to hide any
Private SOP Classes not known in advance.
• storeScpIp: “127.0.0.1”
• storeScpIp: “192.168.200.65”
Destination IP address (or hostname) for the Forward function. Only for
com.softneta.meddream.dcmsnd.forwardingMethod=native.
• storeScpPort: 4242
• storeScpPort: 5678
Destination TCP port for the Forward function. Only for
com.softneta.meddream.dcmsnd.forwardingMethod=native.
• storeScpAet: “PACS”
• storeScpAet: “OSIRIX”
Destination AE Title for the Forward function. Will be visible in the Forward window.
• description: “An example destination for Forward”

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


65

• description: “Osirix workstation”


Human-readable description of a destination device for the Forward window.
• sender: “PacsOneRouter,MainArchive”
• sender: “MainArchive”
Must not be empty for com.softneta.meddream.dcmsnd.forwardingMethod=cmove, and is
ignored otherwise.
Identifies PACSes that can send to this destination (because this destination is configured at the
PACS). This comma-separated list, however, accepts not AE titles but PACS integration plugin
storage identifiers.
The Forward window will narrow the list of available destinations, depending on studies selected
for forwarding, and will therefore prevent situations where the PACS does not know the
destination AET. Suppose the study X, found via PACS integration plugin with a storage identifier
Y, is selected. Then the window will list only destinations where the sender element contains this
storage identifier, Y.
• languages: [“lt”,”en”,”ru”]
List of localization languages that will be offered (in this order) in MedDream user interface. All
major MedDream windows (Search, Viewer, Settings) have the “Languages” drop down near the
upper right corner, unless there is a single language configured.
When MedDream is opened on user’s computer for the first time (or after clearing cookies), then
the first entry from this list becomes the default.
• dicomLibraryConfiguration.dicomLibrarySender: “[email protected]
• dicomLibraryConfiguration.dicomLibrarySubject: “An interesting case at DICOM Library”
• dicomLibraryConfiguration.languages: [“en”, “de”]
• dicomLibraryConfiguration.language: “en”
The Share function requires non-null values here (can be just empty strings/arrays). Users will
also need UPLOAD_DICOM_LIBRARY permission individually.
The languages are offered in the Share window and refer to emails which will be sent. As of 7.9,
values understood by dicomlibrary.com are “en” and “de”. If .languages is empty, there is no
language choice in the window.
• formatIntegrationLinkInViewer: false
(experimental) After the viewer opens, the URL in browser’s address bar is automatically
adjusted so that it becomes a HIS integration link suitable for copying. Only the “study” parameter
(and therefore a single PACS plugin) is supported.
• textureInterpolationType: 1
Type of WebGL texture interpolation: 0 (disabled), 1 (linear, default), 2 (bicubic), 3 (bicubic
spline), 4 (different implementation of “linear”).
When the image is zoomed in to the extreme, pixels will become large squares if the setting is
zero. With 3, boundaries of individual pixels are no more visible, however very small details, like
a couple of pixels in total, might disappear completely.
• maximumMetadataStreams: 2
Number of parallel streams to download study/series metadata.

Note: In MedDream before 7.8, this setting was called seriesParallelStreams and was
applicable to batchImageRequests=true only.

• maximumPixelStreams: 15

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


66

Number of parallel streams to download image pixels. Applies to all kinds of single-frame pixel
requests: the legacy /pixels (for batchImageRequests=false) and the recently introduced /multi-
pixels (for batchImageRequests=true).
In MedDream before 7.8, this setting was named parallelStreams and was applicable
to batchImageRequests=true only.
• maximumMultiFrameStreams: 4
Number of parallel streams to download multi-frame pixels. Applies to any value of
batchImageRequests.

Note: In MedDream before 7.8, this setting was named multiFrameParallelStreams and was
applicable to batchImageRequests=true only.

• batchSizeMb: 5
Image pixel downloads are grouped so that the combined estimate of download size doesn’t
exceed this setting (if batchImageRequests is not false).
• multiFrameBatchSizeMb: 2
Equivalent of batchSizeMb for downloading frames of a multi-frame image (if
batchImageRequests is not false).
• workersConfig: . . .
Number of browser threads. “maxWorkers” are for decompression of pixel data,
“maxSegmentationWorkers” – for the segmentation function. Values in percent are relative to
actual number of CPU threads at a particular client machine.
• cacheSupervisorConfig: . . .
Monitors caching of images at the frontend. Every runFrequencyInSec seconds images not
displayed in any viewport are marked for removal, and those that were marked previously, are
removed from memory.
Specify true for enabled to enable this functionality.
• scrollingConfig: . . .
The vertical slider is displayed on the image if its Modality or SOP Class attribute matches a value
listed here. The default is a few modality values and an empty list of classes, and corresponds
to behavior of earlier versions where those modalities were hardcoded.
• notificationsConfiguration.autoCloseAfterSec: 10
A message is displayed on screen for this number of seconds, then hidden away.
• personNameConfiguration: . . .
Defines the format of person names (currently Patient Name and Referring Physician Name
attributes). In 8.0.0, some plugins (QR, Dicomweb, PacsOne, DCM4CHEE 2.x and 5.x)
were updated to return person names in DICOM standard format – with ^ separators, all 5
components, all 3 component groups.
formatIn provides a pattern for identifying name components in the input string, based on
separator positions. It applies to every component group. The default value (used instead
of null or empty string) is "{lastName}^{firstName}^{middleName}^{prefix}^{suffix}" and
complies to the Standard.
In general, a component consumes the part of the input string up to the next separator. When
there are not enough separators, then some component will consume all remaining input.
Results will be unexpected if the components were entered in a non-compliant manner at the
modality, like “John Doe^Dr.” instead of “Doe^John^^Dr.”; however, if all modalities behave that
way, a corresponding formatIn could adapt to it.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


67

formatOut is a format string for every component group of the result. The default value
(used instead of null or empty string) is "{prefix} {lastName} {firstName} {middleName}
{suffix}".
The simplest use case is to change the component order via formatOut – for example,
"{firstName} {lastName}".
After updating to 8.0.0, compliant plugins listed above will produce names with prefixes at the
beginning, like “Dr. Doe John” instead of “Doe John Dr.”. Furthermore, some plugins are now
returning all components instead of just last and first name. Both issues can be worked around
with formatOut. The behavior won’t differ with non-compliant plugins like Orthanc, as they use
the legacy space-delimited name format and {lastName} in formatIn gets everything.
• searchHistoryByPatientId: true
When true, MedDream uses the traditional patient history search key – a single Patient ID
attribute. When false, the search key is a logical AND of attributes Patient Name, Patient’s
Sex and Patient’s Birth Date.

Warning: As of 8.1.0+, the value “false” is only for DCM4CHEE 2.x and 5.x PACS plugins.
Other plugins might become confused and won’t return any results; this also includes Multi-
PACS setups where DCM4CHEE plugins are mixed with other ones.

• dontAutoOpenTheseAnnotations: [“Lunit”]
Names of annotations that won’t be opened automatically when “Auto open annotations” is
enabled in the Settings window. The intended use case is filtering of annotations added by
automated diagnosis systems, while annotations created manually would still open automatically.
Empty by default.
• fusionConfig.modality: [“CT”, “MR”, “PT”]
• fusionConfig.sopclass: []
In general Fusion is possible between any modalities in the same frame of reference but their
values must be configured first. By default they’re CT, MR or PT. This can be changed by the
“modality” setting.
You can also configure a SOP Class UID whitelist in the “sopclass” setting. Both whitelists are
combined with logical OR (if both are empty, then Fusion isn’t allowed at all).
• segmentationConfig: . . .
“smartPaintPreloadOptions” can be “wait-for-toolbar” (default) or “load-on-open”. The latter will
enable parsing of probability-based annotations as soon as possible.
“messagingLevel” can be “minimal” (default) or “medium”.
• instancesProgressivePreloadConfig.preloadCount: 5
• instancesProgressivePreloadConfig.supportedModalities: [“CT”, “MR”, “PT”, “NM”]
• instancesProgressivePreloadConfig.supportedSOPClasses: []
• instancesProgressivePreloadConfig.enableSeriesManualPreload: true
When loading a particular image, also load up to preloadCount images before and after it. This
behavior, however, applies only if Modality attribute matches an entry in supportedModalities, or
SOP Class UID matches an entry in supportedSOPClasses.
enableSeriesManualPreload=false disables the “cloud” icon in the series header, however only
for series where supportedModalities or supportedSOPClasses match.
• windowPosition: [{“name”: “name1”, “width”: width1, “height”: height1},{“name”: “name2”, . . . },. . . ]

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


68

Override default widths and/or heights of GUI windows. When configuring only the width, you
can target a group of windows; for example, “modalSmallWidth” targets Register, About and
many other windows, while “register” is for the Register window only.
Dimensions are in pixels. Unspecified or zero means “default” and is ignored. Minimum height
is 300, smaller values are also ignored. There is no minimum width, you can use the default
below as a ballpark value; significantly smaller values were not tested and might result in
incorrect appearance or behavior.

Group name Def. Window names


width
modalSmallWidth 570 px realise-notes, color-picker, confirmation, demo-message,
register, windowing-edit, share-dicom-library,
slab-thickness, calibration, add-keyboard-shortcut,
mark-key-object, save-key-objects, about
modalMediumWidth 750 px hanging-protocol-edit, eula, forward, fusion,
patient-history, patient-studies, plugin-content,
series-list, hanging-protocol-group, dicom-attributes,
hanging-protocol-change, edit-shortcuts. It’s also the
default width for any undocumented windows.
modalExtraMediumWidth 850 px report-modal, template-modal
modalLargeWidth 1200 px plugin-content
modalWideWidth 90% of report
screen

5.1.3. Built-in authentication and authorization

MedDream supports a few universal authentication/authorization methods. They can be used when instructions
for a particular PACS integration do not offer a dedicated (more proper) method.
Most methods are designed for the interactive login. As a result, the login form can be opened only when a
particular method is chosen (for example, spring.profiles.include = auth-pacsone).
For authorization you can choose from the following list of permissions:
• ADMIN – Settings and Register;
• SEARCH – the Search window;
• PATIENT_HISTORY – Patient History;
• UPLOAD_DICOM_LIBRARY – Share (Share via DICOM Library window);
• EXPORT_ISO – the Export function related to “Download” and “Burn”;
• EXPORT_ARCH – the Export function related to “Save”;
• FORWARD – the Forward function;
• REPORT_VIEW – read-only access to Reporting function;
• REPORT_UPLOAD – full access to Reporting function (does not include “remote reports”);
• ANONYMOUS_VIEW – on-the-fly anonymization of visible patient data (except PDFs, SRs and forwarded data);
• DOCUMENT_VIEW – ability to view Structured Report and PDF documents (however they are forwarded
regardless of this permission);
• BOUNDING_BOX_VIEW – allows display of annotations saved by Segmentation > Bounding Box;
• BOUNDING_BOX_EDIT – full access to Segmentation > Bounding Box and visibility of this button (however
there also is a global setting, features.boundingBoxAnnotations, in system.json);
• FREE_DRAW_VIEW` – allows display of annotations saved by Segmentation > Free Draw;

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


69

• FREE_DRAW_EDIT – full access to Segmentation > Free Draw and visibility of this button (subject to
features.boundingBoxAnnotations, too);
• SMART_DRAW_VIEW allows display of annotations saved by Segmentation > Smart Draw;
• SMART_DRAW_EDIT – full access to Segmentation > Smart Draw and visibility of this button (subject to
features.boundingBoxAnnotations, too);
• COPY_TO_DICOM – display of the button “Save viewport content as secondary capture DICOM” (there is also
a global setting, features.viewToDICOM=true, in system.json) and support of Montage functionality;
• USER_SETTINGS – allows to save settings to a customized global.json. Without this permission, a
customized global.json can only be read;
• CLEAR_CACHE – allows to use the “Clear cache” function (there also is a global setting, features.clearCache,
in system.json);
• SHORTCUTS_EDIT – allows to edit the shortcuts (this permission is required even for users that have ADMIN);
• HANGING_PROTOCOLS_EDIT – allows editing of hanging protocols for user that don’t have ADMIN (there is
also a global setting, features.hangingProtocols, in system.json);
• PACSONE_VIEW_ONLY_PUBLIC – an opposite of the legacy VIEW_PRIVATE if the message “Limited view
access” is still required.

Warning: When upgrading to 8.2+, it is advised to remove obsolete permissions 3D_RENDERING and
VIEW_PRIVATE from all possible places of configuration:
• authorization.defaultLoginPermissions setting
• authorization.defaultHisPermissions setting
• authorization.users[].role settings
• authorization.remapRoles.* settings
• embedded authentication database for the auth-meddream profile
For some time MedDream will gracefully ignore this permission if left in configuration. However in the future
the value will become really unknown and might crash the backend.

Warning: DOCUMENT_VIEW must be present for pre-7.5.1 functionality. Currently MedDream does not
support permissions of “deny” type (existing ones are of “grant” type), therefore it is not possible to grant
DOCUMENT_VIEW for all users and afterwards deny for a few ones.

Warning: Take caution with DOCUMENT_VIEW together with ANONYMOUS_VIEW. Anonymization of PDFs and
SRs is not supported, therefore DOCUMENT_VIEW will leak sensitive patient data to users who do not see it
normally.
Absence of DOCUMENT_VIEW only prevents interactive display and Export of this data. Forward still shares all
DICOM objects in the study and so might present a workaround for users who don’t have this permission.

Warning: REPORT_UPLOAD and REPORT_VIEW (also BOUNDING_BOX_EDIT and


BOUNDING_BOX_VIEW, etc.) are mutually exclusive, although not all authentication methods enforce that.
To avoid unexpected behavior, especially in future MedDream versions after the upgrade, do not assign both.
This includes attempts to add . . . _VIEW to all users, then “upgrade” to read/write mode for selected users.
Until MedDream does not support deny-type permissions, it does not clean up conflicting or lesser-priority
permissions.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


70

Note: 8.2+ contains an inverted logic regarding the now obsolete VIEW_PRIVATE permission. It behaves as
if that permission is always present; the message “Limited view access” is automatically displayed only when
using Pacsone plugins with auth-pacsone and the account configured in PacsOne user administration doesn’t
have the “View private” privilege.
It is important to remember that in all other situations, like authentication other than auth-pacsone, or using a
non-PacsOne plugin, that message was misleading (and still is): other plugins do not implement a corresponding
filter, while other authentication types do not support First Name and Last Name of the currently logged in user,
that are needed by the filter in PacsOne plugin.
For an unlikely event where the end users are expecting this message despite usage of a different authentication
or a non-PacsOne plugin, you can get it back by adding the PACSONE_VIEW_ONLY_PUBLIC permission for
corresponding users.

5.1.3.1. In-memory storage

Provides both authentication (username/password) and authorization (permissions). All this data must be
entered into application.properties, in plain text form.
The spring.profiles.include setting must include auth-inmemory. 7.5.2+ does this by default and includes a
single user named “demo”, with a password known in advance that must be changed during the installation.
Elements of authentication.inmemory.users[] describe the credentials. Elements of authorization.
users[] link to credentials and list the permissions; the per-user accessibleStorages setting can restrict the
list of allowed Multi-PACS plugin instances (beware: values that don’t match the .id parameter of a configured
plugin will stop application loading). authorization.defaultLoginPermissions lists permissions common to
everyone.
The parameter accessibleStorages can also be used at group level. The group is referenced by
authorization.users[].groups and defined in authorization.groups[].
Example with two users:

spring.profiles.include = auth-inmemory
authentication.inmemory.users[0].userName = user1
authentication.inmemory.users[0].password = pass1
authentication.inmemory.users[1].userName = user2
authentication.inmemory.users[1].password = pass2
authorization.users[0].userName = user1
authorization.users[0].role = ADMIN,SEARCH,DOCUMENT_VIEW
authorization.users[0].groups = administrators
authorization.users[1].userName = user2
authorization.users[1].role = SEARCH,ANONYMOUS_VIEW
authorization.users[1].accessibleStorages = PacsOneRouter,MainArchive
authorization.defaultLoginPermissions = PATIENT_HISTORY,REPORT_UPLOAD,\
UPLOAD_DICOM_LIBRARY
authorization.groups[0].name = administrators
authorization.groups[0].accessibleStorages = PacsOneRouter,MainArchive,ResearchPacs

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


71

5.1.3.2. Embedded database storage

Keeps credentials and permissions in a built-in H2 database. Passwords are salted and hashed.
There is no GUI so far, management involves running SQL commands in the H2 Console.
After fresh installation of MedDream, make sure that application.properties contains

spring.profiles.include = auth-meddream

then do the following:


1. Try to log into MedDream. Make sure the login failed with “Access Denied” error and the log contains
messages “Query returned no results for user . . . ”, “User . . . not found”.
This first attempt will be unsuccessful as the database doesn’t contain any accounts. However,
the file sys/databases/authdb.mv.db with all relevant tables will be automatically created for blank
H2 user and password values.
If the logged error is different (for example, you’ve got a ClassCastException instead), then clear
all cookies and saved passwords and try again.
2. Open H2 Console with the database sys/databases/authdb and empty username/password (see 5.1.10
Opening the H2 Console for details).
3. In the Console, make sure the database contains the tables “USERS” and “PERMISSIONS”, then use the
following SQL expressions to create new users:

INSERT INTO users VALUES('LOGIN_NAME', 'ENCODED_PASSWORD', 1);


INSERT INTO permissions VALUES('LOGIN_NAME', 'PERMISSION_NAME');

ENCODED_PASSWORD consists of a prefix (like {bcrypt}) that identifies the algorithm,


and the encoded value. For the bcrypt algorithm (recommended) you can use online
services like https://www.javainuse.com/onlineBcrypt (do not forget to add the prefix
afterwards). Example: INSERT INTO users VALUES('admin', '{bcrypt}$2a$10$DqbOQDCzx.
inz.anVIYUoOiw.33lUiOn.PIhLWZVlIKARQEJNsjzC', 1).
The third column can either be 1 or 0. Zero means a disabled account (login not possible).
PERMISSION_NAME can be ADMIN, FORWARD, EXPORT_ISO, etc. Use multiple “INSERT INTO
permissions” statements when adding more than one permission.
4. As shown in application.SAMPLE.properties, you can use authorization.defaultLoginPermissions to assign
permissions that are needed for every user account.

Note: Forgetting Step 1 will have the following consequences:


• Step 2 will also create authdb.mv.db but without the relevant tables (unless you modify the JDBC URL in a
particular cumbersome way). This state is unsuitable for continuing with Step 3;
• you can accidentally specify a non-blank username or password during Step 2, and not get any warning or
error; however afterwards Core will be unable to access the database.
Provided that credentials were empty, you can retry Step 1 later which will populate the tables. Stopping Core
and removing authdb.mv.db might also help.

Note: By default, application.SAMPLE.properties enables auth-inmemory and this is done on another line.
There is no error message if you assign to spring.profiles.include multiple times, and the outcome might be
counter-intuitive. Make sure to comment the unneeded line out.
Unlike in other mechanisms, the per-user accessibleStorages setting can’t be stored in the database.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


72

5.1.3.3. LDAP storage

Verifies credentials against an LDAP server (you can use third-party tools to manage credentials and groups).
Mapping between user’s LDAP groups and MedDream permissions is configured in application.properties. The
latter can also append permissions to individual users.
The spring.profiles.include setting must include auth-openldap or auth-activedirectory when using
the corresponding server. There also is a variant of AD for servers with mandatory GSSAPI/Kerberos,
auth-kerberosldap.
The main setting is authentication.ldap.url: hostname, port and base DN. For SSL you need to use “ldaps://”
for the protocol, and likely a different port (for example, 636). Other settings depend on the profile.
Example for OpenLDAP:

spring.profiles.include = auth-openldap
authentication.ldap.url = ldap://MY-SERVER:389/ou=DEPT-NAME,dc=COMPANY-NAME
authorization.defaultLoginPermissions = SEARCH,EXPORT_ARCH,EXPORT_ISO,PATIENT_HISTORY,\
UPLOAD_DICOM_LIBRARY,DOCUMENT_VIEW
authorization.remapRoles.DOCTORS-GROUP-NAME = CLEAR_CACHE
authorization.remapRoles.ADMINS-GROUP-NAME = ADMIN
authorization.remapRoles.TECHNICIANS-GROUP-NAME = FORWARD
authorization.users[0].userName = USER-NAME-1
authorization.users[0].role = ADMIN
authorization.users[1].userName = USER-NAME-2
authorization.users[1].role = FORWARD,REPORT_UPLOAD,BOUNDING_BOX_EDIT
authorization.users[1].accessibleStorages = st3

To authenticate, MedDream binds to DN uid=LOGIN-NAME,ou=People,ou=DEPT-NAME,dc=COMPANY-NAME (the


part uid=...,ou=People is hardcoded) using LOGIN-NAME and password from the login form.
Then it collects groups to which this user belongs, by searching for group objects exactly in ou=groups,
ou=DEPT-NAME,dc=COMPANY-NAME with a filter (memberUid=LOGIN-NAME); both ou=groups and the filter are
hardcoded.
Finally, authorization.remapRoles.* and authorization.users[] are consulted for corresponding MedDream
permission sets: the group DOCTORS-GROUP-NAME receives CLEAR-CACHE, the user USER-NAME-1 additionally
receives ADMIN, etc.
Example for Active Directory:

spring.profiles.include = auth-activedirectory
#spring.profiles.include = auth-kerberosldap
authentication.ldap.url = ldap://MY-SERVER:389/ou=DEPT-NAME,dc=COMPANY-NAME
authentication.ldap.bindUserDn = cn=MEDDREAM-APP,ou=SERVICE,ou=DEPT-NAME,dc=COMPANY-NAME
authentication.ldap.bindUserPassword = MEDDREAM-APP-PASS
authentication.ldap.userSearchBase = ou=USERS
authentication.ldap.groupSearchBase = ou=USERS
authorization.defaultLoginPermissions = SEARCH,EXPORT_ARCH,EXPORT_ISO,PATIENT_HISTORY,\
UPLOAD_DICOM_LIBRARY,DOCUMENT_VIEW
authorization.remapRoles.DOCTORS-GROUP-NAME = CLEAR_CACHE
authorization.remapRoles.ADMINS-GROUP-NAME = ADMIN
authorization.remapRoles.TECHNICIANS-GROUP-NAME = FORWARD
authorization.users[0].userName = USER-NAME-1
authorization.users[0].role = ADMIN,REPORT_VIEW
authorization.users[1].userName = USER-NAME-2
authorization.users[1].role = FORWARD,REPORT_UPLOAD,BOUNDING_BOX_EDIT
authorization.users[1].accessibleStorages = st3

To authenticate, MedDream binds to bindUserDn using bindUserPassword, searches for a user object at or below
ou=USERS (empty userSearchBase is not allowed) with a hardcoded filter (sAMAccountName=LOGIN-NAME), then
binds to the found DN using the password from the login form.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


73

Then it extracts group names from this user object. Its attributes memberOf (hardcoded) are expected to contain
group DNs which start with cn=GROUP-NAME,.... Due to technical limitations, the user object found earlier
is not reused – a second search is performed at or below groupSearchBase (should obviously be equal to
userSearchBase) with the same hardcoded filter (sAMAccountName=LOGIN-NAME).
As with OpenLDAP, authorization.remapRoles.* provide permission sets for entire groups, while
authorization.users[] can add more permissions to individual users.
If your server demands GSSAPI, just use the “auth-kerberosldap” profile instead.
Since 8.3 any kind of LDAP storage can authenticate only users that belong to specified groups:

# must be in "users" or "doctors" group


authentication.ldap.mandatoryGroups = users,doctors

# must be in "meddream" group, or both in "users" and "doctors" groups


authentication.ldap.mandatoryGroups[0] = meddream
authentication.ldap.mandatoryGroups[1] = users,doctors

Traditionally, groups in MedDream are used only to map permissions and do not participate in authentication.
This parameter is empty by default and no group membership is enforced. Two-dimensional syntax similar to
validHisParams is supported: the first level separates elements with logical OR, the second level – with logical
AND.

Note: By default, application.SAMPLE.properties enables auth-inmemory and this is done on another line.
There is no error message if you assign to spring.profiles.include multiple times, and the outcome might be
counter-intuitive. Make sure to comment the unneeded line out.

Warning: Spaces embedded in role names are ignored. For example, “Super Users” and “SuperUsers” will
be treated as the same role.

5.1.3.4. SAML

Credentials entered in the login form will be validated by an external identity provider.
Supported endpoints are /saml2/authenticate/okta. See https://developer.okta.com/code/java/spring_
security_saml for details.

spring.profiles.include = auth-saml
spring.security.saml2.relyingparty.registration.okta.assertingparty.metadata-uri =\
https://dev-0731725.okta.com/app/exk3k4dxuhko35exg5d7/sso/saml/metadata
authorization.defaultLoginPermissions = SEARCH,EXPORT_ARCH,EXPORT_ISO,PATIENT_HISTORY,UPLOAD_
˓→DICOM_LIBRARY

authorization.remapRoles.doctor = CLEAR_CACHE
authorization.remapRoles.administration = ADMIN
authorization.remapRoles.assistant = FORWARD

User roles are taken from the SAML attribute “memberOf”. When using them, authorization.remapRoles.* is
needed for mapping to MedDream permissions.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


74

5.1.3.5. Database connection

Generic authentication against a DBMS server (you can use third-party DBMS tools to manage credentials).
Internal MedDream permissions are assigned to users in application.properties.
Example with two MySQL users:

spring.profiles.include = auth-db-connection
authentication.database.driverClassName = com.mysql.jdbc.Driver
authentication.database.jdbcUrl = jdbc:mysql://127.0.0.1:3306/pacs2
authorization.defaultLoginPermissions = EXPORT_ARCH
authorization.users[0].userName = user1
authorization.users[0].role = ADMIN,SEARCH,DOCUMENT_VIEW,REPORT_VIEW,BOUNDING_BOX_VIEW
authorization.users[1].userName = user2
authorization.users[1].role = SEARCH,REPORT_UPLOAD,BOUNDING_BOX_EDIT
authorization.users[1].accessibleStorages = st3

authorization.defaultLoginPermissions lists permissions common to everyone.


Supported values for authentication.database.driverClassName:
• com.mysql.jdbc.Driver,
• org.postgresql.Driver,
• com.microsoft.sqlserver.jdbc.SQLServerDriver.

Note: By default, application.SAMPLE.properties enables auth-inmemory and this is done on another line.
There is no error message if you assign to spring.profiles.include multiple times, and the outcome might be
counter-intuitive. Make sure to comment the unneeded line out.

5.1.4. Predefined login credentials

In demo installations it is sometimes desirable to have the login form automatically filled with some working
credentials.
For that it is necessary to patch md5/index.html. Find the final </body></html> and insert the following before
it:

<script>
window.autoFillLogin = { username: ACCOUNT_USERNAME, password: ACCOUNT_PASSWORD }
</script>

For example,

... src="js/md.main.min.7.5.1-47d313eb039c.js"></script>
<script>
window.autoFillLogin = { username: 'demo', password: 'demo' }
</script>
</body> </html>

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


75

5.1.5. The Reporting function

Reports and attachments are saved into the same H2 database, sys/database/reportdb.*.
• The legacy option $attachment_upload_dir (config.php) is not implemented yet. Attachment contents are
always stored into the database.
• The structure is slightly different from the legacy “studynotes” and “attachment” tables. Access to legacy
tables, especially the ones updated by PacsOne GUI, is not possible even after configuring MySQL storage
instead of H2.
There are two attachment size limits that you might need to configure. MedDream will inform you which specific
limit was exceeded. The size of the largest file, and the total size of all files during the same upload operation,
are configured separately:

spring.servlet.multipart.max-file-size=1MB
spring.servlet.multipart.max-request-size=10MB

Print templates are supported like in 7.1 MedDream and existing ones might work without modification. The file
sys/report/default.html is an example with all supported value placeholders. Adjacent files CR.html, XC.html etc
(named after the first modality value in the study), if present, will be used for studies with particular modalities.
Stamps in print templates are expected in form of files sys/report/stamp/LOGIN_NAME.jpg.
When Reporting is used in HIS integration mode (including integration into PacsOne web interface), MedDream
currently assigns the same user identity in all saved reports. It can be configured by

authentication.his.username=his-user-name

5.1.5.1. Migrating the legacy MySQL tables to the 7.5.2+ database

Please contact [email protected] for the migration script. It will copy the MySQL database records (and
content of externally stored attachment files) to a .sql file, which can afterwards be imported via H2 Console.

5.1.5.2. Copying templates from one user to another (H2 storage)

This task was sometimes needed in PHP-based MedDream and is now possible in 7.5.2+, too.
Open the H2 Console in the browser (for details, see 5.1.10 Opening the H2 Console). Open
sys/database/reportdb there (example URL: jdbc:h2:file:/C:/PROGRA~1/PacsOne/php/meddream/sys/
database/reportdb) with username “sa” and no password.
View contents of the TEMPLATE table. Add the WHERE user='SOURCE_LOGIN_NAME' clause (with real username)
to the autogenerated SQL statement and confirm that the needed records exist.
Replace the SQL statement with the following, then change DESTINATION_LOGIN_NAME and
SOURCE_LOGIN_NAME to real values and execute:

insert into template (id, node, name, "USER", content)


select
nextval('TEMPLATE_SEQ'),
t.node,
t.name,
'DESTINATION_LOGIN_NAME',
t.content
from
template t
where
t."USER" = 'SOURCE_LOGIN_NAME'

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


76

In a similar fashion, view the TEMPLATE table again and confirm that DESTINATION_LOGIN_NAME now
has the needed records, too. At this point a refreshed MedDream Reporting window should also display the
corresponding templates.
In general, the settings spring.h2.console.* are also needed for editing the auth-meddream database, while
authentication.manager.* are also needed for editing auth-meddream and for various investigations via /manage
endpoint. If these tasks are not planned immediately, then all four settings should be commented out for security
after you finish with templates.

5.1.5.3. Using MySQL instead of H2

H2-based report storage works out of the box and is adequate for small institutions. However heavy use of
reports (especially with attachments), or the need to access them from third-party software, might call for a
different database engine. MedDream 7.6.0+ supports MySQL as an alternative.

Note: The minimum supported MySQL version is 5.7.

We strongly recommend to create a new database dedicated to reports, in order to avoid name conflicts with
existing tables.
Relevant settings in application.properties:

report.datasource.url=jdbc:mysql://DB_HOST:DB_PORT/DB_NAME
report.datasource.driverClassName=com.mysql.cj.jdbc.Driver
report.datasource.username=USER_LOGIN
report.datasource.password=USER_PASSWORD

Missing tables are created automatically when MedDream starts. Table structure might be automatically updated
during the first run of a newer MedDream version. The user name USER_LOGIN must initially refer to a
privileged user – with ALL PRIVILEGES (or at least REFERENCES, INDEX, ALTER, CREATE, SELECT, INSERT,
UPDATE, DELETE), or similarly capable of manipulating the schema. Only after making sure that the entire
functionality of reports is working, you can downgrade to a less-privileged user (SELECT, INSERT, UPDATE,
DELETE are sufficient).
If you absolutely need to use an existing database, then plan carefully:
1. MAKE A DATABASE BACKUP before the first run with MySQL-based report storage, and from now on –
before the first run of a newer MedDream version;
2. names of MedDream-related tables are “report”, “template”, “attachment”, “report_attachment” and
“flyway_schema_history”. Make sure your schema does not already contain tables with these names.
For example, PacsOne uses the table “attachment” for its own purposes;
3. it is possible to assign new names to most tables except “flyway_schema_history” :

report.tableNames.report=NEW_REPORT_NAME
report.tableNames.attachment=NEW_ATTACHMENT_NAME
report.tableNames.template=NEW_TEMPLATE_NAME
report.tableNames.report_attachment=NEW_REPORT_ATTACHMENT_NAME

4. those custom table names are a critical piece of configuration. If you accidentally comment them out, or
specify the name of an existing third-party table, then your data is at danger! In the best case nothing
serious will happen to a foreign table but MedDream won’t be able to use it due to still incompatible
structure.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


77

5.1.5.4. Remote reports

The “Remote reports” functionality requires custom works by the customer and has the following limitations:
• only the Query/Retrieve integration;
• report status available only after opening the study or in the Patient History window (not in the Search
window);
• operation is read-only (no editing, just display);
• supported content types are application/pdf, application/json, application/xml, application/xhtml+xml,
image/gif, image/jpeg, image/png, text/html, text/plain, text/xml.
It must be enabled in application configuration:
• specify features.remoteReports=true in system.json (incompatible with features.reports=true);
• add REPORT_VIEW permission for the user (REPORT_EDIT, however, will be ignored).
In the configuration of the QR plugin, a custom DICOM tag number needs to be specified:

com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.report.tag=CUSTOM_
˓→DICOM_TAG_IN_DECIMAL

com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.report.type=string

The PACS will receive this attribute as a return key, and should return a study-level attribute with this tag. If a
non-empty value is found in the response, then the plugin replaces it with the reportURL setting after filling the
placeholders {studyUid} and {storageId} (at least the first one should be present):

com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].reportURL=http://127.0.0.
˓→1:8088/report?study={studyUid}&storage={storageId}

#com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].reportURL=/mnt/attached-
˓→reports/{studyUid}.pdf

reportURL can specify a custom endpoint that returns content of the report attached to the study. The URL
can be generic or RESTful. A GET request without authentication will be performed. If the URL doesn’t begin
with “http”, it is treated as a file system path and must be readable by the JVM process on the machine where
MedDream is installed.
Additional configuration (optional):

report.remoteReports.contentType=text/plain
report.remoteReports.proxyHost=172.30.55.1
report.remoteReports.proxyPort=8088
report.remoteReports.cacheMaxAgeSec=300
report.remoteReports.httpTimeout=5000
report.remoteReports.maxSize=1000000

The first step in getting the content type is to use the value returned by the server, or configured as file
name extension in reportURL when it specifies a file system path. If the server returned some type, or it
was successfully determined from the path, then it is validated against the list of supported types. Otherwise
(the server didn’t return the type, or detection has failed) the contentType setting is used (defaults to
“application/pdf”). The final value is added to the response from MedDream backend and the browser will
react correspondingly.
proxyHost and proxyPort are only used if both are provided and the port number is larger than zero.
If httpTimeout is larger than zero, it is used both as connection timeout and read timeout (in milliseconds). By
default there is no timeout.
A larger than zero maxSize imposes a size limit on downloadable or file system resource: there will be no
attempts to display a larger file.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


78

If cacheMaxAgeSec is larger than zero, then a Cache-control: max-age=... header with this value is added to
the corresponding MedDream response (from backend to frontend). Might be required when MedDream itself is
being accessed via a caching proxy.

5.1.6. Adjusting Java memory limits

Some example configurations included in MedDream installation archive specify 1 GB, which is sufficient for
typical files.
In general, the application requires an amount of memory no less than the size of the largest DICOM file.
Use this as a ballpark figure, and add a generous overhead for simultaneous connections. Furthermore, up
to com.softneta.preparation.maxThreadCount files of the same study will be processed in the background
simultaneously, so this should be taken into account, too, when your studies contain multiple moderately-sized
files.
Experiments with a single connection show that a single 1.3 GB multiframe file opens rather slowly under a 2
GB memory limit and without problems under a 3 GB limit; consequently, 4 GB would be recommended in this
case.
The memory limit is configured by the Java option -XmxSIZE, where SIZE can use suffixes “M”, “G”, etc. (for
example, -Xmx1024M).
If the same value is also specified with -XmsSIZE, then performance might be better as no resources are wasted
while growing the heap – it’s always of this size. At least 2 GiB is recommended.
Furthermore, even with adequate -Xmx and -Xms values Java might still crash due to “OutOfMemoryError: Direct
buffer memory”. The solution is to configure a small limit (approx. 1 MiB) via jdk.nio.maxCachedBufferSize.
• When you are starting the backend from the console (during 5.1.1 Essential configuration and the first run,
or for a quick experiment with a stopped service), then just add -Xmx4G etc. as the first option. For example,

java -cp MedDream-8.3.1.jar -Xmx4G -Dloader.path=./sys/plugins -Djava.library.


˓→path=./lib -DANTLR_USE_DIRECT_CLASS_LOADING=true --add-opens=jdk.management/

˓→com.sun.management.internal=ALL-UNNAMED --add-opens=java.base/jdk.internal.

˓→misc=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-

˓→opens=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED --add-opens=jdk.

˓→internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED --add-opens=java.base/sun.

˓→reflect.generics.reflectiveObjects=ALL-UNNAMED --add-opens=java.base/java.

˓→io=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.

˓→base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-

˓→opens=java.base/java.time=ALL-UNNAMED --add-exports=java.desktop/sun.awt.

˓→image=ALL-UNNAMED org.springframework.boot.loader.PropertiesLauncher

java -cp MedDream-8.3.1.jar -XX:MaxRAMPercentage=50.0 -Dloader.path=./sys/


˓→plugins -Djava.library.path=./lib -DANTLR_USE_DIRECT_CLASS_LOADING=true --add-

˓→opens=jdk.management/com.sun.management.internal=ALL-UNNAMED --add-opens=java.

˓→base/jdk.internal.misc=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-

˓→UNNAMED --add-opens=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED --add-

˓→opens=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED --add-opens=java.

˓→base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED --add-opens=java.base/

˓→java.io=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-

˓→opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-

˓→UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED --add-exports=java.

˓→desktop/sun.awt.image=ALL-UNNAMED org.springframework.boot.loader.

˓→PropertiesLauncher

(The last version allows Java to utilize 50% of available physical memory.)
• When the service is already set up, then you need to adjust the application command line in the
corresponding part of the installation. See the chapter 5.2 Running as a service for possible locations.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


79

Depending on number of concurrent connections, the following options are recommended:

Concurrent JVM parameters related to memory consumption core-


connections Thread-
Count*
1 -Djdk.nio.maxCachedBufferSize=1048576 -XX:NativeMemoryTracking=detail - 20
Xmx3072m -Xms2048m
2 -Djdk.nio.maxCachedBufferSize=1048576 -XX:NativeMemoryTracking=detail - 20
Xmx3072m -Xms2048m
5 -Djdk.nio.maxCachedBufferSize=1048576 -XX:NativeMemoryTracking=detail - 40
Xmx6144m -Xms2048m
10 -Djdk.nio.maxCachedBufferSize=1048576 -XX:NativeMemoryTracking=detail - 40
Xmx8192m -Xms2048m
20 -Djdk.nio.maxCachedBufferSize=1048576 -XX:NativeMemoryTracking=detail - 40
Xmx12288m -Xms2048m
30 -Djdk.nio.maxCachedBufferSize=1048576 -XX:NativeMemoryTracking=detail - 40
Xmx16384m -Xms2048m
60 -Djdk.nio.maxCachedBufferSize=1048576 -XX:NativeMemoryTracking=detail - 40
Xmx20480m -Xms2048m
60+ -Djdk.nio.maxCachedBufferSize=1048576 -XX:NativeMemoryTracking=detail - 40
Xms20480m

* Specified as com.softneta.preparation.coreThreadCount in application.properties.

5.1.7. Enabling SSL

The single Tomcat web server port, server.port, can be configured for HTTPS instead of HTTP.
(Option 1) To create a self-signed certificate, you can use keytool from JRE:

keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore path/
˓→to/keystore.p12 -validity 3650 -storepass PASSWORD

It will ask for a few identifying attributes of the certificate; it is possible to just press Enter every time. When
asked if the information is correct, type yes. At the last prompt (regarding the key password), press Enter, too.

What is your first and last name?


[Unknown]:
What is the name of your organizational unit?
[Unknown]:
What is the name of your organization?
[Unknown]:
What is the name of your City or Locality?
[Unknown]:
What is the name of your State or Province?
[Unknown]:
What is the two-letter country code for this unit?
[Unknown]:
Is CN=localhost, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
[no]: yes

Enter key password for <tomcat>


(RETURN if same as keystore password):

For verification, use keytool again:

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


80

keytool -list -v -storetype pkcs12 -keystore path/to/keystore.p12

(Option 2) If you already have a certificate, then conversion to a Java keystore is often still needed. The
certificate must be in DER (not PEM) format.

keytool -import -alias tomcat -file myCertificate.crt -keystore keystore.p12 -storepass␣


˓→PASSWORD

To specify the keystore for the JAR, copy its file to configRoot and modify application.properties:

server.ssl.key-store-type=PKCS12
server.ssl.key-store=${com.softneta.meddream.configRoot}/keystore.p12
server.ssl.key-store-password=PASSWORD
server.ssl.key-alias=tomcat
security.require-ssl=true
server.port=8443

server.port is here to minimize confusion: the current default port number, 8080, is normally used with HTTP,
not HTTPS.
When not using the well-known HTTPS port 443, you might need to always add https:// to MedDream URLs
from now on.

5.1.7.1. SSL for the bundled Token Service

The Token Service can be configured by the same Spring Boot properties as above in its own
application.properties file.
In the simplest scenario, it is sufficient to reuse the same PKCS#12 file with server.ssl.key-store and server.
ssl.key-store-password. The example .properties file has those settings commented out.

5.1.8. The external links plugin

This plugin adds custom text-only buttons to MedDream toolbar. They execute various URLs which can contain
metadata of an active image (like Study Instance UID) and are therefore suitable for additional integration with
third-party systems.
The custom buttons appear below the toolbar button “Plugins” that is hidden by default. Go to Settings and
search for “Plugins” in Viewer / Toolbar Settings, then choose at least “Show in desktop mode”.
To configure the plugin, modify the file medcadPlugins/links.json. By default, it contains a single entry that
implements a link to English version of the MedDream user manual:

[
{
"name": "Example: A link to User Manual",
"position": "VIEWER",
"openType": "ACTIVE_VIEWPORT_IFRAME",
"url": "../languages/en/help"
}
]

The top-level array can contain multiple entries instead of this single one. Elements of an entry:

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


81

Element Allowed values Explanation


name Any string Text on the button
position ALL, VIEWER, SEARCH In which parts of MedDream will the button appear
open- NEW_WINDOW, Open the URL in a new window, or replace the existing window
Type SAME_WINDOW, (and entire MedDream), or replace the active viewport, or
ACTIVE_VIEWPORT_IFRAME, create a modal IFRAME
MODAL_IFRAME
url Any URL, including relative Can also include {INSTANCE} and other placeholders from the
paths list below
search- INSTANCE, SERIES, STUDY, (optional) An array consisting of "urlParamName":"INSTANCE"
Params ACCESSION_NO, PATIENT_ID, etc, will be automatically added to url in form of ?
EXAM_DATE, STORAGE urlParamName=dynamicValue&...
window- Any number (optional) Window width in pixels. To be used with
Width MODAL_IFRAME.
window- Any number (optional) Window height in pixels. To be used with
Height MODAL_IFRAME.

The URL is constructed from url and searchParams by the frontend. The following placeholders that refer to
metadata from the active image can be used:
• STORAGE – identifies the current PACS plugin (its .id in application.properties)
• INSTANCE – (0008,0018) SOP Instance UID
• SERIES – (0020,000E) Series Instance UID
• STUDY – (0020,000D) Study Instance UID
• ACCESSION_NO – (0008,0050) Accession Number
• PATIENT_ID – (0010,0020) Patient ID
• EXAM_DATE – (0008,0020) Study Date
Button examples
• Opens http://demo.example.com in a new window:

{
"name": "External website demo",
"position": "ALL",
"openType": "NEW_WINDOW",
"url": "http://demo.example.com/"
}

• Opens a specific study in the same window (for example, http://demo.example.com/?study=1.2.826.0.1.


3680043.2.4852.20180403.113343677.435858665&storage=PacsOne&newParam=otherValue):

{
"name": "Metadata in URL query",
"position": "VIEWER",
"openType": "SAME_WINDOW",
"url": "http://demo.example.com/",
"searchParams": {
"study": "STUDY",
"storage": "STORAGE",
"newParam": "otherValue"
}
}

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


82

• Opens a study in the active viewport, the UID is specified in the path and other parameters –
in the query (for example, http://demo.example.com/PacsOne/1.2.392.200036.9125.2.37100184241200.
64618798380.28802?image=1.2.826.0.1.3680043.6.6054.19688.20100603165016.704.123):

{
"name": "Metadata in URL query and path",
"position": "VIEWER",
"openType": "ACTIVE_VIEWPORT_IFRAME",
"url": "http://demo.example.com/{STORAGE}/{STUDY}",
"searchParams": {
"image": "IMAGE"
}
}

• Executes a custom URL handler on the client computer:

{
"name": "Run a 3rd party application on the client computer",
"position": "VIEWER",
"openType": "SAME_WINDOW",
"url": "applauncher:{STUDY}"
}

Custom URL handlers is a Windows feature that starts a registered application with the entire
URL on its command line. This example uses a generic protocol name “applauncher”. There
also are success stories for Linux (using gconftool-2) and OSX (using a specifically crafted
Application Bundle).
MedDream includes a couple of helper files for Windows:
– runAppFromBrowser/runAppFromBrowser.bat – a wrapper for 3rd-party applications. It
attempts to remove the “applauncher:” prefix from the command line and passes the
remainder to the application in form of studyuid=VALUE. You will need to adjust the path
to your application, and its command line;
– runAppFromBrowser/runAppFromBrowserReg.bat – registers the former file as a handler of
the applauncher protocol. Must be run in an elevated Command Prompt window. You will
need to adjust the path to runAppFromBrowser.bat and probably invent a better protocol
name instead of this “applauncher”.

5.1.8.1. Parameter override in token-based HIS integration

It is possible to override some parameters when MedDream is opened via token, by adding the
pluginConfigurations element:

{
"items": [ ],
"pluginConfigurations": [{
"pluginName": "Metadata in URL query",
"parameters": [{
"name": "url",
"value": "http://example.com/viewer/"
},{
"name": "windowWidth",
"value": "300"
},{
"name": "windowHeight",
"value": "100"
},{
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


83

(continued from previous page)


"name": "openType",
"value": "NEW_WINDOW"
},{
"name": "searchParams.storage",
"value": "STORAGE"
}]
}]
}

pluginName here must match name of an entry in links.json.


Like in the configuration file, searchParams supports any URL parameter name passed in form searchParams.
<parameter name>, and the same set of metadata placeholders for dynamic values.

5.1.9. Reference for remaining configuration parameters

The parameters listed below can be left alone in most situations. The rarest of them aren’t included in
application.SAMPLE.properties for the sake of its simplicity.
1. MedDream root directory

com.softneta.meddream.configRoot = PATH_TO_MEDDREAM_DIRECTORY

All other directories are based on this value by default, therefore a correct specification means
less parameters are needed in application.properties.
If left unconfigured, the current directory of the JVM process is substituted automatically. The
substitution is based on the “user.dir” Java property, which in turn must be initialized by the JVM
and not via the -D option.
If the outcome is still incorrect, you can try to specify configRoot explicitly. It is expected in the
URI format; the “file://” prefix is mandatory and relative paths are not supported.
Examples:
com.softneta.meddream.configRoot = file:///opt/meddream
com.softneta.meddream.configRoot = file:///C:/MedDreamPACS/MedDream
com.softneta.meddream.configRoot = file:///C:/PROGRA~1/PacsOne/php/
meddream
2. Path to MedDream temporary files

com.softneta.meddream.tempDir = PATH_TO_MEDDREAM_TEMP_FILES

Allows to specify the path to a location where MedDream temporary files are stored; the default
“temp” below configRoot might not always be suitable.
Examples:
com.softneta.meddream.tempDir = ./temp (non-URI format might not work in all
cases)
com.softneta.meddream.tempDir = file:///mnt/mdtmp
com.softneta.meddream.tempDir = file:///E:/mdtmp

Note: Since 7.0 some cached files might need paths longer than 260 characters which are not
allowed under Windows. The only solution is to have com.softneta.meddream.tempDir as short
as possible.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


84

3. Session duration in seconds

server.servlet.session.timeout = 60

Some PACS plugins are slower and might take several minutes to load even the structure of a
large study (afterwards error icons are displayed instead of thumbnails). In these situations the
timeout should be increased.
Please remember that due to larger timeouts, client connections will persist longer in case of
inactivity or incorrectly closed MedDream window (using the “X” icon on the corner instead of
“Logoff”). With a license that limits the number of concurrent connections, this might exhaust the
free connections more often.
4. Session cookie name

server.servlet.session.cookie.name = MEDDREAMSESSID

Value in the example is a hidden default and won’t likely need correction.
For cases where the current value is used by HIS or different software on the same domain; in
these situations MedDream unpredictably loses its session.
5. IFRAME embedding permissions
This is the default and allows embedding MedDream only on the server that hosts it:

security.frameOptionsPolicy = SAMEORIGIN
#security.contentSecurityPolicy = frame-ancestors 'self'

(Results in headers X-Frame-Options: sameorigin, Content-Security-Policy:


frame-ancestors 'self'.)
This disables both headers altogether, therefore MedDream can be opened in an IFRAME
without any restrictions:

security.frameOptionsPolicy = NONE
#security.contentSecurityPolicy =

This disallows IFRAME embedding completely:

security.frameOptionsPolicy = DENY
#security.contentSecurityPolicy = frame-ancestors 'none'

(Results in headers X-Frame-Options: deny, Content-Security-Policy:


frame-ancestors 'none'. Please note that DICOM PDFs won’t open any more, as
MedDream uses an internal IFRAME for the system-default PDF viewer.)
This allows embedding on servers listed in the second parameter:

security.frameOptionsPolicy = ALLOW-FROM
security.frameOptionsWhitelist = 93.184.216.34,example.com
#security.contentSecurityPolicy = frame-ancestors 'self' \
# 93.184.216.34 example.com

(Results in headers X-Frame-Options: allow-from <list>, Content-Security-Policy:


frame-ancestors 'self' <list> with <list> populated from the second parameter.)
In the examples above, .contentSecurityPolicy is commented out as the same default value
comes from .frameOptionsPolicy. Exotic cases might require overrides; by the way, ALLOW-
FROM is definitely not supported by some browsers.
6. “Secure” flag of the session cookie

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


85

server.servlet.session.cookie.secure = true

After configuring true, MedDream must be accessed over HTTPS or else the browser won’t
send session cookies back to the server after a successful login. Recommended in HTTPS-only
installations.
7. “SameSite” flag of the session cookie

server.servlet.session.cookie.sameSite = strict

The default value is the string “unset”, which means the flag is not added to the cookie. Other
possible values:
• none – no restrictions on the cookie, however the “Secure” flag is still mandatory. Not
supported by older browsers;
• lax and strict will further prevent embedding MedDream in an IFRAME, and might cause
problems with viewing DICOM PDFs.

Note: Since February 2020, Chrome changed the handling of cookies without this flag. Other
browsers will follow, too.
Now their default is “lax”; to get the older equivalent of “none”, you must specifically use sameSite
= none in MedDream settings.
With “lax”, MedDream should be hosted on a subdomain – for example, https://hospital.com will
be able to display an IFRAME containing https://viewer.hospital.com.
In application.SAMPLE.properties the “lax” version is commented out by default. You can
uncomment it if all your clients have compatible up-to-date browsers, as even support for “lax” is
not widely present.

8. Disable the X-XSS-Protection header if needed

security.xssProtectionDisabled = false

The header X-XSS-Protection is sent by default; true here will turn it off for troubleshooting etc.
9. Disable the X-Content-Type-Options header if needed

security.contentTypeOptionsDisable = false

The header X-Content-Type-Options is sent by default; true here will turn it off for
troubleshooting etc.
10. Address of the reverse proxy through which requests from Internet reach MedDream

security.meddreamProxyIp = 192.168.111.100

Needed to correctly extract remote IP addresses from the X-Forwarded-For header. This way
MedDream logs will contain true remote IPs instead of the proxy address (unless the proxy does
not provide X-Forwarded-For). Typically used in installations with both remote clients (they reach
MedDream via a proxy server) and local clients (direct connections from the LAN).
Empty by default. Must not be present if there is no proxy, or else MedDream will believe
spoofed values of X-Forwarded-For.
Since 8.3.1 hostnames beside IPs are supported, too.
11. Detect the change of remote IP address

security.detectRemoteIpChange = WARN

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


86

LOGOFF invalidates the session, WARN just logs a warning, OFF disables the feature (default).
Might also require settings server.tomcat.remote-ip-header = x-forwarded-for and
server.forward-headers-strategy = native.
12. Restrict client-side addresses that can open MedDream via HIS integration

security.authAllowedOrigins = 192.168.111.20,192.168.111.24

If not empty, IPs not in the list will be denied access to the /auth endpoint, which is a crucial part
of HIS integration.
13. Restrict client-side addresses that can use the Login window

security.meddreamLoginAllowHostIp = 192.168.111.0/24,dep.infra.acme.com

If not empty, IPs not in the list will get the same “403” page instead of the Login window, as in
case of meddream.loginEnabled=false.
CIDR-style subnets and hostnames are supported, too.
14. Limit the number of failed login attempts

com.softneta.meddream.maxAttemptsToConnect = 5
com.softneta.meddream.timeoutSeconds = 60

After maxAttemptsToConnect or more failures from the same IP address, any further attempts
will immediately fail (without validating the provided credentials) during next timeoutSeconds
seconds. The usual validation of credentials resumes after this time interval ends. The attempts
counter is reset by a successful login.
Default values are shown in the example. The limiting is disabled if at least one parameter is
zero. The setting security.meddreamProxyIp is important for correct IP addresses.
15. Path to writeable settings files (system.json / global.json / shortcuts.json / hangingProtocols.json /
columns.json)

com.softneta.settings.fileLocation = ${com.softneta.meddream.configRoot}/\
sys/settings

The value in the example is the default.


Since 7.8.0, to facilitate installations where most of directory tree is read-only, this parameter
applies only to system.json / columns.json (created automatically if missing) and global.json
/ shortcuts.json / hangingProtocols.json (created interactively by the Settings window etc).
Location of rebranding configuration (including favicon.ico) and robots.txt is now hardcoded as
“sys/settings” below configRoot. Since 8.3.1, in a similar fashion the translation files are in “sys”
(not “sys/settings”) below configRoot.
16. Disable usage statistics collection

com.softneta.statistics.enabled = true

By default MedDream logs number of sessions and similar things to files statistics/YYYY-MM.stat
below configRoot.
When using the “pay per view” licensing model, these offline data provide proof for a certain
amount of monthly payment. In other cases statistics can help to find the optimal number of
concurrent connections or provide insights when troubleshooting performance problems.
17. Path to usage statistics files

com.softneta.statistics.fileLocation = ${com.softneta.meddream.configRoot}/\
statistics

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


87

The default value is shown above. In dockerized installations this option might be more
convenient than symlinks etc.
18. Local AE Title for saving annotations and screenshots

com.softneta.meddream.dcmsnd.bind = MEDDREAM

Created DICOM objects will be sent to the PACS over DICOM C-STORE. This Local AET
identifies MedDream as a sender. For testing purposes one might use any AET already accepted
by the PACS.
Not used in case of the “QR” plugin with storageApiEnabled=true because the plugin has a
separate parameter for Local AET.
19. Wait for annotation and screenshot object availability at the PACS

com.softneta.meddream.secToWaitAfterCreatedDICOMSend = 10

If this setting is nonzero, then a fresh PR/KO/RTSTRUCT/SC object must appear in study
structure not later than after this number of seconds. Default is zero and assumes that the
PACS will immediately import an object received via C-STORE.
20. Source of certain attributes in annotation and screenshot objects

com.softneta.meddream.newObjectsUseMetadataFromPacs = false

The default value is true and Patient ID is taken from the PACS by a dedicated request for
study metadata (normally the result isn’t cached and the request is executed during every save
operation). This might be beneficial if there is a chance that the PACS will change the Patient ID
without updating the DICOM files.
When changed to false, Patient ID is taken from attributes of the image being annotated (these
are normally cached). This is important for integrations where the Patient ID isn’t present in study
metadata at all.
21. Patient History scope for MultiPACS configurations

com.softneta.meddream.searchPatientHistoryInAllStorages = true

The default value is false: the PACS from where the study was opened, also provides the patient
history for this study. In contrast, true forces searching for related studies in all PACSes available
to the current user.
22. Credentials for management endpoints like /manage, /h2-console, etc.

authentication.manager.username = LOGIN_NAME
authentication.manager.password = LOGIN_PASSWORD

Use a strong password, and do not leave it configured longer than necessary. (An empty
username or password makes the login impossible.)

Note: Both values can also be file names, or paths to files, from where the final content will
be loaded. A successful load operation is not indicated in the logs. File contents are used as is,
without removing empty lines, whitespace or newline characters (please make sure that there is
no line ending in the file).
Due to this “hidden” functionality, a quite rare bug is possible: when you have a too simple
password that matches the name of an existing file, then content of that file is used instead,
without any warning. Strong passwords will prevent that. With usernames the chance is
obviously higher.

23. Enable functionality of the /manage endpoint

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


88

management.endpoints.enabled-by-default = true
management.endpoints.web.exposure.include = *

This is diagnostic functionality for qualified personnel. The endpoint can be used to examine
MedDream logs etc. over HTTP, therefore it presents a security risk.
Do not leave it configured longer than necessary, and use a strong password in
authentication.manager.password.
By default .enabled-by-default is false and yields an empty directory anonymously; .include is
just health.
It is also possible to trim down the amount of exposed data as it might contain information sought
by hackers. You should enable only individual subsets relevant to your case. The example below
exposes only /manage/env and /manage/health:

management.endpoint.env.enabled = true
management.endpoint.health.enabled = true
management.endpoints.web.exposure.include = env,health

By default /manage is available on the same port and address(es) like other parts of MedDream.
It is strongly recommended to at least use a different port, or even bind to 127.0.0.1 to prevent
access from other machines:

management.server.port = 8081
management.server.address = 127.0.0.1

Note: Spring Framework requires to have management.server.port different from server.port


when management.server.address is used.

24. Enable the /h2-console endpoint

spring.h2.console.enabled = true
spring.h2.console.settings.web-allow-others = true

The /h2-console endpoint allows to manipulate contents of internal databases (Reporting


function, auth-meddream credentials storage, job engine and so on). This is an obvious security
risk.
Other places of this Manual explain the rare cases when this endpoint is needed.
Generally, do not leave it configured longer than necessary, and use a strong password in
authentication.manager.password.
25. Log level
The log level can be adjusted for every class or a particular part of class hierarchy. The example
below provides separate parameters (not alternatives of a single parameter).

logging.level.ROOT = ERROR
logging.level.com.softneta = INFO
logging.level.com.softneta.meddream.dicomStoreServer = DEBUG

26. Log file name without extension

logging.file.name = meddream
#logging.file.name = /opt/md/log/meddream

Commenting this line out will disable logging to file. The console, if visible, will still receive the
messages.
Do not include the extension; it is added automatically together with additional suffixes.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


89

A path can be included, too. All directories must exist, the last one must be writeable by the user
under which the JRE process is running. A related Spring Boot setting, logging.file.path, only
allows to change the path while keeping default file names (logging doesn’t work if you add both
settings).
27. Limit size of old log files

logging.logback.rollingpolicy.max-file-size = 10MB

The log file is automatically rotated (renamed to *.log.1, *.log.2, . . . ) when its size reaches this
value.
Before 8.1.0, logging.file.max-size was suggested instead, however it didn’t work.
28. Limit number of old log files

logging.logback.rollingpolicy.max-history = 10

During log rotation, the oldest ones are removed unless this parameter is set to 0.
Before 8.1.0, logging.file.max-history was suggested instead, however it didn’t work.
29. Base directory for caching thumbnails, pixel data, DICOM attributes and study structure objects

com.softneta.preparation.cacheDir = ./temp/cache

By default it’s the subdirectory “cache” under tempDir.


30. Directory where converted videos and conversion process logs are stored

com.softneta.video.convertedDir = ./temp/converted-videos

31. FFmpeg command line for video conversion

com.softneta.video.commandLineTemplate =-i {INPUT} -y -vcodec libx264 -preset␣


˓→medium -movflags faststart {OUTPUT}

{INPUT} and {OUTPUT} are automatically replaced with corresponding file names. There is no
support for options with embedded spaces, and quoting will not help; the space character
always separates adjacent options.
The default value is shown in the example. It utilizes a software H.264 encoder available in most
builds of FFmpeg.
If you have a hardware encoder, it might be possible to speed up the conversion
without noticeable loss of quality. For an Nvidia video adapter under Windows, one
can try the command line -hwaccel cuda -i {INPUT} -y -vcodec h264_nvenc -preset slow
-movflags faststart {OUTPUT} after installing recent drivers (the version in Windows Update
might still be too old). Experiments under Linux will need a recent FFmpeg build, at least
configure’d with --enable-nvenc. Do not forget to examine the files *.out under convertedDir
if the conversion is failing.
The thumbnail creation command line is hardcoded in a third-party library (not configurable).
32. Directory to store temporary anonymized images before uploading to DICOM Library

com.softneta.dicom.library.upload.tempDir = ./temp/upload-to-dicom-library

33. Settings for Export to ISO/Burn

com.softneta.export.tempDir = ${com.softneta.meddream.tempDir}
com.softneta.export.tmpCleanAfterMilliSec = 86400000
com.softneta.export.fileAliveTimeInMillis = 10800000
com.softneta.export.additionalSoftwarePath=
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


90

(continued from previous page)


#com.softneta.export.isoSizes[0].id = MiniCD
#com.softneta.export.isoSizes[0].name = Mini CD (210 MB)
#com.softneta.export.isoSizes[0].size = 220200960
com.softneta.export.appendIsoSizes = false

Every tmpCleanAfterMilliSec milliseconds after application start, MedDream attempts to


remove outdated (older than fileAliveTimeInMillis) export jobs and their temporary files
under tempDir. During normal operation, this data is removed after the Export window closes,
provided that there are no related background downloads.
If additionalSoftwarePath is specified, it shall be the path to a directory with files of a
DICOMDIR viewer (autorun.inf and others). They will be automatically included in each disc of
exported studies. Since 7.9, Export can create a ZIP file like the Archive function does (always
of unlimited size, however), and the DICOMDIR viewer is included there as well.
The isoSizes[] array can be used to specify custom media sizes. id is a simple alphanumeric
identifier (Latin letters, no spaces). size is in bytes, zero means no limit.
When appendIsoSizes is true, custom media sizes are appended to the default list of unlimited
(0), CD (681574400), DVD (5046586572), DL-DVD (9126805504). Otherwise the default list is
lost and, if some of its entries are still needed, they need to be added to isoSizes[] manually.
34. Possibility to control anonymization amount in the Share via DICOM Library function (VET license only)

com.softneta.dicom.library.upload.anonymizeLevel = false

For non-VET license this parameter is ignored and remains set to 1.


35. Possibility to disable the study count request for Patient History window

com.softneta.meddream.patientStudyCountEnabled = false

This is not needed under normal circumstances (value should remain true).
36. Open a custom viewer from Search window

com.softneta.meddream.alternativeViewerUrl = http://SERVER/viewer?study={study}

If not empty, the Search window will open this URL instead of the Viewer window.
Can contain placeholders “{study}” and “{storage}” that will be replaced with Study Instance UID
and storage ID. If “{study}” is missing, then a hardcoded query “?studyUid=<Study Instance
UID>&storageId=<storage ID>” is appended. The other one, “{storage}”, is optional.
37. Bind address of the HTTP server

server.address = 192.168.200.100

This parameter can be used to expose MedDream on a single IP address that belongs to the
machine. The default value is 0.0.0.0, meaning “all IP addresses”.
38. HTTP context path

server.servlet.context-path = /meddream

By default the MedDream backend is available at /. Some reverse proxying scenarios might
benefit from different values.
39. Enable/disable compression of HTTP responses

server.compression.enabled = true
server.compression.mime-types = application/octet-stream

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


91

If the first parameter is set to true (by default it’s false), then the second one lists comma-
separated MIME types to which the compression will be applied.
40. Maximum size of HTTP headers

server.max-http-header-size = 24576

MedDream configures 24 KB by default (a big difference compared to 8 KB in Tomcat). Some


integrations might need even more and fail with HTTP 400.
Value is in bytes.
41. Age of the /branding resource

com.softneta.meddream.http.brandingCacheMaxAgeSec = 0

The /branding resource will expire in proxy/browser caches after this many seconds. Zero
(default) turns the caching off, that is, the browser will always perform the request anew. Before
8.0.0, the value was hardcoded as 3600.
42. Rename robots.txt

com.softneta.settings.robotsFileName = robots.txt

MedDream is shipped with an example file sys/settings/robots.txt. If you are experimenting with
multiple files, it might be more convenient to point to a different one instead of rewriting contents
of the same file.
43. Adjust what color palettes are offered, and in what order

#com.softneta.meddream.enabledColorPalettes = HOT_IRON,PET,HOT_METAL_BLUE,\
# PET_20_STEP,SPRING,SUMMER,FALL,WINTER
com.softneta.meddream.enabledColorPalettes = HOT_IRON,PET,HOT_METAL_BLUE,\
PET_20_STEP,RAINBOW

Affects both Fusion functionality and the Color Palette Selection widget.
The default value (effective when application.properties doesn’t contain the setting, or it’s
commented out) is shown in the commented-out example. Those are the standard palettes.
The second version is offered in the configuration samples, and contains a custom palette
“RAINBOW” instead of a few standard ones.
Custom palettes are stored as files sys/clut/*.json, file name must be listed in the setting
exactly (case sensitive). The accompanying icon is expected as a file sys/clut/icons/*.png
and is declared in form of a relative URL palette/*.png via the “thumbnailUrl” parameter in the
JSON file.
44. “Share via DICOM Library”: upload chunk size in bytes

com.softneta.dicom.library.upload.partSize = 100000

The default is 1 MB. If the Internet connection to DICOM Library is slow, then smaller values
might yield faster recovery from connection drops.
45. “Share via DICOM Library”: number of retries and related pause

com.softneta.dicom.library.upload.repeatTimes = 5
com.softneta.dicom.library.upload.repeatAfterSeconds = 5

If the upload process fails, then the related job pauses for repeatAfterSeconds seconds and
retries up to repeatTimes times.
46. “Share via DICOM Library”: thread pool management

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


92

com.softneta.dicom.library.upload.job.corePoolSize = 10
com.softneta.dicom.library.upload.job.maxPoolSize = 100
com.softneta.dicom.library.upload.job.keepIdleForSeconds = 30

See https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/
ThreadPoolExecutor.html. Initially, corePoolSize threads are ready for work; up to maxPoolSize
threads can be created on demand and they will be terminated after keepIdleForSeconds
seconds of inactivity.
47. Local Storage SCP: AE Title

com.softneta.dicomStoreService.localAETitle = MEDDREAM

PACSes need to know this value, the corresponding IP and port for sending images to
MedDream. “MEDDREAM” is the default.
localAETitle also accepts multiple values separated by commas. Even more, an empty
parameter will result in any Called AE Title being accepted (some PACSes, too, don’t care about
the Called AE Title).
48. Local Storage SCP: TCP port

com.softneta.dicomStoreService.port = 11116

The SCP listens on this port (11116 by default).


49. Local Storage SCP: bind address

com.softneta.dicomStoreService.address = 192.168.111.70

By default the SCP binds to 127.0.0.1. This parameter can specify a single address, including
“0.0.0.0” which means all available addresses (that was the default before MedDream 8.0.0).
A symbolic name will automatically resolve to a numeric address, but this isn’t recommended
unless a single address is known to the resolver.
50. Local Storage SCP: base directory for received DICOM files

com.softneta.dicomStoreService.saveDirectory = ${com.softneta.meddream.tempDir}/
˓→STORE

If left empty, the SCP will not start. The default value is “STORE” under tempDir.
For better compatibility with the temporary files cleaner, empty value is recommended here
instead of commenting the entire setting out.
Under this directory the SCP creates received files: CALLING_AET/ STUDY_INSTANCE_UID
/SERIES_INSTANCE_UID/ SOP_INSTANCE_UID.dcm. Avoid long saveDirectory under
Windows, because together with UID values from the files the path might become longer than
supported by some third-party applications.
51. Local Storage SCP: accepted Calling AE Titles

com.softneta.dicomStoreService.acceptAETitles = DCMSND,SENDTOPACS

A comma-separated list of accepted titles. It is not possible to accept “any” title.


If left unconfigured or empty, the SCP will not start. This is the default.
52. Local Storage SCP: accepted IP addresses

com.softneta.dicom-store-service.allowedIps = 192.168.111.87,192.168.111.88,\
192.168.111.91

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


93

If not empty, then DICOM file uploads and C-ECHO connections will be allowed only from the
listed IP addresses. Clients from wrong addresses will see an immediate socket closure (a
connection reset).
Totally hiding the listener from some clients, as if nobody listens at the port, is possible only at a
lower network layer and requires a firewall.
53. Local Storage SCP: number of simultaneous connections

com.softneta.dicomStoreService.multiThreadCount = 5

Connections beyond this number will be ignored instead of rejecting associations.


54. Local Storage SCP: try preserving compressed transfer syntaxes

com.softneta.dicomStoreService.preferSingleComprSyntaxInCtx = true

Some DICOM senders are proposing presentation contexts with multiple transfer syntaxes. The
Standard allows to accept only one syntax. By default, the first one is accepted. As it’s often
Implicit VR LE, the sender becomes obliged to uncompress the object, which wastes time and
resources.
If true is configured here, MedDream verifies whether the syntaxes are uncompressed except a
single one, and accepts only that syntax. (Looks like it’s a popular scenario with Sectra software.)
If, however, the list contains more than one compressed syntax, then the first from the list is
accepted again.
MedDream can’t possibly know which syntax is the original one and therefore most efficient for
sending. The sender can avoid this ambiguity by sending the original syntax first, or by packing
every syntax:class pair in a separate context.
55. Local Storage SCP: create preparation jobs

com.softneta.dicomStoreService.prepareReceivedFile = true

true: after receiving an IAN message, or a file over C-STORE, a preparation job will be created.
56. Local Storage SCP: create preparation jobs for certain Called AE Title values only

com.softneta.dicomStoreService.prepareForTheseLocalTitles = MEDDREAM1,MEDDREAM2

When prepareReceivedFile is true, this parameter can restrict values of Called AE Title for
which preparation jobs are created. Applies to C-STORE only, not IAN. No restrictions if empty
(default).
Unless localAETitle is empty (by default it isn’t), the allowed values must be from localAETitle.
57. Default value of (0008,0005) Specific Character Set when this attribute is missing in the DICOM file

com.softneta.dicomParser.defaultCharset =

Empty value, commented out line and US-ASCII are equivalent.


58. Force using defaultCharset above even if (0008,0005) is present in the DICOM file

com.softneta.dicomParser.defaultCharsetOverride = false

true will ignore any declarations in DICOM files. This might be adequate in a (small) clinic where
all modalities specify wrong Specific Character Set.
59. Disable rendering of old-fashioned overlays

com.softneta.dicomParser.builtInOverlayEnabled = false

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


94

MedDream 8.2 began to render overlays that are stored in unused bits of Pixel Data. false here
will disable that.
Overlays specified via the (60xx,3000) attribute are supported since initial versions, and can not
be disabled.
60. Do not use the built-in DICOM Dictionary

com.softneta.dicomParser.useJdtLookupDDict = false

Since 8.3 the declared Value Representation of every DICOM attribute is ignored and is taken
from a built-in dictionary instead (this setting is true by default).
Change to false for previous behavior. Some files that violate the standard might need different
values of this setting. Hopefully a particular installation doesn’t have both kinds of files.
61. Allow parsing of listed private tags
By default private tags are ignored. Consequently, standard tags in private sequences are
inaccessible, too.

com.softneta.dicomParser.additionalPrivateTags = 00430010,2001105F/2005107B
#com.softneta.dicomParser.additionalPrivateTags[0].tagTree=2001105F/2005107B
#com.softneta.dicomParser.additionalPrivateTags[0].inEveryLevel=true

Simple syntax is tag numbers (8 hexadecimal characters) separated by commas. In this syntax
tags are taken only from the root level. If the number is prefixed by slash-separated container
number(s), like SEQ1/SEQ2/TAG1 instead of just TAG1, then the tag is taken from specified
sequence(s) starting at root level.
Extended syntax, which is commented out in the example, allows to specify a tag number or
path, and enable searching for it everywhere – not only from the root level.
Tags needed by certain functionalities, namely 00211106, 00291010 and 001910D7 (all with
inEveryLevel=true), are added to this parameter automatically.
62. MedCAD: path to backend plugins directory

com.softneta.meddream.medcad.pluginsDir = ./medcadPlugins

The value in this example is the default.


63. MedCAD: path to frontend plugins directory

com.softneta.meddream.medcad.frontendPluginsDir = ./md5/plugins

The value in this example is the default, and currently it’s hardcoded in the frontend.
64. HIS integration: JWT security layer

authentication.his.jwtServiceAddress = http://192.168.111.30:90/jwt/
authentication.his.jwtServerKey = ATDwsT...DFHTQ==
authentication.his.jwtMedDreamKey = DjSWFt...psVzg==
authentication.his.responseDecryptPassword = g9RxMR...an67Z4=
authentication.his.responseDecryptSalt = /9kzgA...pYdnw==
security.cookieSecureFlag = false

A custom token validator can use JSON Web Tokens instead of the “token” URL parameter. (Not
supported by the validator shipped with MedDream.)
This mode is enabled by adding a header Authorization: Bearer JWT_STRING to the initial
(at least) request to MedDream. In this case jwtServiceAddress must be configured because
MedDream will send the JWT in a header of a POST request to this URL and expect the same
JSON object as from the usual HIS integration. The service can use claims in the token to
identify what needs to be returned.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


95

The request to jwtServiceAddress will contain the original JWT – or, if jwtMedDreamKey and
jwtServerKey are configured, then MedDream verifies original signature with jwtServerKey and
re-signs the token with jwtMedDreamKey (both operations support only HMAC-SHA of length
256, 384 and 512).
If responseDecryptPassword and responseDecryptSalt are configured, then MedDream will
decrypt the response (AES in GCM mode, no padding) before parsing it as JSON.
The password, salt and keys must be specified in Base64 format.
If cookieSecureFlag is true, the “md-jwt” cookie is sent over HTTPS only.
65. LiveShare
#liveshare.guestRoles=
#liveshare.linkStrategy=SIMPLE_HIS
#liveshare.liveShareTokenValiditySeconds=3600
#liveshare.tokensGeneratorService=http://192.168.111.30:111/v3/generate
#liveshare.tokensInvalidationService=http://192.168.111.30:111/v3/invalidate

LiveShare is enabled when spring.profiles.include contains “liveshare”. Additionally, system.json


must contain features.liveshare=true.
guestRoles contains permissions for guest sessions. You should include only permissions for
operations that you plan to demonstrate; for example,
• if EXPORT_ISO is not included but you accidentally begin exporting a disc image, then
guests won’t see this activity;
• if ANONYMOUS_VIEW is included then guests will not see original patient information seen
by you.
If you change linkStrategy to TOKENIZED_HIS (default is SIMPLE_HIS), then a token service
(for example, the one shipped with MedDream) is used:
1. to convert Study UIDs and permissions to a second-level token via a request to
tokensGeneratorService,
2. for an opposite operation via authorization.his.token-service-address,
3. to discard second-level tokens on end of a LiveShare session via
tokensInvalidationService.
liveShareTokenValiditySeconds is used during validation (first-level tokens themselves
contain the creation timestamp only). Lifetime of second-level tokens is configured separately at
the token service, see its parameter com.softneta.token.cache.time-to-idle-seconds in a
different application.properties file.
Furthermore, spring.profiles.include at MedDream side must contain “auth-his”. For
SIMPLE_HIS, authentication.his.valid-his-params must allow the “study” parameter
even if you don’t use it for integration. For TOKENIZED_HIS, authentication.his.
token-service-address must be configured.
66. Background DICOM preparation: thread management etc.
com.softneta.preparation.coreThreadCount = 1
com.softneta.preparation.maxThreadCount = 40
com.softneta.preparation.workQueueSize = 8000
com.softneta.preparation.threadTimeoutSeconds = 120
com.softneta.preparation.multiFrameThreadCount = 5
com.softneta.preparation.thumbnailCreation = all
com.softneta.preparation.thumbnailCreationModalities = CT,PT,MR,NM
com.softneta.preparation.thumbnailCreationSopClasses = 1.2.840.10008.5.1.4.1.1.
˓→2.2

com.softneta.preparation.prepareStudyInstancesThreadCount = 5
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


96

(continued from previous page)


com.softneta.preparation.prepareStudyInstancesMaxThreadCount = 40
com.softneta.preparation.prepareStudyInstancesWorkQueueSize = 8000
com.softneta.preparation.downloadDicomCoreThreadCount = 5
com.softneta.preparation.downloadDicomMaxThreadCount = 40
com.softneta.preparation.downloadDicomQueueCapacity = 5000
com.softneta.preparation.cachePreparationFiles = false
com.softneta.preparation.compressPixelsBeforeSave = true
com.softneta.preparation.cacheTimeToIdleSeconds = 86400
com.softneta.preparation.trackDicomModifications = false
com.softneta.preparation.modalitiesForFrameExtraction = PT,NM,MG,OPT
com.softneta.preparation.sopClassesForFrameExtraction = 1.2.840.10008.5.1.4.1.1.
˓→4.1,1.2.840.10008.5.1.4.1.1.2.1,1.2.840.10008.5.1.4.1.1.2.2

#com.softneta.preparation.expandEnhancedDicomThreadCount = 8
com.softneta.preparation.sopClassesForConversionToVideo = 1.2.840.10008.5.1.4.1.
˓→1.3.1

com.softneta.preparation.sopClassesForMoveToNewSeries =
#com.softneta.preparation.sopClassesForScoutImageMoveToNewSeries = 1.2.840.
˓→10008.5.1.4.1.1.2

com.softneta.preparation.skipExpandedFrameThumbnailPreparation = false
com.softneta.preparation.skipStructurePreparation = false
com.softneta.preparation.skipInvalidFrames = false
com.softneta.preparation.updateTagsFromPixelContent = false
com.softneta.preparation.useSessionCache = false
com.softneta.preparation.removeHtmlTagsFromSr = false

See https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/
ThreadPoolExecutor.html. Initially, coreThreadCount threads are ready for work and up to
maxThreadCount threads can be created on demand. The same is valid for other similar sets of
parameters, prepareStudyInstances* and downloadDicom*.

Note: In some scenarios, like prefetching a series or an entire study, increasing


coreThreadCount and maxThreadCount to 100-200 might not help to improve performance
– CPU utilization and network traffic will still be too low. In that case, add -Djava.util.
concurrent.ForkJoinPool.common.parallelism=200 (same value as for number of threads)
to the JVM command line.

Threads are terminated after threadTimeoutSeconds even if busy. You might need more time if
some files are very large.
For every multiframe file, up to multiFrameThreadCount threads will be created for processing
frames of the same file in parallel.
MedDream 7.7.0+ exhibits a different thumbnail display and an optimized study loading.
By default only a single “summary” thumbnail is displayed for series of modalities listed in
thumbnailCreationModalities and, due to thumbnailCreation = all, remaining thumbnails are still
created in advance. thumbnailCreation = first might cause the study to be displayed quicker, at
a cost of slower opening of a series after clicking on its summary thumbnail. Note, however,
that first applies only to series with modalities in thumbnailCreationModalities; for other kinds
of series, all thumbnails are always displayed and created. thumbnailCreationSopClasses is an
alternative to thumbnailCreationModalities, based on a different DICOM Attribute.
The downloadDicom* parameter set is used in the “Preload series” and “Preload study” scenarios
to make sure the DICOM files are downloaded and cached before processing their contents. It
might make a big difference with non-direct integrations (QR, Orthanc, Dicomweb, etc) that have
the caching enabled.
cachePreparationFiles controls an in-memory index of cached files. In 7.8.0+ it is false by
default, this saves a significant amount of memory; however outdated files are only removed by

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


97

temporary files cleaner (see below). The legacy value, false, might improve performance and
usually results in automatic removal of outdated files – even without the temporary files cleaner.
compressPixelsBeforeSave turns on compression during caching (possible values are gzip
or true, lz4, false); batchImageRequests is then ignored and remains false. This
might be better than server.compression.enabled as the latter is performed on every request.
Both options have little sense if the network connection is fast enough. After changing
compressPixelsBeforeSave, you must clear all cached data (see com.softneta.preparation.
cacheDir).
cacheTimeToIdleSeconds is the main means to indirectly control the cache size. The preparation
cache removes outdated files according to it. The cache will not work properly if files are removed
by external means, like manually or by the preparation-related entry in configuration of temporary
files cleaner. The latter must therefore be used only as a last resort (to clean files that became
orphaned due to an application crash, etc), and its time limit must be significantly higher than
cacheTimeToIdleSeconds – at least a few times higher.
If trackDicomModifications is true, MedDream makes sure that a cached file is created anew
if the original DICOM file has a newer Last Modified timestamp. This lowers the risk of displaying
outdated patient information, however if MedDream and PACS are on different machines, then
their system clocks must be synchronized for better protection and to avoid repeated re-caching.

Warning: trackDicomModifications should remain disabled in non-direct integrations


where DICOM files must be cached by the plugin (like Dicomweb):
• If the temporary files cleaner is set up to keep those original DICOM files as short
as possible (or caching is disabled in the plugin completely), then their absence will
invalidate the prepared files, which in turn will require to re-download the originals again.
The cleaning will be useless and performance will be poor.
• Even in less extreme examples, the timestamp simply corresponds to the download
time and there is no mechanism to get an updated file from the PACS. As the cached
files don’t change, the timestamp check is hardly useful.
When, however, the PACS deliberately forwards DICOM files to the MedDream listener, and
can therefore change the files in the background, then this timestamp check might still prevent
display of outdated information.

modalitiesForFrameExtraction and sopClassesForFrameExtraction specify which objects


are treated as spatial multiframe images (displayed as separate slices) instead of the traditional
temporal multiframe images (for example, the “movies” in ultrasound studies). A related option,
expandEnhancedDicomThreadCount, specifies how many threads are allocated for processing of
these objects; the default value is equal to autodetected number of processors.
skipExpandedFrameThumbnailPreparation makes sure only the first thumbnail for spatial
multiframe images is generated. The thumbnailCreation setting behaves similarly but for other
kinds of images.
sopClassesForConversionToVideo lists SOP classes of temporal multiframe objects (for
example, Ultrasound Multiframe Image Storage) for an experimental feature: during preparation
started by DICOM Listener (local Store SCP), an equivalent video in MPEG4 format is
created, and the frontend attempts to use a video player instead of a cine player. Empty by
default. Also requires com.softneta.dicomStoreService.prepareReceivedFile=true, the files need
to be forwarded to MedDream, sender’s AE Title must be configured as .storeScpAet at the
corresponding PACS plugin (see 5.1.14 Caching studies via DICOM Listener).
sopClassesForMoveToNewSeries (empty by default) lists SOP classes that must not be
combined with other classes in the same series. If an object of this class is found in a series
where other classes are also present, then it’s moved to a separate virtual series dedicated
to this class. For example, SR objects together with CT, MR, etc will interfere with the MPR
functionality, and even the DICOM Standard requires to have them in separate series.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


98

sopClassesForScoutImageMoveToNewSeries (empty by default) lists SOP Classes of scout


images that need to be moved to a separate series. Some imagers place them at the beginning
of an ordinary series (for example, together with CT slices). If this setting is not empty, SOP
Class of the first object in series matches one of configured values and the series contains at
least 5 images, then the Image Type attribute is extracted from first 5 objects, the middle and the
last object. An equal value from 4th, 5th, middle and last objects is treated as the “main” one;
objects with a different value are moved to a new series. Due to attribute extraction and early
parsing of DICOM files, the initial Viewer window (without thumbnails) will need more time to be
displayed.
skipStructurePreparation `` (false by default) disables the call to findStudy
during preparation when studyStructureSec > 0, and to findStudies when
pgwStudyStructureSec > 0. Otherwise both responses are re-cached every
time when preparation is triggered due to com.softneta.dicomStoreService.
prepareReceivedFile = true. A typical use case for ``true is an installation that
must query the PACS as rarely as possible.
skipInvalidFrames ignores frames that fail to decompress; the frontend attempts to handle
this gracefully, for example, by displaying the previous frame with a warning. By default a
decompression failure is fatal and MedDream stops processing/loading the image.
updateTagsFromPixelContent analyzes data in the pixels tag in order to detect any kind of JPEG
compression and its parameters. Might help to open images with a misleading Transfer Syntax
attribute.
useSessionCache enables session subdirectories in the paths to cached files. When the session
ends, those subdirectories will be removed; furthermore the PACS integration plugins will get
a corresponding event, and therefore will remove their own session subdirectories if those are
supported and configured. This setup ensures that the cached files stay for a time as short as
possible, however the benefit due to pre-caching of particular studies in other sessions is lost. It
is also not compatible with in-advance preparation.
removeHtmlTagsFromSr enables conversion of HTML markup in DICOM SR objects to plain text.
Such files are not standards compliant, and a security risk to viewers. MedDream displays them
in plain text mode where any HTML tags are visible and make the content difficult to read; true
here will improve the look.
67. Override tags cached for the “metadata” endpoint
Tag values will be available below the “attributes” element of the response. At the moment is
reserved for the V2 implementation of hanging protocols.

com.softneta.preparation.additionalMetadataTags = 00080070,00191018,2001105F/
˓→2005107B

This is a comma-separated list of tags (8 hexadecimal digits). If a container (sequence)


is specified, then the result will consist of values from all non-container entries found in
every Item at this level and joined by a backslash character. A tag number can be
prefixed by sequences containing it, as in 2001105F/2005107B provided above; the topmost
sequence, too, is relative to the root level. Private sequences also need to be listed in
com.softneta.dicomParser.additionalPrivateTags.
The default value is 00080070,00080080,00081010,00081090,00082228,00180010,00181000,
00181400,00189506/00181400,00280002,00281300,00500010/00080070,00500010/00081090,
00500010/00181000,00540220,52009229/00189412/00181400,52009230/00189412/00181400.
If you need to add just one tag to this list, then the entire large list must be specified.
Example: suppose the tags look like this,

00540220 SQ
FFE000E0
00281050 DS [1]
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


99

(continued from previous page)


00281051 DS [2]
FFE000E0
00281050 DS [3]

If additionalMetadataTags contains “00540220”, then attributes.00540220 is returned as 1\2\3.


If you use “00540220/00281050” instead, you’ll get 1\3.
68. Give more time for video-related preparation tasks to finish

com.softneta.video.preparationTimeLimitSec = 60

In order to start FFmpeg for video conversion, MedDream requires some data from related
preparation tasks and waits up to this time for them to finish. A heavily loaded server might
require more time.
In case of a corresponding timeout, the logged error message suggests to increase this value.
There is little sense to do it in advance.
69. Temporary files cleaner
Files are removed by their modification date.
You can configure multiple locations with a distinct file name pattern and maximum age. The
setting matchAnyDepth=false disallows searching for a match in every subdirectory and beyond,
thus helps to avoid needless scanning of underlying large directory trees. The age also applies
to directories; if a directory name at some level matches the pattern, and age is suitable, then the
entire directory subtree is removed even if some deeper contents are newer. There is, however,
an exception for .pattern equal to *: first the files of suitable age are removed, then their parent
directories if they became empty.
The cleaner executes every cleanRateMilliSec or according to expression in the cron setting.
Since 8.2 execution can also start outside this schedule if freeSpaceThresholdPct is configured
(larger than zero) and, after verification every monitoringFrequencyMilliSec (larger than zero),
the amount of free space is found lower; it will stop as soon as there is enough free space.
cleanRateMilliSec is relative to the application start. The value of 86400000 (one day) means
that if the application was restarted during some peak load at noon, the next cleaning will also
start during peak load next day.
If a more flexible schedule is needed, then set cleanRateMilliSec to -1 and specify the cron
parameter instead. The string must contain 6 entries: second, minute, hour, day, month,
weekday. Examples:
• 0 0 * * * *: beginning of every hour.
• 0 0 8-10 * * *: 08:00, 09:00, 10:00.
• 0 0 6,19 * * *: 06:00 and 19:00.
• 0 0/30 8-10 * * *: 08:00, 08:30, 09:00, 09:30, 10:00 and 10:30 every day.
• 0 0 9-17 * * MON-FRI: from 09:00 to 17:00, once per hour, weekdays.
• 0 0 0 25 12 ?: on Christmas Day at midnight.
Since 8.2 every cleanable location can have its own values for cleanRateMilliSec (or cron)
and freeSpaceThresholdPct. For the latter, however, you need separate volumes/disks, as
otherwise file systems report the same amount of free space.
corePoolSize and maxPoolSize help to utilize the CPU better. For example, 8 threads on a
recent computer makes the operation approximately three times faster. One thread is used
by default, which corresponds to pre-8.2 behavior. The default thread priority configured by
poolPriority is 1 (the lowest possible), you can increase it to 5 (same as other threads in
MedDream).

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


100

The default configuration, which is duplicated below, lists known locations with possible leftover
temporary files.

#com.softneta.temp-cleaner.disableCleaner = true
com.softneta.temp-cleaner.cleanRateMilliSec = 1800000
#com.softneta.temp-cleaner.cron = 0 30 0 * * *
#com.softneta.temp-cleaner.monitoringFrequencyMilliSec = 0
#com.softneta.temp-cleaner.freeSpaceThresholdPct = -1
#com.softneta.temp-cleaner.corePoolSize = 1
#com.softneta.temp-cleaner.maxPoolSize = 1
#com.softneta.temp-cleaner.poolPriority = 1

com.softneta.temp-cleaner.tempItems[0].directory = ${com.softneta.\
preparation.cacheDir}
com.softneta.temp-cleaner.tempItems[0].pattern = *
com.softneta.temp-cleaner.tempItems[0].olderThanSec = 604800

com.softneta.temp-cleaner.tempItems[1].directory = ${com.softneta.\
meddream.tempDir}
com.softneta.temp-cleaner.tempItems[1].pattern = *_archive
com.softneta.temp-cleaner.tempItems[1].olderThanSec = 7200
com.softneta.temp-cleaner.tempItems[1].matchAnyDepth = false

com.softneta.temp-cleaner.tempItems[2].directory = ${com.softneta.\
meddream.tempDir}
com.softneta.temp-cleaner.tempItems[2].pattern = *_export
com.softneta.temp-cleaner.tempItems[2].olderThanSec = 21600
com.softneta.temp-cleaner.tempItems[2].matchAnyDepth = false

com.softneta.temp-cleaner.tempItems[3].directory = ${com.softneta.\
meddream.tempDir}
com.softneta.temp-cleaner.tempItems[3].pattern = forward_*.dcm
com.softneta.temp-cleaner.tempItems[3].olderThanSec = 7200
com.softneta.temp-cleaner.tempItems[3].matchAnyDepth = false

com.softneta.temp-cleaner.tempItems[4].directory = ${com.softneta.\
meddream.tempDir}/3d
com.softneta.temp-cleaner.tempItems[4].pattern = *
com.softneta.temp-cleaner.tempItems[4].olderThanSec = 7200

com.softneta.temp-cleaner.tempItems[5].directory = ${com.softneta.\
video.convertedDir}
com.softneta.temp-cleaner.tempItems[5].pattern = *
com.softneta.temp-cleaner.tempItems[5].olderThanSec = 3600

com.softneta.temp-cleaner.tempItems[6].directory = ${com.softneta.\
dicom.library.upload.tempDir}
com.softneta.temp-cleaner.tempItems[6].pattern = *
com.softneta.temp-cleaner.tempItems[6].olderThanSec = 86400

#com.softneta.temp-cleaner.tempItems[7].directory = ${com.softneta.
˓→dicomStoreService.saveDirectory}

#com.softneta.temp-cleaner.tempItems[7].pattern = *
#com.softneta.temp-cleaner.tempItems[7].olderThanSec = 86400
#com.softneta.temp-cleaner.tempItems[7].freeSpaceThresholdPct = -1
#com.softneta.temp-cleaner.tempItems[7].cleanRateMilliSec = 0
#com.softneta.temp-cleaner.tempItems[7].cron =

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


101

Take caution with the last entry (related to saveDirectory). If you uncomment it and the related
com.softneta.dicomStoreService.saveDirectory setting is commented out, then the cleaner
receives a literal string ${com.softneta... and might misbehave. When not using the local
DICOM receiver, you should either comment out (or remove) this entire cleaner entry, or set
saveDirectory to an empty string (it is ignored both by receiver and cleaner).
The entry that cleans com.softneta.preparation.cacheDir should have a time limit a few
times higher than com.softneta.preparation.cacheTimeToIdleSeconds, or else intermittent cache
failures will result.
If you use some PACS plugins that download DICOM files instead of directly accessing them on
PACS file system (like “Orthanc” or “Dicomweb”), then their cache directories need to be added
here, too.
70. Old jobs cleaner

com.softneta.preparation.scheduleJobRemovalInSeconds = 0
com.softneta.preparation.job-cleaner.cron = 0 45 0 * * *

Completed jobs from Preparation and Share functionality are not removed immediately. The
legacy behavior corresponds to scheduleJobRemovalInSeconds = 30, cron = - (a job is
removed 30 seconds after completion) and is suspected to cause problems when jobs are
created quite often. Starting from 7.7, MedDream will attempt to remove the jobs at a certain
time (00:45 nightly by default) and only those older than one hour.
71. Google Analytics ID (when using GA to track user activity)

com.softneta.meddream.googleAnalyticsId = UA-000000-2

The GA client code is already included into MedDream, you only need to specify your website
ID.
72. How often the in-memory index of the cache is cleaned

com.softneta.ehcache.cacheCleanRate = 1800000

The outdated cache entries (according to com.softneta.preparation.cacheTimeToIdleSeconds)


are removed every cacheCleanRate milliseconds.
73. Minimalistic persistence of the cache index

com.softneta.preparation.persistCache = true
com.softneta.ehcache.cachePersistRate = 3600000
com.softneta.cache.studyStructureSec = 300
com.softneta.cache.pgwStudyResponseSec = 0

The in-memory cache index can be made partially persistent. If persistCache is true,
MedDream dumps the cache index to disk every cachePersistRate milliseconds, and loads
it during startup. This way the cache index is not completely lost when restarting the service,
however some orphaned files will remain. This, of course, costs CPU and I/O operations, and
slows down the startup.
Experiments will be needed to find out an optimal cachePersistRate that doesn’t waste too much
resources and still preserves enough changes in case of unplanned application restart.
The preparation cache index is preserved in a file “cache.keys” in tempDir. Other two kinds of
caches that can be preserved are: study structure cache (files “struct” in some subdirectories of
cacheDir, created if studyStructureSec is larger than 24h) and HIS integration response cache
(files “search” in some subdirectories of cacheDir, created if pgwStudyResponseSec is larger
than 24h). The main purpose of studyStructureSec and pgwStudyResponseSec is for how many
seconds entries can remain in the corresponding cache.
The Temporary files cleaner above is still needed as a last-resort means. Running every few
days might be sufficient.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


102

Note: studyStructureSec is 300 by default since 8.0. This means that the study structure will
not be queried from the PACS more often. At least 5 minutes must pass until any known changes
at the PACS, like newly added series or removed images, become visible in MedDream. The
“Clear cache” functionality can remove the cached structure earlier.

Note: The cache governed by pgwStudyResponseSec is subject to cleaning by “Clear caches”


functionality but only for HIS integration by Study UID. If your HIS integration references
studies by “accnum”, “patient” or “patient” together with “accnum”, then the following suboptimal
scenario is possible:
1. The study was removed from the PACS,
2. You have used the “Clear caches” functionality.
3. The study is opened from HIS once more. At this moment MedDream will behave as if the
study is still present on the PACS (will not display the “Access denied” error) but will fail
shortly afterwards when fetching the study structure.
For these types of HIS integration, cache entries expire only “naturally” (by becoming too old).

74. Method used by the Forward functionality

com.softneta.meddream.dcmsnd.forwardingMethod = native
#com.softneta.meddream.dcmsnd.forwardingMethod = plugin
#com.softneta.meddream.dcmsnd.forwardingMethod = cmove

There are three implementations:


• native (default): MedDream reads DICOM files of the study via a PACS integration plugin
(like during image display) and sends the contents via the same C-STORE client used for
uploading annotations. Elements of “forwardPacs” (system.json) specify destination’s IP
address, TCP port and AE Title;
• plugin: MedDream uses the PACS integration plugin to create a forwarding job on the
PACS itself and monitor its progress. TCP/IP address and port in “forwardPacs” are not
used. Implemented only in the PacsOne plugin;
• cmove: to forward a study found via a particular PACS integration plugin, MedDream uses a
C-MOVE client to connect to the PACS according to storeScpIp, storeScpPort, storeScpAet
in the configuration of that plugin, and passes Study Instance UID and destination’s AET.
TCP/IP address and port in “forwardPacs” are not used, however one must configure the
sender element: it lists plugin identifiers and so indicates PACSes whose studies can be
sent to this destination (in other words, it lists PACSes that have this destination configured).
75. Number of threads for Forward functionality

com.softneta.meddream.dcmsnd.dicomParseThreadCount = 5
com.softneta.meddream.dcmsnd.dicomSendThreadCount = 1

dicomParseThreadCount (5 by default) is used only with forwardingMethod=native and


influences the delay after which the network activity begins. During that period MedDream
collects paths to DICOM files, or makes local copies of files if the PACS plugin doesn’t support
paths (for example, an HTTP-based integration like Orthanc with caching disabled). More
threads might reduce the delay, however a direct DB integration plugin like Conquest will make
more parallel requests to the database.
dicomSendThreadCount (1 by default) is for all kinds of forwardingMethod. native will perform
up to this number of parallel C-STORE sessions (one DICOM Association per file); note, however,
that the limit applies to all destinations simultaneously. plugin and cmove will be able to send up

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


103

to this number of studies in parallel, therefore a larger number might improve the experience of
Forward for concurrent users.
76. SOCKS5 proxy address for the Forward function
DICOM receivers might validate the source IP address of an incoming session. Suppose the
devices already know the address of the PACS machine; a new address (of MedDream machine)
cannot be added to them due to some reason, while MedDream must run on a different machine
than the PACS. The solution is to set up a SOCKS5 proxy and run its server part on the PACS
machine. MedDream, in turn, must know about the client part of the proxy:

com.softneta.meddream.dcmsnd.forwardProxyHost = 192.168.111.222
com.softneta.meddream.dcmsnd.forwardProxyPort = 4567

If both parameters are specified, then the Forward function and upload of annotations (PR, KO,
segmentations, screenshots) will pass all DICOM communication to the specified proxy so that
the traffic comes out from a different IP address. For MedDream there is no significant difference
where the client part is running: on the PACS machine, on the MedDream machine, or on a
totally different machine.
Setting up such a proxy is beyond the scope of this document. OpenSSH is suitable both for
Linux and Windows; Shadowsocks is a good alternative.
77. Use the original AE Title when sending annotations
When sending annotations to the PACS, the C-STORE
client uses its own AE Title from non-empty value of
com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].storeScuAet, then
from com.softneta.meddream.dcmsnd.bind.
However, if this parameter is true, the first value attempted is the original AE Title already
associated with the study.

com.softneta.meddream.dcmsnd.annotationsFromOrigAet = true

NOTE: this was tested only with PacsOne plugin. Some plugins will not return the study’s AE
Title at all, while some others might return multiple values from different series and this is not
handled properly at the moment.
78. Require user identity in ATNA messages (EXPERIMENTAL)

com.softneta.audit.requireUserIdentity = true

Historically ATNA messages from MedDream have a fake user identity (”login@domain” etc).
Some scenarios, mainly those based on token integration (but not on Login window), carry a
true identity. Set this parameter to true in order to crash (a stack trace will be visible in the
application log) when attempting to send a fake identity via ATNA. On the one hand, messages
like these won’t reach the ARR at all; on the other hand, this will help to identify scenarios that
still need an update, provided that you are monitoring the logs.
79. Disable sorting of toolbar buttons after a version upgrade

com.softneta.meddream.toolbarButtonsOrderingEnabled = false

By default toolbar buttons are reordered after the upgrade (when the new JAR reads the files
*global.json saved by an earlier version). This way newly added buttons don’t go unnoticed.
If false is specified here, then no reordering is done and new buttons are added at the end.
Useful for some installations with a customized list of buttons where it would be too time-
consuming to recreate the custom order manually.
80. Calculation of “main modality” for the study structure (EXPERIMENTAL)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


104

Some modality-related decisions become too complicated with studies having multiple modality
values (like “CT, KO, PR, SR”), compared to single-modality studies (like “DX”). As of 8.3, a
single equivalent value is already calculated, however it is still being integrated into the workflow.

com.softneta.study.modalityWeight.CT = 1200
com.softneta.study.modalityWeight.PT = 100

The number of series with a particular modality is multiplied by configurable weight and the
modality with the highest score “wins”. There is an extensive list of default weights, with 1000 for
many popular values like RG, then 300 for PT and 100 for SR.
In this example, a typical study with both CT and PT series is still considered as “CT” because
CT has a higher weight assigned. If, however, there are more than 12 PT series for 1 CT series,
the result will be “PT”.
81. List of modalities to move series to the end of the study structure

com.softneta.study.lowerPrioritySeriesModalities = OT,SR

Empty by default (no series reordering). The sCSeriesLowerPriority setting of Dicomweb


plugin has a similar effect but is implemented differently.

5.1.10. Opening the H2 Console

Warning: MedDream sessions are incompatible with H2 Console sessions. Use the incognito mode or
another browser if MedDream must be used at the same time.
Otherwise, you will need to log out fully every time. The H2 Console has a “Disconnect” button. MedDream
toolbar has a “Log Off” button, which is renamed to “Close” in HIS integration mode (and logs off, even if the
window fails to close afterwards).

1. Add to (or uncoment in) application.properties, then restart the application:

spring.h2.console.enabled = true
spring.h2.console.settings.web-allow-others = true
authentication.manager.username = ADD_USER_NAME_HERE
authentication.manager.password = ADD_STRONG_PASSWORD_HERE

2. Open SERVER_IP:SERVER_PORT/h2-console in the browser. The browser will request HTTP credentials
configured above, then display Console’s own graphical login form.
3. In the Console login form, make sure the JDBC URL form field contains
jdbc:h2:file:MEDDREAM_ROOT_DIR/sys/database/DB_NAME (with real path instead of
MEDDREAM_ROOT_DIR, and real database name instead of DB_NAME).
Example: jdbc:h2:file:C:/PROGRA~1/PacsOne/php/meddream/sys/database/reportdb.
4. User Name is normally “sa”, however the “authdb” database requires an empty value. Password must
always be empty.
5. Press the Connect button.
6. You should now see some table names at the left, unless an empty database is expected.

Warning: Leaving H2 Console enabled for a long time is a security risk. Disable it as soon as the work is
done, with spring.h2.console.enabled = false.
The safest way is to always use spring.h2.console.settings.web-allow-others = false: the Console
will then open on localhost only. This is OK for Windows machines, as they are often managed via Remote

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


105

Desktop or similar graphics-capable means, and a browser can be run on the server itself. For Linux
machines accessed via SSH, we advise to tunnel the corresponding port (likely localhost:80) to some other
port on operator’s machine, and open a browser there.

5.1.11. Using MySQL for Spring Batch and Quartz Scheduler

By default MedDream uses H2 for all built-in databases. The reason is simplicity: they can be created
automatically due to nature of this DBMS.
MySQL or MariaDB is supported as an alternative. It is advised for installations with high load (for example,
large hospitals with preparation enabled). Switching is easier if done shortly after installation, and involves the
following steps:
1. Create two new databases in MySQL. We suggest names mdquartz and mdbatch although any names will
be OK. It is essential to have dedicated databases instead of reusing some existing one.
2. Create a dedicated user that has access only to these databases and only from a specific machine. Avoid
using the ``root`` user. Example:

GRANT ALL PRIVILEGES ON mdbatch.* TO 'mdjobs'@'localhost' IDENTIFIED BY 'PASS';


GRANT ALL PRIVILEGES ON mdquartz.* TO 'mdjobs'@'localhost' IDENTIFIED BY 'PASS';
FLUSH PRIVILEGES;

Substitute a new password for PASS. Do not reuse existing ones as this password will be visible
in the configuration file.
3. Add to application.properties:

spring.flyway.locations = classpath:/batch/db/mysql
datasource.quartz.url = jdbc:mysql://SERVER:PORT/mdquartz?user=USER\
&password=PASS
datasource.quartz.driverClassName = com.mysql.cj.jdbc.Driver
datasource.batch.url = jdbc:mysql://SERVER:PORT/mdbatch?user=USER\
&password=PASS
datasource.batch.driverClassName = com.mysql.cj.jdbc.Driver

SERVER, PORT, USER and PASS must be changed to real values. If you gave different names
instead of mdquartz and mdbatch, then they must be changed as well.
4. Start the MedDream service.
• In case of fatal errors, like unrecognized password, the service will fail to start. Check whether it’s still
running after a couple of minutes.
• Look for any new ERROR messages or stack traces in the log.
• Verify that a few tables, including flyway_schema_history, have been created in each database.
• Try using functionality that involves background jobs, like in-advance preparation (triggered either by
IAN messages or forwarded files) or Share via DICOM Library.
At the moment Softneta doesn’t provide instructions on how to transfer contents of these databases, as in most
cases they are of little value and can be recreated at virtually no cost.

Note: In fact, the set of ALL PRIVILEGES is only required during:


• the first run of MedDream service in a new installation (it will create the tables),
• the first run of a new version (it might adjust the structure).
Afterwards one can use a smaller set, namely, SELECT, INSERT, UPDATE, DELETE.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


106

This hardening has a cost, however: just before every upgrade of MedDream you will need to restore ALL
PRIVILEGES for a short time. If you forget that, you’ll get an error like “ALTER command denied to user”, and
the flyway_version_history table will remain in a broken state: retries will result in error “Schema . . . contains
a failed migration”. The latter can usually be fixed by removing the newest record from the table (look at the
“installed_on” timestamp); however a safer way is to restore the entire database from a backup.

5.1.12. Changing the HTTP context path

Sometimes one needs a non-default context path, like http://server.tld/meddream/ instead of just http://
server.tld/ (for example, to isolate multiple installations of MedDream).
A proven solution involves accessing the backend via a proxy that changes every “/meddream” to “/meddream/”.
For Apache, the following mod_rewrite directive solves the problem:

RewriteRule ^/meddream$ /meddream/ [R]

5.1.13. Adjusting a reverse proxy

If a reverse proxy is used, it might interfere with websockets. Currently MedDream depends on the latter for
configurations with features.liveShare=true or openTabsTrackingMethod=SOCKETS (both can be enabled in
system.json).
A most common failure is due to the Origin header added by proxies, that results in a message “Handshake
request rejected, Origin header value https://127.0.0.1 not allowed” in MedDream logs. To correct that, you can
add the following to the proxy configuration:
• Apache: RequestHeader unset Origin (requires mod_header);
• Nginx: proxy_set_header Origin "";

5.1.14. Caching studies via DICOM Listener

Note: MedDream 8.0.0+ enables most options by default; sender’s AE Title still needs to be specified manually.

The DICOM Listener (local Store SCP) can run in parallel to any kind of PACS integration.
Non-direct integration plugins like Orthanc, Dicomweb and QR have their own caches with directory tree
compatible to that of the SCP. A plugin cache directory setting can point to a corresponding subdirectory of
the SCP cache, then the plugin will pick up files sent to the SCP in advance.
The Listener can also automatically start the preparation of a received file. This works even with direct integration
plugins, at a cost of some disk space because the file is then received only for triggering the preparation (based
on UIDs from the file) and can be removed shortly afterwards; the preparation reads its own copy of the file from
the PACS file system. So far the direct integration plugins can’t reuse the SCP cache (for example, to avoid a
slower on-demand reading from network storage).

Note: Starting from 7.8.0, there is an alternative preparation trigger that saves both disk space and network
traffic: the PACS can send DICOM Instance Availability Notifications instead of files. (The Listener implements
both Store SCP and IAN SCP.)

Therefore for a significant performance boost one can configure the PACS to forward studies to MedDream, and
adjust related MedDream parameters:

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


107

# These two must be configured or else the Listener won't start up.
com.softneta.dicom-store-service.port=11116
com.softneta.dicomStoreService.acceptAETitles=pacs

# It's possible to assign a different AE Title to MedDream.


com.softneta.dicom-store-service.localAETitle=MEDDREAM

# Cache root directory. A subdirectory with sender's AE Title (only values from
# acceptAETitles) is created automatically.
com.softneta.dicom-store-service.saveDirectory=file:///opt/meddream/temp/STORE/

# If true, the Listener creates preparation jobs with study/series/image UIDs


# from received files or IANs.
# True by default since 8.0.0.
#com.softneta.dicomStoreService.prepareReceivedFile=true

# If true, then preparation jobs are executed; otherwise they remain in paused state
# after creation.
#True by default.
#com.softneta.preparation.enabled=true

# If true, the cache index is periodically saved into a file "cache.keys" under
# com.softneta.meddream.tempDir, and loaded during application startup.
# True by default since 8.0.0.
#com.softneta.preparation.persistCache=true

# Plugin configuration. An AET listed in acceptAETitles is needed in storeScpAet,


# and dicomCacheDirectory must end with a corresponding subdirectory.
com.softneta.meddream.pacs.configurations[0].storeScpAet=pacs
com.softneta.meddream.pacs.configurations[0].dicomCacheDirectory=file:///opt/meddream/\
temp/STORE/pacs/

Warning: The .storeScpAet setting is used to find the plugin that will be used during preparation, and decide
whether the received file is to be removed afterwards.
If you have multiple plugins, then configure a different and not empty .storeScpAet for each plugin.
It might be required to assign some fake and non-realistic AETs. Consequently, a setup where the same
PACS is accessed both via a native plugin and via QR, becomes problematic as only one of them can upload
annotations/screenshots via the universal mechanism. Probably using .storageApiEnabled=true for the QR
plugin can help there, as the plugin will then use its own .remoteAET instead.

5.1.15. Monitoring via Prometheus/Grafana

1. Enable the status endpoint in application.properties and restart the service:

management.endpoint.prometheus.enabled=true
management.endpoints.web.exposure.include=prometheus
management.server.port=8081
management.server.address=127.0.0.1

This configuration makes /manage/prometheus available on 127.0.0.1:8081. Non-default port


and address are important because this endpoint does not require authentication.
For a quick test, start a web browser (or a tool like curl) on the server and open http://127.0.0.1:
8081/manage/prometheus. It should return certain text-like data:

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


108

# HELP jvm_gc_memory_allocated_bytes_total Incremented for an increase in the␣


˓→size of the (young) heap memory pool after one GC to before the next

# TYPE jvm_gc_memory_allocated_bytes_total counter


jvm_gc_memory_allocated_bytes_total{application="MedDream 7.8.0",} 1.807134632E9
...

2. Install Prometheus on the same server as MedDream


See https://prometheus.io/docs/prometheus/latest/installation.
Because MedDream exposes the data on the same host only, software from other hosts won’t
be able to access it. Exposing the data publicly would be a serious security risk.
3. Add MedDream status endpoint to prometheus.yml
See https://prometheus.io/docs/prometheus/latest/configuration/configuration.
scrape_configs.metrics_path must be /manage/prometheus. scrape_configs.static_configs
.targets must contain the IP and port pair of the status endpoint. Example:

scrape_configs:
- job_name: 'prometheus'
metrics_path: '/manage/prometheus'
scheme: 'http'
static_configs:
- targets: ['127.0.0.1:8081']

By default Prometheus listens on all IP addresses and port 9090. Like the status endpoint,
Prometheus itself should be available on localhost only. Address and port are changeable not
in prometheus.yml but via command line parameter --web.listen-addres (for example, in the
prometheus.service wrapper under Linux with systemd).
For a quick test, open http://127.0.0.1:9090/ on the server, enter “system_cpu_usage” as
Expression, press Execute and choose the Graph tab below.
4. Install Grafana on the same server as MedDream
See https://grafana.com/docs/grafana/latest/installation.
5. Add Prometheus as data source
Open http://localhost:3000/ in the browser. Choose “Add your first data source” on the first page.
Choose “Prometheus” from the list. Enter “http://localhost:9090/” as URL, and press the “Save &
test” button at end of the page. A message “Data source is working” should appear above.
See https://grafana.com/docs/grafana/latest/features/datasources/add-a-data-source for more
details.
6. Add a dashboard
Choose “Create your first dashboard” on the first page. Press the plus sign on the left and
choose “Import”. Under “Import via grafana.com”, enter 4701 (or 10280) and press Load. Specify
the data source created earlier, and press Import.
See https://grafana.com/docs/grafana/latest/reference/export_import for more details.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


109

5.1.16. Implementing per-user settings

When the identity of a user without the “ADMIN” permission is known (the user has logged in via the login form, or
a HIS integration token provides the “id” field), then MedDream attempts to load a custom file <login>_global.
json.
If that fails, and the user belongs to one or more groups, then the first group name is chosen for the second
attempt with another custom file <group>_global.json.
As a last resort there is one more attempt with the traditional file global.json.

Note: Some settings, like Info Labels, are global by design and will be ignored in a per-user settings file. The
Settings window does not indicate that at the moment.

Note: The legacy “insecure” HIS integration (URL-based, not token-based) does not support user identities and
always uses the common global.json file.

Note: The user account that will use a custom settings file, must not have the “ADMIN” permission. A login
form account can have this permission individually like authorization.users[0].role=ADMIN, however a value
common to all users is possible in authorization.defaultLoginPermissions. In case of HIS integration, the
.permissions array in the token is the only possible source.

Note: If global.json was renamed via com.softneta.settings.globalFileName, then <login>_ is prepended to the
configured file name.

Starting from 8.1, a user with “USER_SETTINGS” permission (but without “ADMIN” permission) can save
to <login>_global.json directly, even if the file doesn’t exist yet. This implies that afterwards he won’t see any
changes made by the administrator to the common file global.json, as his own settings file is loaded first.
Starting from 8.2, a user with “SHORTCUTS_EDIT” permission can edit keyboard/mouse shortcuts. If “ADMIN”
is also present, then the global file shortcuts.json is edited, while users without “ADMIN” permission will save
to <login>_shortcuts.json instead. Furthermore, even without “SHORTCUTS_EDIT” the user will load an
existing individual file which then is read only.
8.2+ also keeps the hanging protocols settings in a separate file, hangingProtocols.json. The logic is
similar to that of shortcuts. Users with “ADMIN” permission are always editing this file. Other users can load
<login>_hangingProtocols.json in read only mode, and if the “HANGING_PROTOCOLS_EDIT” permission
is present, then this file becomes editable. If a user has “HANGING_PROTOCOLS_EDIT” instead of “ADMIN”,
and the individual file doesn’t exist yet, then it’s created when saving the hanging protocols settings.
As of 8.2, columns.json is not personalizable.
An administrator (who has the “ADMIN” permission) can only view/edit the common global.json file. If
giving the USER_SETTINGS permission is unsuitable due to some reason, then it is still possible to prepare
personalized read-only settings files as follows:
1. Make a copy of global.json.
2. Log in as an administrator (the account must have the “ADMIN” permission), open the Settings window,
make all planned changes and save the settings.
3. Rename the updated global.json to <login>_global.json. This <login> is an exact value of the user
name from the login form, or of .user.id from the HIS integration token. Leave the custom file in the same
directory.
4. Restore global.json from the copy.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


110

5. To verify, log in as an ordinary user (without the “ADMIN” privilege) from the login form, or open a study
from HIS via the token.
The manual duplication steps above are valid not only for global.json but also for other personalizable settings
files.
Example of a HIS integration token with the login name:

{
"items": [
{
"studies": {
"study": "1.2.826.0.1.3680043.8.1055.1.2020050611210409.446757335",
"storage": "OrthancDicomweb"
}
}
],
"permissions": [ "PATIENT_HISTORY", "FORWARD", "DOCUMENT_VIEW" ],
"user": {
"id": "jdoe",
"name": "John Doe"
}
}

This token suggests using settings from the file jdoe_global.json, etc.

5.1.17. Custom columns in Patient History / Patient Studies

MedDream 8.2 offers customizable columns in the Patient History (opens from the thumbnail strip) and Patient
Studies (opens automatically in a certain token-based scenario). The Search window is not customizable so far.
Customization must also be supported by PACS integration plugins. So far those are only QR and Dicomweb
plugins.
A new file sys/settings/columns.json configures the GUI. The default contents are:

{
"patientHistoryColumns": [
{
"name": "openStudyColumn",
"parameters": [
"uid",
"storageId",
"sensitive",
"restricted"
],
"type": "openStudy",
"customClass": "flex-basis-9 center"
},
{
"name": "reportColumn",
"parameters": [
"hasReport"
],
"type": "report",
"customClass": "center"
},
{
"name": "patientId",
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


111

(continued from previous page)


"parameters": [
"patientId"
],
"type": "string",
"labelTranslation": "common.id"
},
{
"name": "patientName",
"parameters": [
"patientName"
],
"type": "string",
"labelTranslation": "common.name"
},
{
"name": "modality",
"parameters": [
"modality"
],
"type": "string",
"customClass": "flex-basis-11",
"labelTranslation": "common.modality"
},
{
"name": "description",
"parameters": [
"description"
],
"type": "string",
"labelTranslation": "common.description"
},
{
"name": "dateTime",
"parameters": [
"date",
"time"
],
"type": "dateTime",
"labelTranslation": "common.dateTime"
},
{
"name": "sourceAE",
"parameters": [
"sourceAE"
],
"type": "string",
"customClass": "flex-basis-15",
"labelTranslation": "common.sourceAE"
}
],
"patientStudiesColumns": [
{
"name": "openStudyColumn",
"parameters": [
"uid",
"storageId",
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


112

(continued from previous page)


"sensitive",
"restricted"
],
"type": "openStudy",
"customClass": "flex-basis-9 center"
},
{
"name": "patientId",
"parameters": [
"patientId"
],
"type": "string",
"labelTranslation": "common.id"
},
{
"name": "patientName",
"parameters": [
"patientName"
],
"type": "string",
"labelTranslation": "common.name"
},
{
"name": "modality",
"parameters": [
"modality"
],
"type": "string",
"customClass": "flex-basis-11",
"labelTranslation": "common.modality"
},
{
"name": "description",
"parameters": [
"description"
],
"type": "string",
"labelTranslation": "common.description"
},
{
"name": "dateTime",
"parameters": [
"date",
"time"
],
"type": "dateTime",
"labelTranslation": "common.dateTime"
},
{
"name": "sourceAE",
"parameters": [
"sourceAE"
],
"type": "string",
"customClass": "flex-basis-15",
"labelTranslation": "common.sourceAE"
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


113

(continued from previous page)


}
]
}

Values of “name” known to the GUI: openStudyColumn (special handling), reportColumn (special handling),
patientId, patientName, modality, description, dateTime, sourceAE.
Values of “parameters” (field names) known to the plugins: uid, storageId, sensitive (certain non-
public plugins only), restricted (certain non-public plugins only), hasReport (QR plugin only), patientId,
patientName, modality, description, date, time, sourceAE, receivedDate, custom1, custom2 . . . custom10.
At the plugin, the corresponding fields are set up like this (. . . columns.PARAMETER_NAME.*):

com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.patientId.tag=1048608
#...
com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.sourceAe.tag=1048624
com.softneta.meddream.pacs.configurations[PLUGIN_INDEX_NUMBER].columns.sourceAe.type=string

“parameters” in columns.json lists fields from the plugin that will be combined into the value (multiple parameters
are joined with a space character). At the plugin, . . . columns.PARAMETER_NAME.* configure what DICOM
attribute to use for this field (documentation of QR and Dicomweb plugins provides more details).

5.1.18. Passing configuration via environment variables

In some installations, especially Docker-based, it is more convenient to have a fixed application.properties file
where a few settings are missing, and pass those settings via environment variables instead.
For this to work, the environment variable must be named according to Spring Boot “relaxed binding” rules.
Example configuration variable: com.softneta.meddream.pacs.configurations[0].baseUrl.
Corresponding environment variable: COM_SOFTNETA_MEDDREAM_PACS_CONFIGURATIONS_0_BASE_URL.
PacsOne and Dicomweb plugins also support COM_SOFTNETA_MEDDREAM_PACS_CONFIGURATIONS_0_BASEURL etc.
(without any underscores as uppercase hints) in their variables.

5.1.19. Setting up Azure SSO with SAML 2.0

You will need to have the following:


• a MedDream installation
• Microsoft Azure account
• SSL set up either in MedDream or in a reverse proxy (Apache or Nginx)

5.1.19.1. Set up Azure AD SAML Toolkit

Follow instructions how to set up Azure AD SAML Toolkit: https://learn.microsoft.com/en-us/azure/


active-directory/manage-apps/add-application-portal
After creating the Toolkit, click 2. Set up single sign on and add the following URLs in Basic SAML Configuration
section:

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


114

Parameter Value
Identifier (Entity ID) https://MEDDREAM_URL/saml2/service-provider-metadata/
a8c544d-c442-4e94-aee4-2df9cb2992aa
Reply URL (Assertion Consumer https://MEDDREAM_URL/login/saml2/sso/a8c544d-c442-4e94-aee4-2df9cb2992aa
Service URL)
Sign on URL https://MEDDREAM_URL/saml2/authenticate/
a8c544d-c442-4e94-aee4-2df9cb2992aa

Change MEDDREAM_URL to real IP address or domain.


Change a8c544d-c442-4e94-aee4-2df9cb2992aa to Application ID of the SAML Toolkit.
In the SAML Certificates section, copy the App Federation Metadata Url, for example, https:
//login.microsoftonline.com/a6a6746e-14bd-4e68-9c12-7593d8871c3c/federationmetadata/2007-06/
federationmetadata.xml?appid=9a8c544d-c442-4e94-aee4-2df9cb2992aa. It will be required in the next
step.

5.1.19.2. Set up MedDream Viewer with Azure AD

Azure doesn’t support plain HTTP hyperlinks, therefore either MedDream itself must use SSL, or you can use a
reverse proxy.
(Option 1) MedDream Viewer with SSL
Configure the following in application.properties for SSL:

server.ssl.key-store=${com.softneta.meddream.configRoot}/keystore.jks
server.ssl.key-store-password=password
server.ssl.key-alias=desktop-alias
security.require-ssl=true
server.port=443

. . . and for SAML:

spring.profiles.include=auth-saml
spring.security.saml2.relyingparty.registration.a8c544d-c442-4e94-aee4-2df9cb2992aa.
˓→assertingparty.metadata-uri=https://login.microsoftonline.com/a6a6746e-14bd-4e68-9c12-

˓→7593d8871c3c/federationmetadata/2007-06/federationmetadata.xml?appid=9a8c544d-c442-4e94-

˓→aee4-2df9cb2992aa

As in previous section, change a8c544d-c442-4e94-aee4-2df9cb2992aa to real Application ID.


Change the value of . . . metadata-uri= to App Federation Metadata Url copied earlier.
Restart MedDream service after saving changes.
(Option 2) MedDream Viewer with Apache-based reverse proxy that provides SSL
Configure the following in application.properties for proper interaction with the reverse proxy:

server.port=8080
server.use-forward-headers=true
server.forward-headers-strategy=native
server.tomcat.remote-ip-header=x-your-remote-ip-header
server.tomcat.protocol-header=x-your-protocol-header

. . . and for SAML:

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


115

spring.profiles.include=auth-saml
spring.security.saml2.relyingparty.registration.a8c544d-c442-4e94-aee4-2df9cb2992aa.
˓→assertingparty.metadata-uri=https://login.microsoftonline.com/a6a6746e-14bd-4e68-9c12-

˓→7593d8871c3c/federationmetadata/2007-06/federationmetadata.xml?appid=9a8c544d-c442-4e94-

˓→aee4-2df9cb2992aa

spring.security.saml2.relyingparty.registration.a8c544d-c442-4e94-aee4-2df9cb2992aa.acs.
˓→location=https://MEDDREAM_URL/login/saml2/sso/{registrationId}

As in previous section, change a8c544d-c442-4e94-aee4-2df9cb2992aa to real Application ID.


Change the value of . . . metadata-uri= to App Federation Metadata Url copied earlier.
Change MEDDREAM_URL to real IP address or domain.
Note: . . . acs.location= in this scenario tells Azure which URL is to be used for the login.
Restart MedDream service after saving changes.
Add the following to Apache’s httpd.conf:

Listen 443
<VirtualHost *:443>
ServerName MEDDREAM_URL
ServerAlias MEDDREAM_URL
ServerAdmin MEDDREAM_URL

SSLEngine on
SSLProxyEngine on
SSLCertificateFile "${SRVROOT}/conf/ssl/cert.crt"
SSLCertificateKeyFile "${SRVROOT}/conf/ssl/cert.key"

#MedDream
ProxyPreserveHost On
RequestHeader add X-Forwarded-Proto https
ProxyTimeout 800
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
ErrorLog "|bin/rotatelogs.exe -l logs/meddream.error.%Y.%m.%d.log 86400"
CustomLog "|bin/rotatelogs.exe -l logs/meddream.access.%Y.%m.%d.log 86400" common
</VirtualHost>

The most important ones are ProxyPreserveHost and RequestHeader.


Restart the Apache service after saving changes.

5.1.19.3. Test login from Azure AD to MedDream Viewer

Log in to https://portal.azure.com with test user account which you have created when you set up Azure AD
SAML Toolkit, then go to Active Directory > Enterprise Applications. Choose “Azure AD SAML Toolkit” created
earlier. In Manage section choose Single sign-on.
Scroll down till you see section 5 Test single sign-on with Azure AD SAML Toolkit and press the Test button.
Select Sign in as current user and click Test sign-in button. It will open a new tab for sending login information
to Microsoft. Enter test user email address and password.
After a successful login, the page will change to MedDream Viewer search window.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


116

5.1.20. Setting up Keycloak SSO with SAML 2.0

(This is a summary that assumes the reader is already familiar with Keycloak. Please contact
[email protected] for the detailed version with screenshots.)
1. In Keycloak, create a Realm, a Client, at least one test user and export the certificate of that client.
2. Copy the exported certificate (files .crt and .key) to MedDream Viewer installation directory, for example,
C:\MDPACS\MedDream.
3. Add the following to application.properties

spring.profiles.include=auth-saml
authorization.defaultLoginPermissions=SEARCH,EXPORT_ISO,EXPORT_ARCH,FORWARD,
˓→REPORT_VIEW,REPORT_UPLOAD,PATIENT_HISTORY,UPLOAD_DICOM_LIBRARY,DOCUMENT_VIEW,

˓→FREE_DRAW_EDIT,BOUNDING_BOX_EDIT

spring.security.saml2.relyingparty.registration.REALM_NAME.signing.
˓→credentials[0].private-key-location=file:///C:/MDPACS/MedDream/myalias.key

spring.security.saml2.relyingparty.registration.REALM_NAME.signing.
˓→credentials[0].certificate-location=file:///C:/MDPACS/MedDream/myalias.crt

spring.security.saml2.relyingparty.registration.REALM_NAME.assertingparty.
˓→metadata-uri=http://KEYCLOAK_ADDR_PORT/realms/meddream/protocol/saml/

˓→descriptor

and update REALM_NAME to the actual realm name, KEYCLOAK_ADDR_PORT – to the


address (and possibly port) of Keycloak server. Then adjust paths to .key and .crt files.
4. Save the changes and restart the MedDream service.
5. Open MedDream root URL in the web browser (for example, http://127.0.0.1:8082). It will be automatically
redirected to Keycloak login page.
6. Enter the username and password created in Keycloak during the first step.
7. If credentials and configuration are correct, the Search window of MedDream will open.

5.1.21. Avoiding service restart after some configuration changes

8.3.1 supports a “configuration server”: a cloud-dedicated mechanism where a separate JAR is running and
provides a fresh copy of application.properties for multiple MedDream instances. Currently you can run it on the
same machine for a single MedDream instance.
1. Create a dedicated subdirectory (for example, “C:\MDPACK\MedDream\configserver”). Move the file md-
config-server-0.0.1-SNAPSHOT.jar to that directory.
2. Create a couple of deeper subdirectories config/md (“C:\MDPACK\MedDream\configserver\config\md”)
and an empty file md.properties (not application.properties) there.
3. Copy storage definitions (PACS plugin configuration) from MedDream to this file. Another supported setting
is com.softneta.dicom-store-service.acceptAETitles. Other settings were not tested so far, and might
result in undefined behavior, or not apply as expected. For example,

com.softneta.dicom-store-service.acceptAETitles=PACS4

com.softneta.meddream.pacs.configurations[0].type=Dcm4chee2
com.softneta.meddream.pacs.configurations[0].id=d4c2Local
com.softneta.meddream.pacs.configurations[0].url=\
jdbc:mysql://172.16.32.11:3306/pacsdb
com.softneta.meddream.pacs.configurations[0].username=pacs
com.softneta.meddream.pacs.configurations[0].password=pacs
com.softneta.meddream.pacs.configurations[0].defaultStoragePath=\
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


117

(continued from previous page)


C:/PACS/dcm4chee/server/default/archive

com.softneta.meddream.pacs.configurations[1].type=FileSystem
com.softneta.meddream.pacs.configurations[1].id=files1
com.softneta.meddream.pacs.configurations[1].rootDirectory=C:\\upload

4. From the dedicated directory, start the JAR: java -Dspring.profiles.active=native -jar C:\MDPACS\
MedDream\md-config-server-0.0.1-SNAPSHOT.jar (include the full path to JRE executable if needed).
5. At MedDream side, add the following to application.properties (or change existing lines), then restart the
MedDream service:

authentication.manager.username = admin
authentication.manager.password = <USE A STRONG PASSWORD>
management.endpoints.enabled-by-default = true
management.endpoints.web.exposure.include = refresh

This is similar to other parts of this Manual which also suggest configuring manager’s credentials
and exposing some management endpoints. For this scenario a strong password and the
endpoint name “refresh” are sufficient.
6. After adding more plugin configurations at the configuration server (C:\MDPACK\MedDream\configserver\
config\md\md.properties), or changing the acceptAETitles setting there, make a POST call to
<MedDream URL>/manage/refresh, with the configured credentials passed via Basic Authentication.
The configuration will refresh immediately. After reloading the GUI in browser, or logging in anew,
you’ll see the updated set of storages.
Current limitations:
• MedDream requires at least one plugin in order to start, therefore you can’t begin with no plugin
configurations in its application.properties. Include at least one initially (at both sides), then add more
at the configuration server.
• Plugin configurations present in MedDream’s application.properties can’t be removed via the configuration
server. Furthermore, their copies should always remain in md.properties to avoid unexpected and hard to
troubleshoot behavior.
For example, a particular plugin was defined as the second one (...[1]) and you remove the
first one. Then this new [0] coming from configuration server will be merged with the original [0]
at MedDream, which means overwriting properties with the same names.
The configuration server starts on port 8888, and MedDream expects it there. If this port can’t be used on your
machine, then more configuration is necessary. Suppose you chose the port 12345:
• create a dedicated application.properties file in the configuration server’s directory (C:\MDPACK\MedDream\
configserver\application.properties) and add a single server.port setting:

server.port=12345

• in MedDream’s application.properties, specify the port using a different syntax:

spring.config.import=configserver:http://127.0.0.1:12345

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


118

5.2. Running as a service

Troubleshooting incomplete configuration is more difficult when a service is involved. You should first make sure
that MedDream already works as expected when Java Core is started from a console window.

5.2.1. Windows

1. In the directory of MedDream-*.jar, copy MedDream.NET2.exe or MedDream.NET4.exe (depends on


installed .NET version) to MedDream.exe;
2. Open an elevated Command Prompt;
3. Run the command MedDream.exe install;
4. Start the “MedDream” service from the Windows service manager.
When configuring the Token Service this way, a different directory is required. It’s because both Java
applications attempt to read the same application.properties file, however the Token Service needs either a
separate file or none at all.
In the MedDream installation archive, all files related to Token Service already are in a separate subdirectory.
We suggest moving the entire subdirectory (not just files in it) to a suitable place.
1. In its installation directory, copy the chosen token-service.NET?.exe to token-service.exe;
2. Open an elevated Command Prompt there;
3. Run the command token-service.exe install;
4. Start the “MedDream Token Service” from the Windows service manager.

5.2.2. Linux (System-V init)

If your system is RedHat-like (Fedora, RHEL, etc.), then copy {INSTALL_DIRECTORY}/meddream.redhat


to {INSTALL_DIRECTORY}/meddream. If it’s Debian-like (Ubuntu, Debian itself, etc.), then copy
{INSTALL_DIRECTORY}/meddream.debian to {INSTALL_DIRECTORY}/meddream.
Execute the following commands:

sudo ln -s {INSTALL_DIRECTORY}/meddream /etc/init.d/meddream


sudo chmod +x {INSTALL_DIRECTORY}/meddream {INSTALL_DIRECTORY}/meddream-jar-wrapper
sudo service meddream start
sudo chkconfig meddream on

Note: The variable BASEDIR in the script is dynamically initialized with the directory of the script itself. This
means that you must leave the script near the JAR file, and place only a softlink in /etc/init.d, like in the above
example. The entire script can be copied to /etc/init.d only if you adjust BASEDIR, too.

As Debian-like systems don’t have chkconfig, the last command can be replaced with sudo update-rc.d
meddream defaults.
By changing the line USER=root in {INSTALL_DIRECTORY}/meddream, you can force a less privileged user that
can still access DICOM files etc. However this will likely require updating the line PIDF=/var/run/$PROG.pid,
too, as /var/run is usually a privileged location (a chown’ed subdirectory will suffice in that case).
The file {INSTALL_DIRECTORY}/meddream also contains the JRE command line, for example:

MD_JAR_COMMAND="java -cp ./MedDream-8.3.1-dev.jar -Xmx1G -Dloader.path=./sys/plugins -Djava.


˓→library.path=./lib -DANTLR_USE_DIRECT_CLASS_LOADING=true org.springframework.boot.loader.

˓→PropertiesLauncher"

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


119

To configure the Token Service this way, change the file names and command parameters accordingly:
• /opt/token-service/token-service.redhat or /opt/token-service/token-service.debian is copied
to /opt/token-service/token-service;
• in the console,

sudo ln -s /opt/token-service/token-service /etc/init.d/token-service


sudo chmod +x /opt/token-service/token-service /opt/token-service/\
token-service-jar-wrapper
sudo service token-service start
sudo chkconfig token-service on
#sudo update-rc.d token-service defaults

• files /opt/token-service/token-service and /opt/token-service/application.properties will likely


not need any changes.

5.2.3. Linux (systemd)

Create the file /etc/systemd/system/meddream.service with the following text:

[Unit]
Description=MedDream Viewer
After=syslog.target

[Service]
WorkingDirectory=/opt/meddream
User=root
ExecStart=/usr/bin/java -cp MedDream-8.3.1-dev.jar -Xmx1G -Dloader.path=./sys/plugins -Djava.
˓→library.path=./lib -DANTLR_USE_DIRECT_CLASS_LOADING=true --add-opens=jdk.management/com.

˓→sun.management.internal=ALL-UNNAMED --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED --

˓→add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.management/com.sun.jmx.

˓→mbeanserver=ALL-UNNAMED --add-opens=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED --

˓→add-opens=java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED --add-opens=java.

˓→base/java.io=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/

˓→java.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/

˓→java.time=ALL-UNNAMED --add-exports=java.desktop/sun.awt.image=ALL-UNNAMED org.

˓→springframework.boot.loader.PropertiesLauncher

SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Note: Update User=root with the actual username under which the Java application will run.

Execute the following command for service autostart:

sudo systemctl enable meddream.service

To configure the Token Service this way, change the names accordingly: the file is /etc/systemd/system/token-
service.service, and contains

[Unit]
Description=MedDream Token Service
After=syslog.target

[Service]
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


120

(continued from previous page)


WorkingDirectory=/opt/token-service
User=root
ExecStart=/usr/bin/java -Xmx1G -jar /opt/token-service/token-service.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

The service autostart of course needs

sudo systemctl enable token-service.service

5.2.4. Linux (upstart)

Create a file /home/{user name}/.config/upstart/meddream.conf with the following text:

description "MedDream Viewer"


respawn
exec java -cp /opt/meddream/MedDream-8.3.1-dev.jar -Xmx1G -Dloader.path=/opt/meddream/sys/
˓→plugins -Djava.library.path=/opt/meddream/lib -DANTLR_USE_DIRECT_CLASS_LOADING=true --add-

˓→opens=jdk.management/com.sun.management.internal=ALL-UNNAMED --add-opens=java.base/jdk.

˓→internal.misc=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.

˓→management/com.sun.jmx.mbeanserver=ALL-UNNAMED --add-opens=jdk.internal.jvmstat/sun.

˓→jvmstat.monitor=ALL-UNNAMED --add-opens=java.base/sun.reflect.generics.

˓→reflectiveObjects=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.

˓→base/java.nio=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.

˓→base/java.lang=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED --add-exports=java.

˓→desktop/sun.awt.image=ALL-UNNAMED org.springframework.boot.loader.PropertiesLauncher

To configure the Token Service this way, change the names accordingly: the file is /home/{user
name}/.config/upstart/token-service.conf and contains

description "MedDream Token Service"


respawn
exec java -Xmx1G -jar /opt/token-service/token-service.jar

5.3. Verification checklist

Suppose you already went through the 5.1.1 Essential configuration and the first run chapter, configured the
authentication method and PACS plugins, set up Java applications as services, adjusted system.json and even
read the 5.1.9 Reference for remaining configuration parameters superficially.
This is a good opportunity for initial security tightening (see 7 Security considerations, especially the “Summary”
part). If during that process you accidentally disable too much of MedDream functionality, this will be noticed in
subsequent steps.
Afterwards it’s time for a final functionality check-up.
• For installations with an interactive login and Search window:
– The login form does not produce an error message and is successfully replaced by the Search
window. An administrative login (with the ADMIN permission) also succeeds and gives access to
the Settings window.
Remember that the login form is unavailable by default (results in “403 Forbidden” message)
if no authentication method is configured.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


121

In 7.5.1+, there is no sense to have an interactive login if the Search window is disabled (the
text “404” on dark background, due to features.search=false in system.json).
Even if the integration doesn’t offer a working search functionality, you might still decide to
keep the window enabled, at least for a short time – for convenient access to the Settings
window via an administrative login.
– The Search window shows studies from every configured PACS plugin (except FileSystem).

* Results can be restricted by date interval, Patient ID, etc. Keep in mind, however, that some
plugins do not support returning some fields at all, and some plugins do not support filtering by
some returned fields.

* If the plugin supports filtering by user identity, then results are different depending on who is
logged in. Consult configuration of the PACS and MedDream for a suitable identity.
– If Export or Forward are enabled (both globally and by current user’s permissions), then the operation
can be started from the Search window and succeeds.
• For all installations:
– Opening a study succeeds: thumbnails are displayed instead of exclamation marks, the chosen image
opens as well.
Choose the studies wisely and cover at least different modalities.

* Attempt to open MPEG2/MPEG4 video studies if any exist.


* For example, if the PACS stores all images from a particular Source AE, or some historic
images, at a totally different location, then you might not notice a faulty or incomplete
“mappedStorageLocation” plugin setting until those images are accessed.
When opening from the Search window, repeat the attempt for every PACS plugin that
returned some search results.
– From an open study, all functionality allowed by 1) configuration, 2) license and 3) current user’s
permissions, is accessible and succeeds:

* Export (both its versions, “Burn” and “Export”, also including the reports as PDFs),
* Forward,
* Share to DICOM Library,
* Oblique MPR,
* display of PDFs and SRs,
* the expected set of measurements is available.
Repeat with less-privileged users if any exist.
– Verify that the example “demo” / “demo” user account is not present any more.
– The Core service (and the token validation service, if used) starts successfully after rebooting the
entire machine.
– If rebranding is used, then the About window etc. looks as expected.
– Info Label and Thumbnail size settings correspond to end users’ requirements. Changing these two
settings often is not desired: it might also require cleaning of temporary files at the server, therefore
studies will again open slower like during the first time.
• For HIS integration installations:
– In case of “unsafe” integration, check if every enabled URL parameter (“study” etc.) results in opening
of the right studies. If the “storage” parameter is not listed in the validHisParams setting, it will be
silently ignored.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


122

– In case of token-based integration, also check whether MedDream correctly handles all integration
options implemented in your HIS: expected set of object identifiers (“study”, “accnum”, etc. – no
less and no more), token-specified patient history, permission overrides, object restrictions (like by
Patient ID), one-time tokens, limited-lifetime tokens. This will obviously involve different tokens and
experiments at the HIS side.
– If MedDream is supposed to open in an IFRAME at your webpage, then also attempt to open it from
the dedicated network and using the dedicated server hostname.
• For integration into PacsOne web interface:
– MedDream successfully opens from the list of studies (not from the list of patients, series or images).
– Multiple studies are allowed. You should know how many of them the users might want, and configure
the limit accordingly.
– After MedDream opens this way, the expected set of features (Export, Reporting, etc.) is still available
to all users.
A few first days after going online can involve multiple restarts of the Core service. Each restart can leave a
lot of unused temporary files that will be removed some time later. The cleanest way to verify this removal is to
lower every “olderThanSec” setting (for example, to 1 second) temporarily and confirm that all accumulated files
disappear. Nevertheless monitoring of the disk space is still advised.

5.4. Option: dockerized environment

We provide two ready-to-use Docker images that might save you some time, especially during evaluation. See
• https://hub.docker.com/r/meddream/dcm4chee-dicom-viewer for DCM4CHEE 5.x, or
• https://hub.docker.com/r/meddream/orthanc-dicom-viewer for Orthanc.

5.5. Updating the license

After purchasing a commercial license or more concurrent connections, it is necessary to update the license file
(meddream.lic).
On installations with an Internet connection, the “Register” window is sufficient. MedDream will automatically
download the file and place it where appropriate. The new file comes into effect immediately, though restarting
the service is still recommended.
In other cases you must update meddream.lic manually:
• by default it resides in the same directory as application.properties or meddream*.jar, likely it’s /opt/
meddream or C:\MedDreamPACS-Premium\MedDream;
• in dockerized installations a dedicated subdirectory is often used, like /opt/meddream/license – that way
it’s easier to store any changes outside the container;
• when in doubt, look for com.softneta.license.licenseFileLocation in application.properties. If this setting is
not present, it defaults to the directory of the JAR file.
Restarting the service is mandatory after a manual update.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


123

5.6. Cleaning server-side caches

MedDream 8.1+ has the “Clear cache” function for interactive removal of a single study (or series, or image) from
the preparation cache. It must be enabled globally in system.json (features.clearCache=true) and for a particular
user (CLEAR_CACHE permission). This mechanism, however, does not yet extend to DICOM files cached by
some plugins.
The entire preparation cache will need cleaning if:
• you changed the setting com.softneta.preparation.compressPixelsBeforeSave;
Currently the setting controls whether the pixels are cached in compressed or non-compressed
form, and the frontend attempts decompression based on its value (instead of detecting the
existing format). As a result, cached pixels become incompatible after changing the setting.
• you changed the settings Thumbnail size or Info Label properties (the latter, in turn, might be affected by
personNameConfiguration in system.json);
Thumbnails are generated and cached using the configured size, and their appearance on
studies opened earlier might become suboptimal after changing the size.
Info Labels are generated and cached using the configured patterns. This includes a particular
person name format configured elsewhere. Changed patterns will be visible only on studies that
haven’t been opened before.
Plan ahead when choosing the values, as losing many days’ worth of prepared files might be
too costly.
• trackDicomModifications in application.properties is off and some DICOM files have been changed on
the PACS.
For example, PacsOne supports modification of certain DICOM attributes and this is done not
only in the database but in the files, too. The operation updates the file timestamps, therefore
trackDicomModifications=true in case of direct integration is enough for automatic regeneration.
Modalities are an unlikely reason, as they normally use new UIDs after changing patient
demographics etc. in a study that has already been sent to the PACS.
The default location of the preparation cache is “temp/cache” in the directory of the JAR file. Your installation
might redefine it directly via com.softneta.preparation.cacheDir; if only com.softneta.meddream.tempDir is
redefined, then a subdirectory “cache” under it is used by default. To confirm that it’s the right one, examine
the contents: you should see a storage subdirectory (same as .id in configuration of a PACS plugin), then three
two-digit subdirectories like 6f/3e/1b, then a long subdirectory like 89a44027269f77b1cb3948290635077461 and
various files below it.
After removing the cached files, the MedDream service must be restarted in some cases.

5.7. Creating a dump of an H2 database

1. Open H2 Console in the browser, then a corresponding database there (see 5.1.10 Opening the H2
Console for details).
2. Execute the command SCRIPT TO 'db-backup.sql', where “db-backup.sql” can have any name and
extension (an SQL file is always created), and wait for its completion.
By default the file is created in the same directory as the application JAR file; you should be able
to use any other writeable location, too, like /tmp/export.sql or d:\temp\backup.sql.
3. Disable the Console afterwards.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


124

5.8. Restoring an H2 database from a dump

Note: The restore process will destroy current database contents. If in doubt, make a backup.
A binary backup is sufficient. A rather simple way is to copy the database file (it has an extension .mv.db) when
the MedDream service is stopped.

1. Open H2 Console in the browser, then a corresponding database there (see 5.1.10 Opening the H2
Console for details).
2. Remove all content by using the command DROP ALL OBJECTS.
3. Execute the command RUNSCRIPT FROM 'db-backup.sql', using the relevant path to a dump file. Make
sure there are no errors reported.
4. Restart the application so that it has the opportunity to upgrade the database schema, then verify the
functionality related to this database.
5. Disable the Console afterwards.

5.9. Using strong passwords in MySQL accounts

Passwords with special characters, like NN"A_B7;Q{G\.}q5+XTuw=^q, can be difficult to enter correctly in SQL
queries (“IDENTIFIED BY” clause, “SELECT PASSWORD(. . . )” query, etc.) because some characters must be
escaped or else their meaning becomes different. As a result, the password might not be accepted afterwards
even by the same MySQL client.
A workaround is to use an online MySQL password calculator/generator that is entirely browser-based (does not
perform a request to the server during the calculation), then enter the resulting hash into the query that updates
the password.
At the time of this writing (January 2023), we can recommend https://www.browserling.com/tools/
mysql-password; it yields *6BED9D9BC91C5F5994B2F7D4AE105E2E5BBC262F for the example string above.

6. Additional software
MedDream can be used in tandem with several external pieces of software that are listed below.

6.1. Browser plugin

A plugin for the Chrome browser that expands a newly opened tab across several monitors. The URL is scanned
for an entered keyword and if a match is found, a new window is created and expanded across the selected
monitors. The plugin can be added using the Chrome extensions tab.
When using the plugin, it is important to give the MedDream website the “window placement” or “window
management” permission. When opening MedDream for the first time on a particular browser, you should
get a prompt that the website wants “manage windows on all your displays”, then click “Allow”. If you clicked
“Block” back then, this can be adjusted by clicking the “lock” icon near the URL, choosing “Site settings” and
looking for “Window management” there.
To obtain the plugin, please contact [email protected].

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


125

6.2. Writing an ISO file to a USB stick

The legacy solution “MedDreamBurn” is/was for writing ISOs to optical disks. There is no direct equivalent for
writing to USB sticks.
It might be possible, however, to work around using these freeware alternatives:
• ISO to USB (http://www.isotousb.com/) – no command line support and therefore not possible to start
automatically with an ISO file already specified; you will need to specify the file manually. Because
formatting removable media is a privileged operation, Windows UAC prompt might be triggered on every
start.
• Rufus (https://rufus.ie/en/) – again no command line support. Might require a bootable ISO file although
MedDream never creates these.

6.3. Alternative to MedDreamBurn

On Windows it might be enough to use the built-in functionality for writing optical disks:
• Right-click on the file (ISO or BURN) and select “Open With”.
• Select “Choose another app”.
• Select “More apps”.
• Scroll to the bottom and select “Look for another app on this PC”.
• Browse to folder C:WindowsSystem32 and select isoburn.exe
• Click Open.
From now on clicking on those files will start the built-in burner. You might also want to select the checkbox
“Open when done” while the file is still being downloaded.

7. Security considerations
RATIONALE: It is an old dilemma of using “security through obscurity”. As a matter of fact, most MedDream
installations tend to have a few security holes due to non-paranoid Web administrators. The very publication of
this knowledge makes every old/unmaintained MedDream installation an easy target. But we must draw a line
one day so that at least new installations are secure.

7.1. Default passwords

The default application.SAMPLE.properties sets up “in-memory” authentication method with a username “demo”
and password “demo”. It is included only to ease installation and might be known to everyone who has
downloaded a recent MedDream release.
Do not forget to change it (or remove altogether) after the installation is finished.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


126

7.2. Search engines

MedDream is shipped with the following sys/settings/robots.txt:

User-agent: *
Disallow: /

User-agent: AdsBot-Google
Disallow: /

This should prevent finding Internet-exposed MedDream login forms by searching for “MedDream” or “Softneta”
(as most customers don’t use rebranding). Afterwards an attacker could check for known issues or
misconfigurations.
If you still would like to index your installation, or allow indexing for a particular search engine only,
then sys/settings/robots.txt can be modified accordingly (see http://www.robotstxt.org/robotstxt.html) or even
renamed/removed. The backend treats the file as a static anonymous resource and simply returns contents
of the file if it is found.

7.3. DCM4CHEE 2.x

Official installation instructions offer some defaults that sometimes are left unchanged.
After a mindless installation there also will be some default user accounts:
• a database user “pacs” with password “pacs”. Suitable for MedDream when using auth-db-connection;
• an internal user “admin” with password “admin” – suitable for MedDream and DCM4CHEE’s web interface
when using auth-dcm4chee;
• an internal user “user” with password “user” – suitable for MedDream and DCM4CHEE’s web interface
when using auth-dcm4chee.
Any of these accounts can be used to access sensitive patient data. We suggest to change passwords for all
three, as soon as possible after the installation. The first one is used by DCM4CHEE to connect to the database,
therefore you will also need to update the file server/default/deploy/pacs-*-ds.xml (name depends on database
used).

7.4. Embedding into IFRAME etc.

Availability to embed MedDream into FRAME, IFRAME or OBJECT containers allows untrusted websites to use
MedDream in fraudulent manner (“clickjacking”). Since v6.2.1 this is restricted by default: only the server that
hosts MedDream is allowed to wrap it with an additional container.
It is possible to adjust IFRAME permissions in the application.properties file. Valid values for
frameOptionsPolicy: NONE, DENY, SAMEORIGIN, ALLOW-FROM. When NONE is used, then the X-Frame-
Options and Content-Security-Policy headers are not sent; when ALLOW-FROM is used, then valid host must be
set in parameter security.frameOptionsWhitelist. Another parameter, security.contentSecurityPolicy,
can be used to explicitly control the Content-Security-Policy header. Address entries are separated using spaces.

security.frameOptionsPolicy=POLICY_VALUE
security.frameOptionsWhitelist=IP_ADDRESS or HOST_ADDRESS
#security.contentSecurityPolicy = frame-ancestors 'self' IP_ADDRESS HOST_ADDRESS

It is recommended to use contentSecurityPolicy instead, as support for ALLOW-FROM in browsers is more


limited.
Functionalities “Copy the image to the clipboard” and “Copy measurements to the clipboard” depend on IFRAME
parameters, too. One must add the permissions “clipboard-read” and “clipboard-write” to the tag attributes:

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


127

<iframe src="meddream/index.html" allow="clipboard-read; clipboard-write">


</iframe>

7.5. php.ini

When the same machine also contains a PHP/Apache installation (needed by third-party software like PacsOne),
then some PHP settings might make it less secure. This chapter lists most important recommendations and
caveats.
Error handling
• expose_php = Off
The value “Off” hides the version of PHP from webserver response headers or error messages
and therefore makes it more difficult to scan for known vulnerabilities of PHP itself.
• error_reporting = E_ALL
“E_ALL” is recommended for production. However during installation/troubleshooting of any
server, including a production one, a more detailed choice like “E_ALL | E_STRICT” might be
needed. One could have two versions of this line and comment the inactive one out.
• display_errors = Off
• display_startup_errors = Off
Use “Off” in production for both, or else error messages visible to the end user might reveal paths
to files and other sensitive information.
• track_errors = Off
Can remain disabled as MedDream’s applet.php doesn’t use $php_errormsg.
• html_errors = Off
“On” is not needed and, due to display_errors=Off, has no effect anyway.
• log_errors = On
• error_log = /valid_path/PHP-logs/php_error.log
Logging to a file is preferred over STDERR. The latter means Apache’s error_log where PHP
messages will be intermixed with Apache messages and therefore harder to read.
• ignore_repeated_errors = Off
“On” is OK only as a temporary measure if there are lots of identical errors, they are filling up the
log and nothing else can be done about that right now.
General settings
• doc_root = /PacsOneInstall/php
In 7.5+, the only part of MedDream served over the Web is applet.php when copied to PacsOne’s
“php” directory. In this configuration you can specify this directory or some parent part of the path.
• open_basedir = /PacsOneInstall/php
Not relevant to MedDream anymore.
A non-empty setting provides more benefits (and influence) to other software, like PacsOne GUI,
running on the same Apache server. Take caution and test all functionality.
• include_path = .:/path/PHP-pear/
Keep this list as short as possible. This setting is not related to applet.php of MedDream, but
might be used by other software if hosted on the same server.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


128

• extension_dir = /path/PHP-extensions/
Use a full path.
This parameter is not relevant to MedDream any more.
• mime_magic.magicfile = /path/PHP-magic.mime
Use a full path.
Not relevant to MedDream anymore. When using MedDream with PacsOne on the same host,
PacsOne might still benefit on correct value.
• allow_url_fopen = Off
“On” is not required by MedDream 7.5+.
• allow_url_include = Off
• allow_webdav_methods = Off
“Off” for both is safer and doesn’t interfere with any MedDream functionality.
• variables_order = "GPCS"
A general recommendation, not relevant to MedDream anymore.
• session.gc_maxlifetime = 600
Not relevant to MedDream anymore as sessions are now handled at Java side. Will influence
behavior of PacsOne GUI, though.
A smaller value will log the user off faster if the browser is closed, the computer is suspended or
the Internet connection is cut. 10 minutes is a sane default and the legacy default is 1440 (24
minutes).
File uploads
• file_uploads = Off
MedDream 7.5+ does not contain PHP-based Reporting functionality so this setting doesn’t
apply.
“On” might be important for PacsOne, though, as its Study Notes and Upload Dicom Image
functions work in a similar way.
• upload_tmp_dir = /path/PHP-uploads/
Use a full path. A separate directory might make cleaning leftover files easier.
• upload_max_filesize = 10M
• post_max_size = 40M
Files larger than upload_max_filesize will fail to upload. To account for overhead, ensure
post_max_size > 4*upload_max_filesize and memory_limit > 16*post_max size.
• max_file_uploads = 1
PacsOne always uploads a single attachment together with a Study Note so “1” is a safe choice.
Executable handling
• enable_dl = Off
Not relevant to MedDream anymore, and “Off” is a safer choice.
• disable_functions = system, shell_exec, passthru, phpinfo, show_source,
highlight_file, fopen_with_path, dbmopen, dbase_open, putenv, exec, popen, proc_open,
move_uploaded_file, mkdir, rmdir, chmod, rename, chdir, filepro, filepro_rowcount,
filepro_retrieve, posix_mkfifo

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


129

These functions are generally considered dangerous and applet.php of MedDream does not use
them. However, some might be needed for proper functioning of PacsOne. Take caution and test
the configuration.
Session handling
• session.save_path = /path/PHP-session/
Use an absolute path. This will ensure that both Apache-integrated and CLI versions of PHP
keep session files in the same location.
• session.name = mysessid
You can rename the session cookie to something less obvious.
Not relevant to MedDream anymore but other software on the same Apache server might benefit
from this.
• session.auto_start = Off
Not relevant to MedDream anymore, and “Off” is a safer choice.
• session.use_trans_sid = 0
• session.use_cookies = 1
• session.use_only_cookies = 1
Not relevant to MedDream anymore, and “Off” is a safer choice. Take care with PacsOne, though.
• session.cookie_domain = my.website.tld
Not relevant to MedDream anymore, and “Off” is a safer choice. Take care with PacsOne, though.
• session.use_strict_mode = 1
“1” or “On” is more secure. There is no effect on MedDream functionality in any case.
• session.cookie_lifetime = 0
Zero is the legacy value (the session exists while the browser is not closed) and end users are
accustomed to it. This is more relevant to PacsOne than MedDream.
• session.cookie_secure = 1
Not relevant to MedDream anymore. If Apache also hosts other software that is accessed only
via HTTPS (plain HTTP is undesirable), then set this to “1”.
• session.cookie_httponly = 1
“1” is a general recommendation. Not relevant to MedDream anymore, but might influence other
software if hosted on the same server.
• session.cache_expire = 30
Not relevant to MedDream anymore but might influence other software if hosted on the same
server.
• session.cookie_samesite = Strict # PHP 7.3+
• session.sid_length = 256 # PHP 7.1+
• session.sid_bits_per_character = 6 # PHP 7.2+
• session.hash_function = 1 # PHP 7.0-7.1
• session.hash_bits_per_character = 6 # PHP 7.0-7.1
The above values are recommended and are understood by newer PHP versions.
• session.referer_check = http://server/path

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


130

Not relevant to MedDream anymore but might influence other software if hosted on the same
server. For PacsOne, you can set here a typical URL pointing to its GUI (directories only, without
home.php etc).
Less obvious settings
• memory_limit = 50M
• max_execution_time = 30
Not relevant to MedDream anymore. The setting provides more benefits (and influence) to other
software running on the same Apache server.
• report_memleaks = On
“On” might help to detect memory leaks earlier. Not relevant to MedDream anymore.

7.6. Browser’s cache

MedDream is designed with “zero footprint” concept in mind. From a security perspective this also means that no
patient data is left on a client machine: after the end user logs out from MedDream, its cache does not contain
any server responses with patient data.
Normally browsers obey the “do not cache” headers. Firefox, however, has a bug that allows to extract potentially
sensitive data from browser’s memory cache after the user logs out and doesn’t close the entire browser
application. On a shared computer, an attacker could later examine the memory cache and access data that
isn’t available to him via MedDream and HIS.
Shared computers make protecting sensitive data a lot more difficult. If this is unavoidable, then we recommend
at least to avoid Firefox or teach users to also close the entire browser (not just a particular tab or one of the
windows) after logging out from MedDream.

7.7. Firewalls

Every server, especially the ones that handle medical data, should have a working firewall.
MedDream obviously needs permission to listen at port configured by server.port for a typical HTTP(s) traffic.
When using websockets (system.json: features.liveShare=true, or openTabsTrackingMethod=SOCKETS), they
operate over the same port.
Similarly, the receiver for QueryRetrieve plugin will continuously listen at com.softneta.dicomStoreService.
port for a typical DICOM traffic.
Outgoing network accesses might need to be whitelisted in a corporate firewall:
• the Register function downloads a license file from lic.softneta.com;
• the About window verifies availability of a new version at www.softneta.com;
• the Share function sends anonymized files to dicomlibrary.com.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


131

7.8. Summary: Minimum relevant IT security requirements

• The MedDream installation package must be validated against the SHA-256 value published at
softneta.com. (Scanning it with VirusTotal, https://www.virustotal.com/, is a good idea, too.)
– Windows: certutil -hashfile MedDream-DICOM-Viewer-8.3.1.zip SHA256
– Linux: sha256sum MedDream-DICOM-Viewer-8.3.1.zip
– Mac OS: shasum -a 256 MedDream-DICOM-Viewer-8.3.1.zip
If the displayed hash is the same as provided on the website for that file, then the file has been
downloaded without corruption and can be used safely.
The hash can also be downloaded as a separate file with the extension “.sha256” instead of “.zip”:
https://www.softneta.com/files/meddreamviewer/820/MedDream-DICOM-Viewer-8.3.1.sha256
• The operating system should be up to date with latest security patches.
• All not needed software should be removed from the system to reduce points of possible security breaches.
• Use the latest Java 17 version with all security patches.
• Server version should be hidden in HTTPS responses.
• Open only those firewall ports that are necessary to access MedDream (default Web port 80 or 443, and
default DICOM port 11116 if used) or PACS servers.
• For HIS integration the secure token-based integration is highly recommended, instead of the legacy URL
integration.
• The MedDream backend should not run under a privileged user, like Linux “root” user or Windows
“Administrators” user group.
• MedDream files should have limited permissions (Linux example: 0775 for files, 0664 for directories).
• The MedDream backend should always run over HTTPS (with SSL encryption). Do not use self-signed
certificates; if your company doesn’t have one, then https://letsencrypt.org/ will provide it for free.
• Main security-related settings in application.properties:
– server.servlet.session.cookie.sameSite = strict
– server.servlet.session.cookie.secure = true
– security.xssProtectionDisabled = false
– security.contentTypeOptionsDisable = false
– security.contentSecurityPolicy = default-src 'self'; style-src 'self'
'unsafe-inline'; script-src 'self'; child-src 'self' blob:; connect-src 'self' *;
img-src 'self' data:; worker-src 'self' blob:;
– server.servlet.session.timeout – set a reasonable duration based on network and system
performance.
– authentication.manager.* should be disabled. Enable it only for a short amount of time, and use a
strong password (see below).
– management.server.port = 8081 (or similar) together with management.server.address = 127.0.
0.1, if some software is monitoring the status of MedDream.
– spring.profiles.include = auth-inmemory, authentication.inmemory.*, authorization.
users[] should not be used in production configuration.
• MedDream should use strong passwords everywhere: at least 12 characters with uppercase, lowercase,
numbers, special characters, and not listed in https://haveibeenpwned.com/Passwords.
• User roles must be only those that are absolutely necessary for a particular user. Less roles = more strict
and safe account.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


132

• authorization.defaultLoginPermissions should also be as minimum as possible, to prevent data


breach from extended functionality abuse. User permissions should be based on user authentication and
role control.
• The demo/demo user should be removed from the system.
• When using the bundled Token Service, it should run over HTTPS, too. See end of 5.1.7 Enabling SSL.
• When the Token Service is using the “redis” profile for round-robin parallelization, make sure to not use
the example values of encryption parameters in its own application.properties; new random values must
be generated.
• Search engines like Google should be disabled in robots.txt.
• Main security-related settings in system.json are the MedDream features. Disabling them also disables
corresponding HTTP(s) endpoints:
– turn off search if users won’t use the Search window;
– turn off history if users won’t use the Patient History window;
– turn off reports if users won’t use the Reporting function;
– turn off hangingProtocols if users won’t use the Hanging Protocols function;
– remaining features can also be disabled if not needed.
• Review other MedDream settings to disable any not used functionality.

Warning: IT security can be compromised in the event of:


1. Unauthorized user (hacker) got the access to the operating system and connected to the operating
system where the medical device is installed. In such event the hacker can access sensitive patient
data, can modify or impact medical device functionality and/or performance. MedDream can not detect
such event. Medical device user must apply best security practices to prevent such event by installing
WAF, Firewall, Antivirus and other applications to detect possible security breach.
2. Unauthorized user (hacker) got user/password (or got access token) and connected to the system.
In such event the hacker can access sensitive patient data, can impact medical device functionality
and/or performance. MedDream can not detect such event. Medical device user must apply best
user authentication practices, provide user trainings to improve social engineering knowledge. Medical
device user can use VPN, WAF, Firewall to limit unauthorized users’ access to the medical device.
Medical device user can track web server logs or proxy logs to track and measure possible security
atacks to the system.

Warning: If the IT security is compromised, MedDream does not guarantee any functionality. If there is a risk
that a security issue can impact patient safety or cause sensitive data leak, then it is recommended to stop
using product as soon as possible until the issue is resolved. Depending on the risk impact (for example, when
the issue can not impact patient safety or leak sensitive data), the medical device user can continue using the
device on his own risk. However it is recommended to have an external standby system (redundant, spare
system) which could provide full functionality (or part of it) instead of the compromised system. MedDream
product is fully compatible with the possibility to deploy one or more offline/online standby systems to increase
healthcare process safety, security and reliability.

Warning: “InMemory” users are recommended to use only for testing proposes. In production, please use
DB users or token authentication.
If you found that IT security is compromised, for Emergency work while the system will be fixed we
recommend to create InMemory user(s) with needed permissions: for an administrator, add ADMIN and
SEARCH permissions; for ordinary users, add the SEARCH permission.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


133

Note: MedDream does not detect a change of the client IP address during the session. There are legitimate
cases when this change is possible (for example, because a mobile device is moving).

8. Localization
By default, MedDream is available in English, Lithuanian and Russian; user documentation is only in English.

Warning: Softneta is not responsible for not verified translations made by licensed users. Please note that
Medical Device certificates are not valid for not verified translations.

The default value of “languages” setting in sys/settings/system.json is just “en”. You can specify any available
language or their combination. For example, :["en"] can be changed to :["lt","en","ru"].

9. Rebranding
MedDream can be rebranded and use custom branding information (e.g., logos, product name, some certification
details). Four scenarios are possible:
1. No rebranding was the default in older licenses (v7.8.0 and older). MedDream displays the default logo
pictures, while “Distributor” and “End user” data come from the license;
2. Simple rebranding is usually enabled and allows to change logotypes, system name, default color theme;
3. Full rebranding (also called “Rebranding as a module”, requires a special license) allows to change more
options, however these changes will invalidate CE, FDA and other medical certificates;
4. Viewport rebranding can be used together with Viewports API, where a large portion of MedDream
user interface is not present and can be implemented by the customer. Additional analysis is required to
determine which parts of the product will be certified, please contact [email protected] for assistance.
Since 7.9, the product version number can’t be rebranded and MedDream will always check for the latest version.
All rebranding-related files must be located in the directory sys/settings/rebranding/ below configRoot. The
configuration file is “rebranding_configuration.json”, it must be in valid JSON format (UTF-8, no comments, no
embedded newlines).
An override for the Web resource /favicon.ico is always expected under a name “favicon.ico”. This file must
exist if the license allows rebranding.
Example configuration file for simple rebranding:

{
"systemName":"MyHospital",
"companyLogoFile":"companylogo.jpg",
"productLogoFile":"productlogo.jpg",
"loginLogoFile":"loginlogo.jpg",
"defaultTheme": "red"
}

• systemName
(optional) Name of the system into which MedDream is integrated. Displayed at top of About
dialog if not empty, and overrides the product name in browser tab titles, below login form and
below search results.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


134

• companyLogoFile
Name of a JPG/PNG file with the company logo displayed in the About dialog.
Recommended size is 134 x 28 px. Images wider than 540 pixels do not always fit into the dialog.
A too high image might move the buttons outside the screen so the dialog becomes unusable.
Make sure to check your customization on various client systems (different display DPI, etc.)
from where MedDream will be opened.
• productLogoFile
Name of a JPG/PNG file with the product logo displayed in Wiewer window (top left corner).
Recommended size is 180 x 38. In the viewer the height can be up to 52 px, anything more is
clipped; if the width exceeds 215 px, the rest will overlap with thumbnails. When your picture is
near these limits, it might need checking on various client systems to ensure consistent behavior.
• loginLogoFile
Name of a JPG/PNG file with the login logo displayed in Login window.
Maximum dimensions are 270 x 50. Wider images will not be centered. Higher images will shift
the form towards the bottom of the page.
• defaultTheme
(optional) Selects a predefined color theme from values red (default), blue, green, dark-blue,
dark-green, orange.
The default rebranding configuration strives to provide the same look of MedDream as in not rebranded
installations.
Remaining configuration options are used in rare cases:
• productName
(Required when full rebranding) Replaces the text “MedDream” in the bottom of the login
window, the “Product” part of the About dialog, the title of the browser tab, below login form and
below search results.
For ordinary licenses (rebranding without isUsedAsModule), the product name comes from the
license.
Example:
"productName":"MyViewer"
• manufacturedBy
(Optional, full rebranding only) When true, the Distributor contacts from the license are
displayed as “Manufactured By”.
Example:
"manufacturedBy":true
• uniqueDeviceId
(Optional, full rebranding only) Displayed as “Unique device identifier” in the About dialog.
Consult your certification documents.
Example:
"uniqueDeviceId":"444444455"
• medicalDeviceClass
(Optional, full rebranding only) Displayed as “Medical device class” in the About dialog.
Typically includes both class and legislation where this class is defined; consult your certification
documents.
Example:

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


135

"medicalDeviceClass":"Example Class"
• notifiedBodyId
(Optional, full rebranding only) Displayed as “ID of the notified body” in the About
dialog. Consult your certification documents. A related image at the bottom is taken from
md5/css/icons/certification-logo2.png when rebrandCertified=true.
Example:
"notifiedBodyId":"0123"
• rebrandFdaClarification
(Optional, full rebranding only) Displayed as “FDA Cleared” in the About dialog. Consult your
certification documents. A related image at the bottom is taken from md5/css/icons/certification-
logo.png when rebrandCertified=true.
Example:
"rebrandFdaClarification":"FDA Cleared B12345"
• rebrandCertified
(Optional, full rebranding only) When true, md5/css/icons/certification-logo.png and
md5/css/icons/certification-logo2.png are still displayed despite rebranding.
Example:
"rebrandCertified":true
• catalogueNumber
(Optional, full rebranding only) Displayed as “Catalogue number” in the About dialog.
Hardcoded value “MDSY” when the license does not allow full rebranding.
• mobileDisplayLimitations
(Optional, full rebranding only) Displayed as “Warning” in the About dialog.
Hardcoded value “about.mobileDisplayLimitations” (a particular translation code) when the
license does not allow full rebranding.
• showRepresentativesInfo
(Optional, full rebranding only) Enable display of the “REP” tab in the About dialog.
Hardcoded value true when the license does not allow full rebranding.
• safetySign
(Optional) Object with additional properties for overriding the warning/caution/note symbols and
a corresponding comment in the About dialog:
– warning
Name of the warning icon file (in the same directory as JSON file).
For full rebranding, there is no default image and this setting must be configured in
order to display an icon.
For other kinds of rebranding, a default image is displayed if this setting is not
configured.
– caution
Name of the caution icon file (in the same directory as JSON file).
For full rebranding, there is no default image and this setting must be configured in
order to display an icon.
For other kinds of rebranding, a default image is displayed if this setting is not
configured.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


136

– note
Name of the note icon file (in the same directory as JSON file).
For full rebranding, there is no default image and this setting must be configured in
order to display an icon.
For other kinds of rebranding, a default image is displayed if this setting is not
configured.
– safetySignDescription
(Optional, full rebranding only) Any text about the safety signs.
Hardcoded value “about.safetySignDescription” (a particular translation code) when
the license does not allow full rebranding.

9.1. Changing the progress bar color

The files md5/css/md.*.css are minified and difficult to navigate. You should pretty print the chosen file first, even
free online tools like https://www.cleancss.com/css-beautify/ can handle that.
The following example changes the color in the de-minified “default” theme to pure yellow:

--- a/md.default.45774122db7d.css 2022-12-15 14:37:04.186199200 +0200


+++ b/md.default.45774122db7d.css 2022-12-15 14:37:02.265140800 +0200
@@ -2914,34 +2914,34 @@
.series-progress-bar {
position: relative;
z-index: 1;
display: block;
margin: 0.5rem 0;
width: 100%;
height: 1rem;
border: none;
border-radius: 0.5rem;
background: #afafaf;
- color: #e51b48;
+ color: #ffff00;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
}
.series-progress-bar::-moz-progress-bar {
border-radius: 0.5rem;
- background: #e51b48;
+ background: #ffff00;
}
.series-progress-bar::-webkit-progress-value {
border-radius: 0.5rem;
- background: #e51b48;
+ background: #ffff00;
}
.series-progress-bar::-webkit-progress-bar {
border-radius: 0.5rem;
background: #afafaf;
}
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


137

(continued from previous page)


.list {
display: inline-flex;
flex-flow: column nowrap;
margin: 0;
width: 100%;
@@ -4447,24 +4447,24 @@
.viewports-layout .viewport-container {
position: absolute;
display: flex;
border: 1px solid #323237;
background: #000;
}
.viewports-layout .viewport-container.active {
border: 1px solid #e51b48;
}
.viewports-layout .viewport-container .md-progress-bar::-moz-progress-bar {
- background: #e51b48;
+ background: #ffff00;
}
.viewports-layout .viewport-container .md-progress-bar::-webkit-progress-value {
- background: #e51b48;
+ background: #ffff00;
}
.viewports-layout .instant-notifications {
position: absolute;
top: 0;
right: 0;
z-index: 1000;
display: flex;
flex-direction: column;
overflow-y: auto;
min-width: 0;

10. Troubleshooting
10.1. Preventive measures

The most important step in preventing problems is monitoring, especially for some time just after the installation.
System administrators should regularly watch:
• amount of free space on disks used by MedDream;
Currently MedDream does not stop creating temporary files if amount of free space is
dangerously low, and will proceed until its amount drops to zero. This might result in corrupt
databases (reindexing usually takes a long time) or corrupt cached files (difficult to identify which
ones are corrupt, and too costly to remove everything). If other software is using the same disks,
it might get similar issues. To minimize impact, it is quite important to timely react to low disk
space situations.
The size of temporary/cached files is proportional to user activity. In some installations the daily
amount of new studies sent to the PACS might have a larger influence. Both are not constant
and MedDream therefore might need a periodic review of data age thresholds in temporary files
cleaner configuration. But sometimes the only solution is to add more storage.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


138

• amount of free memory, and memory used by the Java process;


If your license limits number of concurrent connections, then one-time implementation of
recommendations in 5.1.6 Adjusting Java memory limits should be sufficient.
In case of unlimited connections, it is important to know the actual usage statistics first. The
easiest way is to collect the activeConnectionCount property from MedDream’s offline statistics
files (YYYY-MM.stat).
• CPU and I/O load from the Java process;
Helps to identify hardware inadequate for the task.
• whether a time synchronization service is successfully adjusting the system time;
A correct system time on the server is important for many scenarios:
– analysis of logs during troubleshooting (incorrect time zone increases the confusion even
more);
– caching of application resources in the client-side web browser because it is based on
resource timestamps reported by server;
– validation of SSL certificates in the MedDream backend when it securely connects to other
systems as a client;
– integration with Google Cloud Healthcare might fail if time difference is more than one hour;
– if the JWT security layer for HIS integration is enabled, then it allows only 5-second difference
by default (see the setting authentication.his.allowedClockSkewSeconds).
Other software on the server might exhibit different effects if the time is off by a too large amount.
• number and nature of “ERROR” messages in MedDream logs;
Not every problem is worth an error message seen by the end user. Some errors are visible
only in the logs, and indicate suboptimal configuration, corrupt or non-compliant DICOM files, or
simply MedDream bugs.
• the /manage/health/md endpoint can be used to track concurrent connections and other licensing details
in real time. This is especially useful if the license has a limited number of connections. Example response:

{"status":"UP","components":{"licensing":{"status":"UP","details":{"cc":1}},
˓→"ping":{"status":"UP"}}}

10.2. Antivirus software

Excessive virus scanning may severely impact performance. There is no sense to scan the MedDream
preparation cache (com.softneta.preparation.cacheDir, or “cache” under tempDir by default) so this directory
tree should be excluded, especially when using the in-advance preparation and expecting a large amount of
data there.
You should also consider whitelisting the DICOM files themselves on the PACS. Even if some are routinely
uploaded over a custom Web interface, their on-demand scanning in a corresponding temporary directory (before
importing to the PACS) might be more adequate.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


139

10.3. Log files of the Java-based core

In the directory of the Java application, the file meddream.main.log will be created.
To control the overall logging level, adjust the following line in application.properties:

logging.level.root=DEBUG

Alternatives to “DEBUG” are INFO, ERROR etc. as per Log4j specification.


More specific setting, logging.level.com.softneta, refers only to internal MedDream logic and in some cases
might be insufficient even at the TRACE level. On the other hand, logging.level.root yields so much data
that it becomes impractical after a few minutes.
When investigating SQL queries in direct integrations, the following might be useful:

logging.level.org.hibernate=DEBUG
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
spring.jpa.show-sql=true

Lots of third-party information related to user authentication:

logging.level.org.springframework.security=DEBUG

Logic of the temporary files cleaner is spread among the following modules:

logging.level.com.softneta.meddream.service.temp.TempCleanerService=DEBUG
logging.level.com.softneta.meddream.util.PathUtils=DEBUG
logging.level.com.softneta.meddream.util.DirTreeRemover=DEBUG

Dicomweb and Orthanc plugins depend on the following third-party library that can display HTTP
request/response headers (but not POST data):

logging.level.sun.net.www.protocol.http=DEBUG

PACS integration plugins themselves (pick the relevant one):

logging.level.com.softneta.pacs.gateway.plugin.pacsone=DEBUG
logging.level.com.softneta.pacs.gateway.plugin.dcm4chee5=DEBUG
logging.level.com.softneta.pacs.gateway.plugin.dcm4chee2=TRACE
logging.level.com.softneta.pacs.gateway.plugin.clearcanvas=DEBUG
logging.level.com.softneta.pacs.gateway.plugin.conquest=TRACE
logging.level.com.softneta.pacs.gateway.plugin.orthancplugin=TRACE
logging.level.com.softneta.pacs.gateway.plugin.dicomweb=DEBUG
logging.level.com.softneta.pacs.gateway.plugin.qr=TRACE
logging.level.com.softneta.pacs.gateway.plugin.filesystem=DEBUG
logging.level.com.softneta.pacs.gateway.plugin.amazon.s3=DEBUG

The levels listed above correspond to the maximum level used by a particular plugin.
When troubleshooting cache behavior, it is sometimes needed to know what UIDs are hidden beyond
those random-looking subdirectories, like .../bb/b2/ef/eedc376fdb0d545d9344b67092ee2e78d2/meta. This
is revealed by

logging.level.com.softneta.meddream.util.HashedPath=TRACE

Unfortunately, there will be a lot of corresponding messages, as they appear multiple times even when loading
a single-image study.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


140

Under Windows, the MedDream.exe service wrapper duplicates the logged information into files
MedDream.err.log and MedDream.out.log. The latter is sometimes more informative than meddream.main.log,
and its size can be controlled separately. To adjust the size and number of files MedDream.out.*.log, add the
<log> element to MedDream.xml, then modify its sizeThreshold and keepFiles:

<log mode="roll-by-size">
<sizeThreshold>10240</sizeThreshold>
<keepFiles>10</keepFiles>
</log>
</service>

10.4. Video conversion

When a video file is being converted to MPEG4, then stdout and stderr of the FFmpeg process are
redirected to a troubleshooting file ${com.softneta.video.convertedDir}/<SOP Instance UID><storage
ID>.out; the converted video goes to a temporary file ${com.softneta.video.convertedDir}/<SOP Instance
UID><storage ID>.tmp.mp4. When FFmpeg finishes, the temporary file is renamed to the final version, ${com.
softneta.video.convertedDir}/<SOP Instance UID><storage ID>.mp4. By default convertedDir points to a
subdirectory “temp/converted-videos”.
The conversion has no formal time limit. But, while the temporary file still exists, its modification time should
always be recent (which is the case if FFmpeg still writes to it). If the time doesn’t change for more than 120
seconds, then MedDream assumes FFmpeg is likely stuck or its wrapper script has crashed, and attempts to
remove all related files (.out, .tmp.mp4, .mp4).
On success the troubleshooting file is removed, and the final file is moved to the preparation cache for later use.
On failure both files remain for analysis. An empty final file is considered a failure, too.
Since 8.2.0 subsequent retries are not possible (the converter doesn’t even start) while the final file
(*.mp4) still exists. You must remove it manually in order to try again. The suggested configuration of Temporary
files cleaner removes any files under convertedDir older than one hour, every 30 minutes.

10.5. Client side: browser download path selection

10.5.1. Google Chrome

You can choose a location on your computer where downloads should be saved by default or pick a specific
destination for each download.
• On your computer, open Chrome.
• At the top right, click More and then Settings.
• At the bottom, click Advanced.
• Under the “Downloads” section, adjust your download settings:
• To change the default download location, click Change and select where you’d like your files to be saved.
• If you’d rather choose a specific location for each download, check the box next to “Ask where to save each
file before downloading”.
If you didn’t change your default download location, then Google Chrome downloads files to the following
locations:
• Windows 10, 8, 7 and Vista: \Users\<username>\Downloads
• Mac: /Users/<username>/Downloads
• Linux: /home/<username>/Downloads

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


141

10.5.2. Mozilla Firefox

Note: Changing the location of your downloads affects all downloaded files in this Web browser.

• Click the menu icon on the top right corner of the browser.
• Click Preferences.
• Click General.
• Click Choose. . . next to Save files to.

10.5.3. Microsoft Edge

• Open Microsoft Edge.


• Select Settings and more -> Settings.
• Under Downloads, select Change.
• In the dialog box, select a new location for your downloaded files.

10.5.4. Safari

To change the default download location of your Safari browser:


• Click on the “Edit Menu” -> Preferences -> General tab
• Locate the “Save downloaded files to” section, Click on “Downloads” > “Other”. . .
• Browse and indicate your new download location.

10.6. Client side: enabling clipboard operations

The buttons “Copy the image to the clipboard” and “Copy measurements to the clipboard” become hidden if the
conditions below are not met:
1. the connection must be HTTPS or to a “localhost” address (when MedDream is opened on the server
itself). This is a limitation in all Web browsers;
2. Firefox also requires dom.events.asyncClipboard.clipboardItem with value “true” in about:config. This
setting must be created or adjusted on every client machine;
3. when MedDream is integrated into another website via an IFRAME, then the latter must have the
allow="clipboard-read; clipboard-write" attribute. This, however, is a server side change.

10.7. Client side: monitor calibration

Note: Proper display of color images usually requires the “sRGB” color profile set up in the browser. For
Chrome, this can be changed at the chrome://flags/#force-color-profile page.

If you suspect that the monitor does not show small differences in brightness, especially at the dark or at the
bright end of the entire range, then the first step is to confirm the problem using third-party resources:
• https://www.photofriday.com/info/calibrate
• http://www.lagom.nl/lcd-test/

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


142

Afterwards you may attempt to calibrate the monitor.


• Windows: https://support.microsoft.com/en-us/windows/calibrate-your-built-in-display-for-hdr-content-in-
windows-de1c66fa-6cc0-b327-e73a-1bac6bd46bc0
• Linux: https://help.ubuntu.com/stable/ubuntu-help/color-calibrate-screen.html.en
• MacOS: https://support.apple.com/en-us/HT212851

10.8. Symptom: on Linux the loading pauses just after logging in,
possibly with wrong webpage colors

On some Linux installations, the Java backend might pause for up to several minutes when a new concurrent
connection is made. Immediately after the login, the user sees either an empty dark page with a progress bar
spinning at the top, or an empty white page, or a white page with a black-and-white DEMO message.
The cause: the default configuration of OpenJDK suggests reading from /dev/random that can block due to
exhausted entropy pool. Some systems are refilling the pool more slowly so this problem becomes more
common.
Solution 1: add -Djava.security.egd=file:///dev/./urandom to the command that starts the Java backend.
Refer to the 5.2 Running as a service chapter for hints where this command might be located.
It is recommended to stop the service, then start the updated command manually and verify the effect. You
might want to force entropy exhaustion so that the problem appears as soon as possible; use dd if=/dev/
random of=/dev/null bs=512 count=1 for that (on a different terminal as it will block, too).
Solution 2: the above might still not help with some OpenJDK builds, therefore you’ll need to update system-
wide configuration in the java.security file (traditionally it’s $JAVA_PATH/jre/lib/security/java.security):

securerandom.source=file:///dev/./urandom

10.9. Symptom: queries to MS SQL Server take seconds from Java but
milliseconds from Management Studio

A very poor performance was observed in a particular installation of Conquest over ODBC,
even for simple queries by object UID. Adding sendStringParametersAsUnicode=false; to
com.softneta.meddream.pacs.configurations[].url fixed that.
The default true means that all query parameters are sent to server as NVARCHAR, even for columns of
VARCHAR type. The type conversion results in a full table scan so performance with large tables drops down.
If correct representation of non-Latin characters is important, then you should leave true and the database
schema should use NVARCHAR in all MedDream query key columns (including UIDs). When national characters
are not used, then false is a more simple solution.

10.10. Symptom: video not playable on Firefox under Windows

Some DICOM MPEG4 videos play on recent Chrome and Edge browsers but not on Firefox under Windows.
The “loading” animation (spinning dots in a circle) is displayed forever, the browser’s console contains “Decoder
may not have the capability to handle the requested video format with YUV444 chroma subsampling”. Older
Firefox versions tell that the file is corrupt.
Unfortunately, Firefox team claims that under Windows support is not possible due to legal limitations. This video
format might provide a higher image quality.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


143

If too many end users of yours can’t use another browser, then you should force a format downgrade by adding
-pix_fmt yuv420p to FFmpeg command line. Afterwards all browsers will encounter the more popular 4:2:0
chroma format, and there will no benefit for those that support 4:4:4.
Example for software encoder (default command line) with this additional parameter:

com.softneta.video.commandLineTemplate =-i {INPUT} -y -vcodec libx264 -preset medium \


-pix_fmt yuv420p -movflags faststart {OUTPUT}

Example for Nvidia hardware encoder with this additional parameter:

com.softneta.video.commandLineTemplate = -hwaccel cuda -i {INPUT} -y -vcodec h264_nvenc \


-preset slow -pix_fmt yuv420p -movflags faststart {OUTPUT}

10.11. Known limitations and their solutions

10.11.1. Share functionality skips some objects

By design, Share to DICOM Library does not send the following objects in “Active study” mode:
• those that are hidden due to blackListedSopClasses in system.json, and due to another hardcoded list of
known unsupported SOP Classes;
• old versions of Bounding Box, Free Draw and Smart Paint annotations.
If they are important, then one should use the Export function and upload the resulting archive to DICOM Library
manually.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


144

A. Appendix: Configuration changes since 8.3.0

Note: Names marked with # (for example, “#datasource.quartz”) are internal properties, not to be changed by
the end user. Most of them are also not offered in application.SAMPLE.properties to discourage any changes.

A.1. application.properties, generic

A.1.1. Options that are handled differently

security.meddreamProxyIp
Also supports a hostname, which will be resolved to an IP address.

A.1.2. New options or values

authorization.remapRoles.*
Now supported in case of auth-pacsone.
Names of PacsOne groups to which the user belongs are fetched from the database, and can used in
parameters “authorization.remapRoles.GROUP_NAME” to add some more MedDream permissions.
However group’s own privileges assigned in PacsOne GUI are ignored.
com.softneta.preparation.additionalMetadataTags
List of custom tags cached for the “metadata” endpoint which is used by the “V2” implementation
(experimental) of hanging protocols.
com.softneta.dicomParser.additionalPrivateTags
List of private tags that won’t be ignored during parsing. Might be needed for additionalMetadataTags
to function properly.
com.softneta.preparation.skipStructurePreparation
Disables queries to the PACS during preparation if studyStructureSec > 0 ir pgwStudyResponseSec
> 0.
com.softneta.meddream.dcmsnd.annotationsFromOrigAet
When sending annotations to the PACS, in some cases MedDream can use the original AE Title
already associated with the study. (Tested only with PacsOne plugin; will definitely not work with
DCM4CHEE2 plugin.)
security.detectRemoteIpChange
It is possible to detect the change of client’s IP address and log a warning or invalidate the session.
com.softneta.study.lowerPrioritySeriesModalities
Reordering of study structure: series with modalities listed here will be moved to the end.
The effect is similar to sCSeriesLowerPriority setting of Dicomweb plugin, however might be more
effective/flexible and works for all plugins.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


145

A.2. application.properties, PacsOne plugin 6.4.0

A.2.1. New options or values

eventApiEnabled
Controls “Clean cache” at the plugin side when caching is enabled for PacsOne installations that
store studies on AWS S3.
dicomCacheDirectory
In this directory the plugin will cache DICOM files downloaded from AWS S3 so that subsequent
accessses are faster and do not contribute to the traffic cost.
awsS3Marker
A magic value used to detect that PacsOne has stored the DICOM file on S3 instead of a local disk.
Likely hardcoded in PacsOne.
awsS3Separator
The character that separates awsS3Marker from the remaining path. Likely hardcoded in PacsOne.
awsS3ConnectionInfoCacheTimeInSec
AWS S3 bucket and region identifiers extracted from the database will be reused for this many
seconds.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


146

B. Appendix: Upgrading 8.3.0 to 8.3.1 (Linux)


1. Stop the Core service (and the Token Service if it is used). The method depends on how you are running
it, see 5.2 Running as a service.
2. Back up the old MedDream folder:

mv /opt/meddream /opt/meddreamBKP

3. Extract new MedDream version to /opt/meddream/ so that the file /opt/meddream/MedDream-8.3.1.jar


exists.
4. Copy the following old files to the new version:
• meddream.lic
• sys/settings/*.json
• sys/settings/robots.txt
5. Review JVM parameters in your service wrapper script (5.2 Running as a service). For instance, the
example System-V scripts bundled with MedDream won’t contain changes made by you, and an example
might still need renaming to the final file.
6. If application.SAMPLE.properties was used during the initial installation, then copy the new file to
application.properties and for every setting, copy the value from old application.properties.
(During every upgrade, it is advised to keep the original application.SAMPLE.properties: later it
can be compared with the new version and therefore save some time.)
If the old file does not contain the same setting, then consult Appendix: Configuration changes
since 8.3.0 or the entire list 5.1.9 Reference for remaining configuration parameters. Probably it
has been renamed, or is totally new.

Warning: You might be tempted to simply copy the old application.properties to the new
version and then review it. This is not recommended:
• A higher risk of keeping settings not supported any more, which might lead to confusion
later.
• No opportunity to encounter default values (or totally new settings) in
application.SAMPLE.properties that are safer security-wise, especially if overlooked.
• No opportunity to encounter comments/explanations that might be more comprehensive
in newer versions of application.SAMPLE.properties.

7. If, however, your application.properties is made from scratch instead, then consult Appendix: Configuration
changes since 8.3.0 or even the entire list 5.1.9 Reference for remaining configuration parameters.
8. If rebranding is used, then for every setting in the new sys/settings/rebranding/rebranding_configuration.json,
copy the value from a setting in the old version.
If the old file does not contain the same setting, then consult Rebranding. It might be renamed
or totally new.
Afterwards copy all referenced image files from the old sys/settings/rebranding directory to the
new one.
9. Update file permissions (example below is for MedDream running as user “meddream”):

chown -R meddream:meddream /opt/meddream


find /opt/meddream/ -type d -exec chmod 775 {} \;
(continues on next page)

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


147

(continued from previous page)


find /opt/meddream/ -type f -exec chmod 664 {} \;
chmod +x /opt/meddream/sys/ffmpeg/flv.sh

DO NOT RUN MedDream AS ROOT.


10. Start the JAR so that sys/settings/system.json is created automatically. For every setting, copy the value
from the old system.json. Consult the documentation (5.1.2 System.json) and list of configuration changes
(Appendix: Configuration changes since 8.3.0).

Warning: Unmodified system.json from older versions might be incompatible and result in a
crash when starting the JAR.
If you went the non-recommended way and are upgrading in-place, then old files
sys/database/*.mv.db might prevent the JAR from starting, too. In case of errors related to
H2 database engine, these files must be moved elsewhere so that new ones can be created.

11. Open the Settings window, review/adjust the configuration and save it. Without
toolbarButtonsOrderingEnabled = false, the ordering of toolbar buttons and actions might differ from
the saved one, and this new order will be forced until settings are manually reordered and saved by the
new version.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


148

C. Appendix: Upgrading 8.3.0 to 8.3.1 (Windows)


1. Stop the Core service (and the Token Service if it is used).
2. Back up the old MedDream folder: rename/move C:\MDPACS\MedDream to C:\MDPACS\MedDreamOLD.
3. Make sure Java 17 is available on the system, and the command java -version indicates version 17.
Even better is to always upgrade Java (17.x) when upgrading MedDream.
4. Extract new MedDream version to C:\MDPACS\MedDream so that the file
C:\MDPACS\MedDream\MedDream-8.3.1.jar exists.
5. Copy C:\MDPACS\MedDream\MedDream.NET?.exe (depending on .NET version) to
C:\MDPACS\MedDream\MedDream.exe.
6. Copy the following old MedDream files to the new version:
• meddream.lic
• sys\settings\*.json
• sys\settings\robots.txt
7. Apply to MedDream.xml any changes made in the old file.
8. If application.SAMPLE.properties was used during the initial installation, then copy the new file to
application.properties and for every setting, copy the value from old application.properties.
(During every upgrade, it is advised to keep the original application.SAMPLE.properties: later it
can be compared with the new version and therefore save some time.)
If the old file does not contain the same setting, then consult Appendix: Configuration changes
since 8.3.0 or the entire list 5.1.9 Reference for remaining configuration parameters. Probably it
has been renamed, or is totally new.

Warning: You might be tempted to simply copy the old application.properties to the new
version and then review it. This is not recommended:
• A higher risk of keeping settings not supported any more, which might lead to confusion
later.
• No opportunity to encounter default values (or totally new settings) in
application.SAMPLE.properties that are safer security-wise, especially if overlooked.
• No opportunity to encounter comments/explanations that might be more comprehensive
in newer versions of application.SAMPLE.properties.

9. If, however, your application.properties is made from scratch instead, then consult Appendix: Configuration
changes since 8.3.0 or even the entire list 5.1.9 Reference for remaining configuration parameters.
10. If rebranding is used, then for every setting in the new sys\settings\rebranding\rebranding_configuration.json,
copy the value from the old version.
If the old file does not contain the same setting, then consult Rebranding. It might be renamed
or totally new.
Afterwards copy all referenced image files from the old sys\settings\rebranding folder to the new
one.
11. If MedDream is running under some dedicated user, reapply the “Modify” permission for this user on
C:\MDPACS\MedDream and all its contents.
12. Start the JAR so that sys\settings\system.json is created automatically. For every setting, copy the value
from the old system.json. Consult the documentation (5.1.2 System.json) and list of configuration changes
(Appendix: Configuration changes since 8.3.0).

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)


149

Warning: Unmodified system.json from older versions might be incompatible and result in a
crash when starting the JAR.
If you went the non-recommended way and are upgrading in-place, then old files
sys\database\*.mv.db might prevent the JAR from starting, too. In case of errors related to
H2 database engine, these files must be moved elsewhere so that new ones can be created.

13. Open the Settings window, review/adjust the configuration and save it. Without
toolbarButtonsOrderingEnabled = false, the ordering of toolbar buttons and actions might differ from
the saved one, and this new order will be forced until settings are manually reordered and saved by the
new version.

MedDream 8.3.1 Install manual of Viewing functionalities (document version 1.0)

You might also like