# DICOM (Digital Imaging and Communications in Medicine)

Refer to the [Slicer User Guide DICOM Section](../../user_guide/modules/dicom.md) for a comprehensive overview of the DICOM standard and related features in Slicer.

The overall DICOM Implementation in 3D Slicer consists of two main bodies of code embedded within the application.
- [CTK](https://commontk.org) code is responsible for the implementation of the DICOM database and DIMSE networking layer. The CTK code is implemented in C++ and follows the Qt style.
- The DICOM Module exposes CTK functionality to Slicer users, and provides hooks through which other modules can register DICOM Plugins to handle the conversion of specific DICOM data objects into the corresponding MRML representation.  Once the data is in slicer, it can be operated on via the standard Slicer mechanisms.

Additional tools are available for Slicer Python scripted module development:
- [DICOM Toolkit (DCMTK)](https://www.dcmtk.org/en/) command line application tools are installed with 3D Slicer and can be called synchronously within a Slicer scripted module.
- The [DICOMweb Client (`dicomweb-client`)](https://github.com/ImagingDataCommons/dicomweb-client) Python module is available within 3D Slicer for DICOMweb networking.
- Various Slicer-specific implementations for DICOM management and network are provided in the [DICOMLib scripted module](https://github.com/Slicer/Slicer/tree/main/Modules/Scripted/DICOMLib).

## Customize table columns in DICOM browser

Columns in the browser can be renamed, reordered, shown/hidden, etc. An example snippet to customize the browser can be found in the [script repository](../script_repository.md#customize-table-columns-in-dicom-browser).

The changes made like this are written into the database (ColumnDisplayProperties table), so the column customizations can be done only once per database.

## Customize DICOM browser table content

The way the raw DICOM tags are represented in the fields of the DICOM tables is determined by the displayed field generator rules. These rules are subclasses of the [ctkDICOMDisplayedFieldGeneratorAbstractRule class](https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h), and need to be [registered](https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.h#L70) to the displayed field generator in order to take part of the generation.

The fields are [updated](https://github.com/commontk/CTK/9c2af28e84da1abb986036317d75009d4c149923/blob/Libs/DICOM/Core/ctkDICOMDatabase.h#L207) when 1) files are added to the database or 2) the database schema is updated (happens when opening an older database with a newer Slicer). In the [current](https://github.com/commontk/CTK/tree/9c2af28e84da1abb986036317d75009d4c149923) version only those files (i.e. instances) are processed for which the displayed fields have never been generated.

When updating the displayed fields, every rule defines the fields it is responsible for using the cached DICOM tags in the database. Tags can be requested to be cached in the rules from the [getRequiredDICOMTags](https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h#L63) function. New field values are generated by the rules instance by instance. First, the getDisplayedFieldsForInstance function is called for each rule in which the custom values are generated from the raw tags, then the results are merged by calling mergeDisplayedFieldsForInstance for all the rules. Each field can be requested to be merged with "expect same value", which uses the only non-empty value and throws a warning if conflicting values are encountered, or with "concatenate", which simply concatenates the displayed field values together.

The existing two rules can be used as examples: the [default](https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.cpp) and the [RT](https://github.com/commontk/CTK/blob/9c2af28e84da1abb986036317d75009d4c149923/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.cpp) rules.

## Plugin architecture

There are many different kind of DICOM information objects and import/export of all of them would not be feasible to implement in the Slicer core (see more information in the [DICOM module user manual](../../user_guide/modules/dicom.md#dicom-plugins)). Therefore, extensions can implement custom importer/exporter classes based on DICOMLib.DICOMPlugin class and add them to slicer.modules.dicomPlugins dictionary object. The DICOM module uses these plugins to determine list of loadable and exportable items.

## DICOM Networking Development

3D Slicer leverages CTK, DCMTK, and `dicomweb-client` to provide DICOM networking capabilities. Medical DICOM images stored on a remote Picture and Archiving Communication Systems (PACS) can be queried, fetched to Slicer, annotated, and then stored back to the PACS.

We suggest that Slicer developers dealing with DICOM networking explore local test environment options to fit their needs.
- DCMTK provides tools for testing DIMSE networking. You can use DCMTK's `storescp.exe` tool distributed with 3D Slicer to test asynchronous store requests with DIMSE.

Run the following command from a shell prompt:
```
> "path/to/Slicer x.y.z\bin\storescp.exe" <port-number>
```
Then in Slicer, send DICOM data to the server at `localhost:<port-number`.

- Several open source PACS platforms can be installed locally to support DICOMweb testing in an isolated environment, including:
  - [Orthanc](https://www.orthanc-server.com/index.php)
  - [DCM4CHE](https://www.dcm4che.org/)


## References

See the [CTK web site](https://commontk.org) for more information on the internals of the DICOM implementation. This tool uses the [DCMTK DICOM library](https://dicom.offis.de).

## Examples

Examples for common DICOM operations are provided in the [script repository](../script_repository.md#dicom).
