
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "auto_examples/input_output/plot_read_fileset.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        Click :ref:`here <sphx_glr_download_auto_examples_input_output_plot_read_fileset.py>`
        to download the full example code

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_auto_examples_input_output_plot_read_fileset.py:


=====================
Read a DICOM File-set
=====================

This example shows how to read and interact with a DICOM File-set.

.. GENERATED FROM PYTHON SOURCE LINES 9-124




.. rst-class:: sphx-glr-script-out

 Out:

 .. code-block:: none

    DICOM File-set
      Root directory: /build/pydicom-sEi8Lz/pydicom-2.4.3/pydicom/data/test_files/dicomdirtests
      File-set ID: PYDICOM_TEST
      File-set UID: 1.2.276.0.7230010.3.1.4.0.31906.1359940846.78187
      Descriptor file ID: (no value available)
      Descriptor file character set: (no value available)
      Changes staged for write(): DICOMDIR update, directory structure update

      Managed instances:
        PATIENT: PatientID='77654033', PatientName='Doe^Archibald'
          STUDY: StudyDate=20010101, StudyTime=000000, StudyDescription='XR C Spine Comp Min 4 Views'
            SERIES: Modality=CR, SeriesNumber=1
              IMAGE: 1 SOP Instance
            SERIES: Modality=CR, SeriesNumber=2
              IMAGE: 1 SOP Instance
            SERIES: Modality=CR, SeriesNumber=3
              IMAGE: 1 SOP Instance
          STUDY: StudyDate=19950903, StudyTime=173032, StudyDescription='CT, HEAD/BRAIN WO CONTRAST'
            SERIES: Modality=CT, SeriesNumber=2
              IMAGE: 4 SOP Instances
        PATIENT: PatientID='98890234', PatientName='Doe^Peter'
          STUDY: StudyDate=20010101, StudyTime=000000
            SERIES: Modality=CT, SeriesNumber=4
              IMAGE: 2 SOP Instances
            SERIES: Modality=CT, SeriesNumber=5
              IMAGE: 5 SOP Instances
          STUDY: StudyDate=20030505, StudyTime=050743, StudyDescription='Carotids'
            SERIES: Modality=MR, SeriesNumber=1
              IMAGE: 1 SOP Instance
            SERIES: Modality=MR, SeriesNumber=2
              IMAGE: 1 SOP Instance
          STUDY: StudyDate=20030505, StudyTime=025109, StudyDescription='Brain'
            SERIES: Modality=MR, SeriesNumber=1
              IMAGE: 1 SOP Instance
            SERIES: Modality=MR, SeriesNumber=2
              IMAGE: 3 SOP Instances
          STUDY: StudyDate=20030505, StudyTime=045357, StudyDescription='Brain-MRA'
            SERIES: Modality=MR, SeriesNumber=1
              IMAGE: 1 SOP Instance
            SERIES: Modality=MR, SeriesNumber=2
              IMAGE: 3 SOP Instances
            SERIES: Modality=MR, SeriesNumber=700
              IMAGE: 7 SOP Instances

    PatientName=Doe^Archibald, PatientID=77654033
      StudyDescription='XR C Spine Comp Min 4 Views', StudyDate=20010101
        Modality=CR - 1 SOP Instance
        Modality=CR - 1 SOP Instance
        Modality=CR - 1 SOP Instance
      StudyDescription='CT, HEAD/BRAIN WO CONTRAST', StudyDate=19950903
        Modality=CT - 4 SOP Instances
    PatientName=Doe^Peter, PatientID=98890234
      StudyDescription='', StudyDate=20010101
        Modality=CT - 2 SOP Instances
        Modality=CT - 5 SOP Instances
      StudyDescription='Carotids', StudyDate=20030505
        Modality=MR - 1 SOP Instance
        Modality=MR - 1 SOP Instance
      StudyDescription='Brain', StudyDate=20030505
        Modality=MR - 1 SOP Instance
        Modality=MR - 3 SOP Instances
      StudyDescription='Brain-MRA', StudyDate=20030505
        Modality=MR - 1 SOP Instance
        Modality=MR - 3 SOP Instances
        Modality=MR - 7 SOP Instances

    Found 7 instances for SeriesInstanceUID=1.3.6.1.4.1.5962.1.1.0.0.0.1196533885.18148.0.118
    Found 0 instances with PhotometricInterpretation='MONOCHROME1' without loading the stored instances and 3 instances with loading

    Original File-set still at /build/pydicom-sEi8Lz/pydicom-2.4.3/pydicom/data/test_files/dicomdirtests
    File-set copied to /tmp/tmpnwjmmrfz and contains the following files:
      DICOMDIR
      PT000000/ST000000/SE000000/IM000000
      PT000000/ST000000/SE000001/IM000000
      PT000000/ST000000/SE000002/IM000000
      PT000000/ST000001/SE000000/IM000000
      PT000000/ST000001/SE000000/IM000001
      PT000000/ST000001/SE000000/IM000002
      PT000000/ST000001/SE000000/IM000003
      PT000001/ST000000/SE000000/IM000000
      PT000001/ST000000/SE000000/IM000001
      PT000001/ST000000/SE000001/IM000000
      PT000001/ST000000/SE000001/IM000001
      PT000001/ST000000/SE000001/IM000002
      PT000001/ST000000/SE000001/IM000003
      PT000001/ST000000/SE000001/IM000004
      PT000001/ST000001/SE000000/IM000000
      PT000001/ST000001/SE000001/IM000000
      PT000001/ST000002/SE000000/IM000000
      PT000001/ST000002/SE000001/IM000000
      PT000001/ST000002/SE000001/IM000001
      PT000001/ST000002/SE000001/IM000002
      PT000001/ST000003/SE000000/IM000000
      PT000001/ST000003/SE000001/IM000000
      PT000001/ST000003/SE000001/IM000001
      PT000001/ST000003/SE000001/IM000002
      PT000001/ST000003/SE000002/IM000000
      PT000001/ST000003/SE000002/IM000001
      PT000001/ST000003/SE000002/IM000002
      PT000001/ST000003/SE000002/IM000003
      PT000001/ST000003/SE000002/IM000004
      PT000001/ST000003/SE000002/IM000005
      PT000001/ST000003/SE000002/IM000006
      PT000002/ST000000/SE000000/IM000000
      PT000003/ST000000/SE000000/IM000000






|

.. code-block:: default


    from pathlib import Path
    from tempfile import TemporaryDirectory
    import warnings

    from pydicom import dcmread
    from pydicom.data import get_testdata_file
    from pydicom.fileset import FileSet
    from pydicom.uid import generate_uid

    warnings.filterwarnings("ignore")

    path = get_testdata_file('DICOMDIR')
    # A File-set can be loaded from the path to its DICOMDIR dataset or the
    #   dataset itself
    fs = FileSet(path)  # or fs = FileSet(dcmread(path))

    # A summary of the File-set's contents can be seen when printing
    print(fs)
    print()

    # Iterating over the FileSet yields FileInstance objects
    for instance in fs:
        # Load the corresponding SOP Instance dataset
        ds = instance.load()
        # Do something with each dataset

    # We can search the File-set
    patient_ids = fs.find_values("PatientID")
    for patient_id in patient_ids:
        # Returns a list of FileInstance, where each one represents an available
        #   SOP Instance with a matching *Patient ID*
        result = fs.find(PatientID=patient_id)
        print(
            f"PatientName={result[0].PatientName}, "
            f"PatientID={result[0].PatientID}"
        )

        # Search available studies
        study_uids = fs.find_values("StudyInstanceUID", instances=result)
        for study_uid in study_uids:
            result = fs.find(PatientID=patient_id, StudyInstanceUID=study_uid)
            print(
                f"  StudyDescription='{result[0].StudyDescription}', "
                f"StudyDate={result[0].StudyDate}"
            )

            # Search available series
            series_uids = fs.find_values("SeriesInstanceUID", instances=result)
            for series_uid in series_uids:
                result = fs.find(
                    PatientID=patient_id,
                    StudyInstanceUID=study_uid,
                    SeriesInstanceUID=series_uid
                )
                plural = ['', 's'][len(result) > 1]

                print(
                    f"    Modality={result[0].Modality} - "
                    f"{len(result)} SOP Instance{plural}"
                )

    # Of course you can just get the instances directly if you know what you want
    series_uid = "1.3.6.1.4.1.5962.1.1.0.0.0.1196533885.18148.0.118"
    result = fs.find(SeriesInstanceUID=series_uid)
    print(f"\nFound {len(result)} instances for SeriesInstanceUID={series_uid}")

    # We can search the actual stored SOP Instances by using `load=True`
    # This can be useful as the DICOMDIR's directory records only contain a
    #   limited subset of the available elements, however its less efficient
    result = fs.find(load=False, PhotometricInterpretation="MONOCHROME1")
    result_load = fs.find(load=True, PhotometricInterpretation="MONOCHROME1")
    print(
        f"Found {len(result)} instances with "
        f"PhotometricInterpretation='MONOCHROME1' without loading the stored "
        f"instances and {len(result_load)} instances with loading"
    )

    # We can remove and add instances to the File-set
    fs.add(get_testdata_file("CT_small.dcm"))
    fs.add(get_testdata_file("MR_small.dcm"))
    result = fs.find(StudyDescription="'XR C Spine Comp Min 4 Views'")
    fs.remove(result)

    # To edit the elements in the DICOMDIR's File-set Identification Module
    #   (Part 3, Annex F.3.2.1) use the following properties:
    # (0004,1130) File-set ID
    fs.ID = "MY FILESET"
    # Change the File-set's UID
    fs.UID = generate_uid()
    # (0004,1141) File-set Descriptor File ID
    fs.descriptor_file_id = "README"
    # (0004,1142) Specific Character Set of File-set Descriptor File
    fs.descriptor_character_set = "ISO_IR 100"

    # Changes to the File-set are staged until write() is called
    # Calling write() will update the File-set's directory structure to meet the
    #   semantics used by pydicom File-sets (if required), add/remove instances and
    #   and re-write the DICOMDIR file
    # We don't do it here because it would overwrite your example data
    # fs.write()

    # Alternatively, the File-set can be copied to a new root directory
    #   This will apply any staged changes while leaving the original FileSet
    #   object unchanged
    tdir = TemporaryDirectory()
    new_fileset = fs.copy(tdir.name)
    print(f"\nOriginal File-set still at {fs.path}")
    root = Path(new_fileset.path)
    print(f"File-set copied to {root} and contains the following files:")
    # Note how the original File-set directory layout has been changed to
    #   the structure used by pydicom
    for p in sorted(root.glob('**/*')):
        if p.is_file():
            print(f"  {p.relative_to(root)}")


.. rst-class:: sphx-glr-timing

   **Total running time of the script:** ( 0 minutes  0.193 seconds)


.. _sphx_glr_download_auto_examples_input_output_plot_read_fileset.py:


.. only :: html

 .. container:: sphx-glr-footer
    :class: sphx-glr-footer-example



  .. container:: sphx-glr-download sphx-glr-download-python

     :download:`Download Python source code: plot_read_fileset.py <plot_read_fileset.py>`



  .. container:: sphx-glr-download sphx-glr-download-jupyter

     :download:`Download Jupyter notebook: plot_read_fileset.ipynb <plot_read_fileset.ipynb>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
