SkillAgentSearch skills...

Pylinac

An image analysis library for medical physics

Install / Use

/learn @jrkerns/Pylinac
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

.. image:: https://storage.googleapis.com/pylinac_demo_files/Pylinac-GREEN.png :width: 100% :target: https://github.com/jrkerns/pylinac :align: center

.. image:: https://img.shields.io/pypi/v/pylinac?logo=pypi :target: https://pypi.python.org/pypi/pylinac :alt: Latest Version

.. image:: https://img.shields.io/pypi/pyversions/pylinac?logo=python :alt: PyPI - Python Version

.. image:: https://img.shields.io/pypi/wheel/pylinac :alt: PyPI - Wheel

.. image:: https://img.shields.io/github/license/jrkerns/pylinac :target: https://choosealicense.com/licenses/mit/ :alt: MIT

.. image:: https://img.shields.io/readthedocs/pylinac/latest?logo=readthedocs :target: https://pylinac.readthedocs.io/en/latest/ :alt: Read the Docs (version)

.. image:: https://img.shields.io/pypi/dm/pylinac :alt: PyPI - Downloads

.. image:: https://img.shields.io/github/commit-activity/m/jrkerns/pylinac :alt: GitHub commit activity (branch)

.. image:: https://img.shields.io/badge/JOSS-10.21105%2Fjoss.06001-brightgreen :alt: JOSS Paper :target: https://joss.theoj.org/papers/10.21105/joss.06001

.. contents:: :class: this-will-duplicate-information-and-it-is-still-useful-here

Introduction

Pylinac provides TG-142 quality assurance (QA) tools to Python programmers in the field of therapy and diagnostic medical physics.

Pylinac contains high-level modules for automatically analyzing images and data generated by linear accelerators, CT simulators, and other radiation oncology equipment. Most scripts can be utilized with less than 10 lines of code.

The library also contains lower-level modules & tools <http://pylinac.readthedocs.org/en/latest/core_modules.html>_ for creating your own image analysis algorithms.

The major attributes of the package are:

  • Simple, concise image analysis API
  • Automatic analysis of imaging and performance metrics like MTF, Contrast, ROIs, etc.
  • PDF report generation for solid documentation
  • Automatic phantom registration even if you don't set up your phantom perfect
  • Image loading from file, ZIP archives, or URLs

Installation

Install via pip:

.. code-block:: bash

$ pip install pylinac

See the Installation page <https://pylinac.readthedocs.io/en/latest/installation.html>_ for further details.

Citation

You may cite the pylinac library in publications; see the paper <https://joss.theoj.org/papers/10.21105/joss.06001>__ in the Journal of Open Source Software. The citation string is:

Kerns, J. R., (2023). Pylinac: Image analysis for routine quality assurance in radiotherapy. Journal of Open Source Software, 8(92), 6001, https://doi.org/10.21105/joss.06001

And the BibTeX entry:

.. code-block::

@article{Kerns2023, doi = {10.21105/joss.06001}, url = {https://doi.org/10.21105/joss.06001}, year = {2023}, publisher = {The Open Journal}, volume = {8}, number = {92}, pages = {6001}, author = {James R. Kerns}, title = {Pylinac: Image analysis for routine quality assurance in radiotherapy}, journal = {Journal of Open Source Software} }

I was also interviewed due to this article! Thanks to Arfon and Abby for the fun interview: YouTube <https://youtu.be/YoOc6MpmKK8?si=Cq5-RTXtApyv9N_n>__.

Documentation

To get started, install the package, run the demos, view the API docs, and learn the module design, visit the Full Documentation <http://pylinac.readthedocs.org/>_ on Read The Docs.

Features

Low-level Tooling


DICOM, XIM & Image Loading
##########################

Load DICOM files, XIM, and TIFF images:

.. code-block:: python

  from pylinac import image
  from pylinac.core.image import XIM

  my_dcm = image.load("path/to/my/image.dcm")
  my_dcm.metadata.GantryAngle  # the GantryAngle tag of the DICOM file
  # these won't have the metadata property as they aren't DICOM
  my_tiff = image.load("path/to/my/image.tiff")
  my_jpg = image.load("path/to/my/image.jpg")

  my_xim_file = r"C:\TDS\H12345\QA\image.xim"
  xim_img = XIM(my_xim_file)

  # plot the image
  xim_img.plot()

  # see the XIM properties
  print(xim_img.properties)


Read more about DICOM and pixel loading: `Image Loading <http://pylinac.readthedocs.org/en/latest/topics/images.html>`_.
Read more about XIM images: `XIM Images <http://pylinac.readthedocs.org/en/latest/topics/xim.html>`_.

Image Manipulation
##################

Images can be manipulated in a variety of ways. This is helpful when combined with the loading utilities above:

.. code-block:: python

      from pylinac import image

      # load an image
      my_img = image.load("path/to/my/image.dcm")

      # rotate the image
      my_img.rotate(90)

      # flip the image
      my_img.flipud()

      # crop the image
      my_img.crop(pixels=50, edges=("left", "top"))

      # invert the image
      my_img.bit_invert()

      # normalize the array (max value = 1)
      my_img.normalize()

      # plot the image
      my_img.plot()

      # save the image back out to DICOM
      my_img.save("path/to/new.dcm")

Convert TIFF to DICOM:

.. code-block:: python

    from pylinac import image

    # load the TIFF image
    new_dicom = image.tiff_to_dicom(
        "path/to/my/image.tiff", sid=1000, gantry=90, coll=0, couch=0, dpi=400
    )

    # save out the FILE to DICOM
    new_dicom.save("path/to/new.dcm")

Compute Gamma
#############

Compute gamma between two arrays:

.. code-block:: python

    from pylinac import image

    # load the images
    img1 = image.load("path/to/image1.dcm")
    img2 = image.load("path/to/image2.dcm")

    # compute gamma
    gamma = image.gamma_2d(
        reference=img1.array,
        evaluation=img2.array,
        dose_to_agreement=1,
        distance_to_agreement=1,
        gamma_cap_value=2,
        global_dose=True,
        dose_threshold=5,
    )

    # plot the gamma map
    plt.imshow(gamma)

Compute gamma for 1D profiles:

.. code-block:: python

    from pylinac import profile

    # load the images and profiles
    img1 = image.load("path/to/image1.dcm")
    img2 = image.load("path/to/image2.dcm")
    mid_img1_profile = img1.array[img1.shape[0] // 2, :]
    mid_img2_profile = img2.array[img2.shape[0] // 2, :]

    # compute gamma
    gamma = profile.gamma_1d(
        reference=mid_img1_profile,
        evaluation=mid_img2_profile,
        dose_to_agreement=1,
        distance_to_agreement=1,
        gamma_cap_value=2,
        global_dose=True,
        dose_threshold=5,
    )

    # plot the gamma map
    plt.plot(gamma)

Compute Custom Metrics on Profiles
##################################

Pylinac comes with several built-in metrics that can be computed on 1D profiles, each of which can be
configured.

`Writing new metrics <https://pylinac.readthedocs.io/en/latest/topics/profiles.html#writing-plugins>`__ is also easy.

* `Left Penumbra <https://pylinac.readthedocs.io/en/latest/topics/profiles.html#penumbra-left>`__ using ``LeftPenumbralMetric``
* `Right Penumbra <https://pylinac.readthedocs.io/en/latest/topics/profiles.html#penumbra-right>`__  using ``RightPenumbralMetric``
* `FFF "Top" <https://pylinac.readthedocs.io/en/latest/topics/profiles.html#top-position>`__ using ``TopPosition``
* `Flatness (Difference) <https://pylinac.readthedocs.io/en/latest/topics/profiles.html#flatness-difference>`__ using ``FlatnessDifferenceMetric``
* `Flatness (Ratio) <https://pylinac.readthedocs.io/en/latest/topics/profiles.html#flatness-ratio>`__ using ``FlatnessRatioMetric``
* `Symmetry (Point Difference) <https://pylinac.readthedocs.io/en/latest/topics/profiles.html#symmetry-point-difference>`__ using ``SymmetryPointDifferenceMetric``
* `Symmetry (Point Difference Quotient) <https://pylinac.readthedocs.io/en/latest/topics/profiles.html#symmetry-point-difference-quotient>`__ using ``SymmetryPointDifferenceQuotientMetric``

Calculate the penumbra of a profile using the built-in ``LeftPenumbraMetric``:

.. code-block:: python

    from pylinac import profile
    from pylinac.metrics.profile import LeftPenumbraMetric

    # load the image and profile
    img = image.load("path/to/image.dcm")
    mid_profile = FWXMProfile(img.array[img.shape[0] // 2, :])

    # compute the penumbra
    left_penumbra = mid_profile.compute(metrics=[LeftPenumbraMetric(upper=80, lower=20)])

    print(left_penumbra)  # prints the penumbra value

Read more about 1D metrics: `Profiles & 1D Metrics <http://pylinac.readthedocs.org/en/latest/topics/profiles.html#metric-plugins>`_.

Convert Gantry, Collimator, Couch Coordinate Systems
####################################################

Convert gantry, collimator, and couch coordinates to and from each other:

.. code-block:: python

    from pylinac.core.scale import convert, MachineScale

    gantry = 0
    coll = 90
    couch = 45

    new_gantry, new_coll, new_couch = convert(
        input_scale=MachineScale.Varian,
        output_scale=MachineScale.IEC61217,
        gantry=gantry,
        collimator=coll,
        rotation=couch,
    )

Read more: `Coordinate Systems <http://pylinac.readthedocs.org/en/latest/topics/scale.html>`_.

Generate Synthetic Images
#########################

Want to generate images to test out your image analysis algorithms? Pylinac can do that.

Generate an AS1000 50x50mm, centered open field image at gantry 45:

.. code-block:: python

  from matplotlib import pyplot as plt

  from pylinac.core.image_generator import AS1000Image
  from pylinac.core.image_generator.layers import FilteredFieldLayer, GaussianFilterLayer

  as1000 = AS1000Image()  # this will set the pixel size and shape automatically
  as1000.add_layer(
      FilteredFieldLayer(field_size_mm=(50, 50))
  )  # create a 50x50mm square field
  as1000.add_layer(
      GaussianFilterLayer(sigma_mm=2)
  )  # add an image-wide gaussian to simulate penumbra/scatter
  as1000.generate_dicom(
      file_out_name="my_AS1000.dcm", gantry_angle=45
  )  # create a DICOM file with the simulated image
  # p

Related Skills

View on GitHub
GitHub Stars189
CategoryHealthcare
Updated8h ago
Forks122

Languages

Python

Security Score

100/100

Audited on Mar 24, 2026

No findings