Reading Header Information

django_dicom uses the dicom_parser package to read header information and store it as an Header instance. Some information is already available to us directly through the values stored in the associated Image, Series, Patient, and Study instances. However, Header instances are collections of DataElement instances, each storing a queryable reference to both the raw and parsed values of a given data element.

By defualt, django_dicom will store all official DICOM tags, skipping any private data elements. These will still be easily readable, however, we will not be able to query them from the database. For more information about import modes, see Import Modes.

Reading a Single Image’s Header

To read a single Image instance’s header, we can simply use the instance property to retrieve dicom_parser’s representation of a DICOM image ( Image):

>>> from django_dicom.models import Image

>>> image = Image.objects.first()
>>> image.instance.header
            Keyword                      VR                VM  Value
Tag
(0008, 0005)  SpecificCharacterSet         Code String       1   ISO_IR 100
(0008, 0008)  ImageType                    Code String       5   ['ORIGINAL', 'PRIMARY', ...
(0008, 0012)  InstanceCreationDate         Date              1   2019-12-18
(0008, 0013)  InstanceCreationTime         Time              1   08:54:41.479000
(0008, 0016)  SOPClassUID                  Unique Identifer  1   1.2.840.10008.5.1.4.1.1.4
(0008, 0018)  SOPInstanceUID               Unique Identifer  1   1.3.12.2.1107.5.2.43.660...
(0008, 0020)  StudyDate                    Date              1   2019-12-18
...
Private Data Elements
=====================
            Keyword                      VR           VM  Value
Tag
(0019, 0010)                               Long String  1   SIEMENS MR HEADER
(0019, 1008)  CsaImageHeaderType           Unknown      1   b'IMAGE NUM 4 '
(0019, 1009)  CsaImageHeaderVersion??      Unknown      1   b'1.0 '
(0019, 100b)  SliceMeasurementDuration     Unknown      1                          3535
...

>>> image.instance.header.get('PixelSpacing')
[0.48828125, 0.48828125]

For more information on dicom_parser’s classes and functionality, see the documentation.

Querying the Database

According to the chosen import mode, no, some, or all of the saved images’ data elements will be serialized to the database as DataElement instances. Each DataElement represents a single tag within a single header, however, the actual information is available its definition and value attributes. These attributes associate the DataElement instance with reusable DataElementDefinition and DataElementValue instances, thereby preventing data duplication simplifying queries.

To better understand the way header information is serialized in the database, let’s query all the Series instances in which the underlying image headers contain a data element named ImageType which contains a value of MOSAIC.

First, we’ll have a look at the relevant DataElementDefinition instance:

>>> from django_dicom.models import DataElementDefinition
>>> definition = DataElementDefinition.objects.get(keyword="ImageType")
>>> definition
<DataElementDefinition:
Tag                     (0008, 0008)
Keyword                    ImageType
Value Representation              CS
Description               Image Type>

Now, let’s select any DataElementValue instances satisfying our condition:

>>> from django_dicom.models import CodeString
>>> values = CodeString.objects.filter(value="MOSAIC")
>>> values.count()
9

This means there are 9 different distinct ImageType values that contain the string MOSAIC. If we want all the related DataElement instances, we could:

>>> from django_dicom.models import DataElement
>>> data_elements = DataElement.objects.filter(definition=definition, _values__in=values)
>>> data_elements.count()
42236

Two important things to note here:

  • We used the _values attribute to access the raw relationship between the DataElement and its associated DataElementValues.
  • We used __in to query this ManyToMany relationship and retrieve data elements containing any of the desired values. This is necessary because DICOM elements may have multiple values (for more information see value multiplicity).

Now, if we would like to query all the images to which these data elements belong:

>>> image_ids = data_elements.values_list('header__image', flat=True)
>>> images = Image.objects.filter(id__in=image_ids)

or the series:

>>> from django_dicom.models import Series
>>> series_ids = images.values_list('series', flat=True)
>>> series = Series.objects.filter(id__in=series_ids)
>>> series.count()
409
>>> series.first().description
'IR-DTI_30dir_3iso'