Core Modules¶
The following is the API documentation for the core modules of pylinac. These can be used directly, or as the base for mixin classes or methods.
Image Module¶
This module holds classes for image loading and manipulation.
- pylinac.core.image.equate_images(image1: DicomImage | ArrayImage | FileImage | LinacDicomImage, image2: DicomImage | ArrayImage | FileImage | LinacDicomImage) tuple[DicomImage | ArrayImage | FileImage | LinacDicomImage, DicomImage | ArrayImage | FileImage | LinacDicomImage][source]¶
- Crop and resize two images to make them:
The same pixel dimensions
The same DPI
The usefulness of the function comes when trying to compare images from different sources. The best example is calculating gamma on a machine log fluence and EPID image. The physical and pixel dimensions must be normalized, the SID normalized
Parameters¶
- image1{
ArrayImage,DicomImage,FileImage} Must have DPI and SID.
- image2{
ArrayImage,DicomImage,FileImage} Must have DPI and SID.
Returns¶
- image1
ArrayImage The first image equated.
- image2
ArrayImage The second image equated.
- pylinac.core.image.is_image(path: str | BytesIO | DicomImage | ArrayImage | FileImage | LinacDicomImage | ndarray) bool[source]¶
Determine whether the path is a valid image file.
Returns¶
bool
- pylinac.core.image.retrieve_image_files(path: str) list[str][source]¶
Retrieve the file names of all the valid image files in the path.
Returns¶
- list
Contains strings pointing to valid image paths.
- pylinac.core.image.load(path: str | Path | DicomImage | ArrayImage | FileImage | LinacDicomImage | ndarray | BinaryIO, **kwargs) DicomImage | ArrayImage | FileImage | LinacDicomImage[source]¶
Load a DICOM image, JPG/TIF/BMP image, or numpy 2D array.
Parameters¶
- pathstr, file-object
The path to the image file or data stream or array.
- kwargs
See
FileImage,DicomImage, orArrayImagefor keyword arguments.
Returns¶
- :
FileImage,ArrayImage, orDicomImage Return type depends on input image.
Examples¶
Load an image from a file and then apply a filter:
>>> from pylinac.core.image import load >>> my_image = r"C:\QA\image.tif" >>> img = load(my_image) # returns a FileImage >>> img.filter(5)
Loading from an array is just like loading from a file:
>>> arr = np.arange(36).reshape(6, 6) >>> img = load(arr) # returns an ArrayImage
- pylinac.core.image.load_url(url: str, progress_bar: bool = True, **kwargs) DicomImage | ArrayImage | FileImage | LinacDicomImage[source]¶
Load an image from a URL.
Parameters¶
- urlstr
A string pointing to a valid URL that points to a file.
Note
For some images (e.g. Github), the raw binary URL must be used, not simply the basic link.
- progress_bar: bool
Whether to display a progress bar of download status.
- pylinac.core.image.load_multiples(image_file_list: ~collections.abc.Sequence, method: str = 'mean', stretch_each: bool = True, loader: callable = <function load>, **kwargs) DicomImage | ArrayImage | FileImage | LinacDicomImage[source]¶
Combine multiple image files into one superimposed image.
Parameters¶
- image_file_listlist
A list of the files to be superimposed.
- method{‘mean’, ‘max’, ‘sum’}
A string specifying how the image values should be combined.
- stretch_eachbool
Whether to normalize the images being combined by stretching their high/low values to the same values across images.
- loader: callable
The function to use to load the images. If a special image subclass is used, this is how it can be passed.
- kwargs :
Further keyword arguments are passed to the load function and stretch function.
Examples¶
Load multiple images:
>>> from pylinac.core.image import load_multiples >>> paths = ['starshot1.tif', 'starshot2.tif'] >>> superimposed_img = load_multiples(paths)
- class pylinac.core.image.BaseImage(path: str | Path | BytesIO | DicomImage | ArrayImage | FileImage | LinacDicomImage | ndarray | BufferedReader)[source]¶
Bases:
objectBase class for the Image classes.
Attributes¶
- pathstr
The path to the image file.
- arraynumpy.ndarray
The actual image pixel array.
Parameters¶
- pathstr
The path to the image.
- classmethod from_multiples(filelist: list[str], method: str = 'mean', stretch: bool = True, **kwargs) DicomImage | ArrayImage | FileImage | LinacDicomImage[source]¶
Load an instance from multiple image items. See
load_multiples().
- property center: Point¶
Return the center position of the image array as a Point. Even-length arrays will return the midpoint between central two indices. Odd will return the central index.
- property physical_shape: float, float¶
The physical size of the image in mm.
- date_created(format: str = '%A, %B %d, %Y') str[source]¶
The date the file was created. Tries DICOM data before falling back on OS timestamp. The method use one or more inputs of formatted code, where % means a placeholder and the letter the time unit of interest. For a full description of the several formatting codes see strftime() documentation.
Parameters¶
- formatstr
%A means weekday full name, %B month full name, %d day of the month as a zero-padded decimal number and %Y year with century as a decimal number.
Returns¶
- str
The date the file was created.
- plotly(fig: Figure | None = None, colorscale: str = 'gray', title: str = '', show: bool = True, show_metrics: bool = True, show_colorbar: bool = True, **kwargs) Figure[source]¶
Plot the image in a plotly figure.
Parameters¶
- fig: plotly.graph_objects.Figure
The figure to plot to. If None, a new figure is created.
- colorscale: str
The colorscale to use on the plot. See https://plotly.com/python/builtin-colorscales/
- showbool
Whether to show the plot. Set to False if performing later adjustments to the plot.
- show_metricsbool
Whether to show the metrics on the image.
- title: str
The title of the plot.
- show_colorbarbool
Whether to show the colorbar on the plot.
- kwargs
Additional keyword arguments to pass to the plot.
- plot(ax: Axes = None, show: bool = True, clear_fig: bool = False, show_metrics: bool = True, metric_kwargs: dict | None = None, **kwargs) Axes[source]¶
Plot the image.
Parameters¶
- axmatplotlib.Axes instance
The axis to plot the image to. If None, creates a new figure.
- showbool
Whether to actually show the image. Set to false when plotting multiple items.
- clear_figbool
Whether to clear the prior items on the figure before plotting.
- show_metricsbool
Whether to show the metrics on the image.
- metric_kwargsdict
kwargs passed to the metric plot method.
- kwargs
kwargs passed to plt.imshow()
- plot_metrics(show: bool = True) list[figure][source]¶
Plot any additional figures from the metrics.
Returns a list of figures of the metrics. These metrics are not drawn on the original image but rather are something complete separate. E.g. a profile plot or a histogram of the metric.
- filter(size: float | int = 0.05, kind: str = 'median') None[source]¶
Filter the profile in place.
Parameters¶
- sizeint, float
Size of the median filter to apply. If a float, the size is the ratio of the length. Must be in the range 0-1. E.g. if size=0.1 for a 1000-element array, the filter will be 100 elements. If an int, the filter is the size passed.
- kind{‘median’, ‘gaussian’}
The kind of filter to apply. If gaussian, size is the sigma value.
- crop(pixels: int = 15, edges: tuple[str, ...] = ('top', 'bottom', 'left', 'right')) None[source]¶
Removes pixels on all edges of the image in-place.
Parameters¶
- pixelsint
Number of pixels to cut off all sides of the image.
- edgestuple
Which edges to remove from. Can be any combination of the four edges.
- roll(direction: str = 'x', amount: int = 1) None[source]¶
Roll the image array around in-place. Wrapper for np.roll().
Parameters¶
- direction{‘x’, ‘y’}
The axis to roll over.
- amountint
The amount of elements to roll over.
- rot90(n: int = 1) None[source]¶
Wrapper for numpy.rot90; rotate the array by 90 degrees CCW n times.
- rotate(angle: float, mode: str = 'edge', *args, **kwargs)[source]¶
Rotate the image counter-clockwise. Simple wrapper for scikit-image. See https://scikit-image.org/docs/stable/api/skimage.transform.html#skimage.transform.rotate. All parameters are passed to that function.
- threshold(threshold: float, kind: str = 'high') None[source]¶
Apply a high- or low-pass threshold filter.
Parameters¶
- thresholdint
The cutoff value.
- kindstr
If
high(default), will apply a high-pass threshold. All values above the cutoff are left as-is. Remaining points are set to 0. Iflow, will apply a low-pass threshold.
- as_binary(threshold: int) DicomImage | ArrayImage | FileImage | LinacDicomImage[source]¶
Return a binary (black & white) image based on the given threshold.
Parameters¶
- thresholdint, float
The threshold value. If the value is above or equal to the threshold it is set to 1, otherwise to 0.
Returns¶
ArrayImage
- dist2edge_min(point: Point | tuple) float[source]¶
Calculates distance from given point to the closest edge.
Parameters¶
point : geometry.Point, tuple
Returns¶
float
- ground() float[source]¶
Ground the profile in place such that the lowest value is 0.
Note
This will also “ground” profiles that are negative or partially-negative. For such profiles, be careful that this is the behavior you desire.
Returns¶
- float
The amount subtracted from the image.
- normalize(norm_val: str | float | None = None) None[source]¶
Normalize the profile to the given value.
Parameters¶
- valuenumber or None
If a number, normalize the array to that number. If None, normalizes to the maximum value.
- check_inversion(box_size: int = 20, position: float, float = (0.0, 0.0)) None[source]¶
Check the image for inversion by sampling the 4 image corners. If the average value of the four corners is above the average pixel value, then it is very likely inverted.
Parameters¶
- box_sizeint
The size in pixels of the corner box to detect inversion.
- position2-element sequence
The location of the sampling boxes.
- check_inversion_by_histogram(percentiles: float, float, float = (5, 50, 95)) bool[source]¶
Check the inversion of the image using histogram analysis. The assumption is that the image is mostly background-like values and that there is a relatively small amount of dose getting to the image (e.g. a picket fence image). This function looks at the distance from one percentile to another to determine if the image should be inverted.
Parameters¶
- percentiles3-element tuple
The 3 percentiles to compare. Default is (5, 50, 95). Recommend using (x, 50, y). To invert the other way (where pixel value is decreasing with dose, reverse the percentiles, e.g. (95, 50, 5).
Returns¶
bool: Whether an inversion was performed.
- gamma(comparison_image: DicomImage | ArrayImage | FileImage | LinacDicomImage, doseTA: float = 1, distTA: float = 1, threshold: float = 0.1, ground: bool = True, normalize: bool = True) ndarray[source]¶
Calculate the gamma between the current image (reference) and a comparison image.
Added in version 1.2.
The gamma calculation is based on Bakai et al eq.6, which is a quicker alternative to the standard Low gamma equation.
Parameters¶
- comparison_image{
ArrayImage,DicomImage, orFileImage} The comparison image. The image must have the same DPI/DPMM to be comparable. The size of the images must also be the same.
- doseTAint, float
Dose-to-agreement in percent; e.g. 2 is 2%.
- distTAint, float
Distance-to-agreement in mm.
- thresholdfloat
The dose threshold percentage of the maximum dose, below which is not analyzed. Must be between 0 and 1.
- groundbool
Whether to “ground” the image values. If true, this sets both datasets to have the minimum value at 0. This can fix offset errors in the data.
- normalizebool
Whether to normalize the images. This sets the max value of each image to the same value.
Returns¶
- gamma_mapnumpy.ndarray
The calculated gamma map.
See Also¶
- comparison_image{
- compute(metrics: list[MetricBase] | MetricBase) Any | dict[str, Any][source]¶
Compute the given metrics on the image.
This can be called multiple times to compute different metrics. Metrics are appended on each call. This allows for modification of the image between metric calls as well as the ability to compute different metrics on the same image that might depend on earlier metrics.
Metrics are both returned and stored in the
metricsattribute. Themetricsattribute will store all metrics every calculated. The metrics returned are only those passed in themetricsargument.Parameters¶
- metricslist[MetricBase] | MetricBase
The metric(s) to compute.
- class pylinac.core.image.XIM(file_path: str | Path, read_pixels: bool = True)[source]¶
Bases:
BaseImageA class to open, read, and/or export an .xim image, Varian’s custom image format which is 99.999% PNG
This had inspiration from a number of places: - https://gist.github.com/1328/7da697c71f9c4ef12e1e - https://medium.com/@duhroach/how-png-works-f1174e3cc7b7 - https://www.mathworks.com/matlabcentral/answers/419228-how-to-write-for-loop-and-execute-data - https://www.w3.org/TR/PNG-Filters.html - https://bitbucket.org/dmoderesearchtools/ximreader/src/master/
Parameters¶
- file_path
The path to the file of interest.
- read_pixels
Whether to read and parse the pixel information. Doing so is quite slow. Set this to false if, e.g., you are searching for images only via tags or doing a pre-filtering of image selection.
- array: np.ndarray¶
- properties: dict¶
- property dpmm: float¶
The dots/mm value of the XIM images. The value appears to be in cm in the file.
- as_dicom() Dataset[source]¶
Save the XIM image as a simplistic DICOM file. Only meant for basic image storage/analysis.
It appears that XIM images are in the Varian standard coordinate system. We convert to IEC61217 for more general compatibility.
- save_as(file: str | Path, format: str | None = None) None[source]¶
Save the image to a NORMAL format. PNG is highly suggested. Accepts any format supported by Pillow. Ironically, an equivalent PNG image (w/ metadata) is ~50% smaller than an .xim image.
Warning
Any format other than PNG will not include the properties included in the .xim image!
Parameters¶
- file
The file to save the image to. E.g. my_xim.png
- format
The format to save the image as. Uses the Pillow logic, which will infer the format if the file name has one.
- class pylinac.core.image.DicomImage(path: str | Path | BytesIO | BufferedReader, *, dtype: dtype | None = None, dpi: float = None, sid: float = None, sad: float = 1000, raw_pixels: bool = False, invert_pixels: bool | None = None)[source]¶
Bases:
BaseImageAn image from a DICOM RTImage file.
Attributes¶
- metadatapydicom Dataset
The dataset of the file as returned by pydicom without pixel data.
Parameters¶
- pathstr, file-object
The path to the file or the data stream.
- dtypedtype, None, optional
The data type to cast the image data as. If None, will use whatever raw image format is.
- dpiint, float
The dots-per-inch of the image, defined at isocenter.
Note
If a DPI tag is found in the image, that value will override the parameter, otherwise this one will be used.
- sidint, float
The Source-to-Image distance in mm.
- sadfloat
The Source-to-Axis distance in mm.
- raw_pixelsbool
Whether to apply pixel intensity correction to the DICOM data. Typically, Rescale Slope, Rescale Intercept, and other tags are included and meant to be applied to the raw pixel data, which is potentially compressed. If True, no correction will be applied. This is typically used for scenarios when you want to match behavior to older or different software.
- invert_pixelsbool | None
Whether to invert the pixel values (inverted = max + min - original). If True, the pixel value will be inverted. If False, the pixel value will be not inverted. If None, the pixel value will be inverted if PixelIntensityRelationshipSign=-1
- classmethod from_dataset(dataset: Dataset)[source]¶
Create a DICOM image instance from a pydicom Dataset.
- save(filename: str | Path) str | Path[source]¶
Save the image instance back out to a .dcm file.
Parameters¶
- filenamestr, Path
The filename to save the DICOM file as.
Returns¶
A string pointing to the new filename.
- property z_position: float¶
The z-position of the slice. Relevant for CT and MR images.
- property slice_spacing: float¶
Determine the distance between slices. The spacing can be greater than the slice thickness (i.e. gaps). Uses the absolute version as it can apparently be negative: https://dicom.innolitics.com/ciods/nm-image/nm-reconstruction/00180088
This attempts to use the slice spacing attr and if it doesn’t exist, use the slice thickness attr
- property sid: float¶
The Source-to-Image in mm.
- property sad: float¶
The source to axis (iso) in mm
- property dpi: float¶
The dots-per-inch of the image, defined at isocenter.
- property dpmm: float¶
The Dots-per-mm of the image, defined at isocenter. E.g. if an EPID image is taken at 150cm SID, the dpmm will scale back to 100cm.
- property cax: Point¶
The center of the image, accounting for EPID translations (e.g. Isocal). If no DICOM translation tags are found then the center is returned. Uses this tag: https://dicom.innolitics.com/ciods/rt-beams-delivery-instruction/rt-beams-delivery-instruction/00741020/00741030/3002000d which is in mm.
Notes¶
The DICOM tag is in mm, so the value must be converted to pixels.
The DICOM tag is (x,y,z) using the Gantry IEC coordinate space, meaning +x is right, +y is in.
DICOM y-axis pixel indices INCREASE going down the image. Combined with above, this means we must subtract from the x-axis and add from the y-axis to get the correct pixel location because the CAX is in the opposite direction of the translation.
We currently assume that the shift is AT THE PANEL, meaning we have to back-correct the shift for the magnification.
- class pylinac.core.image.LinacDicomImage(path: str | Path | BinaryIO, use_filenames: bool = False, axes_precision: int | None = None, **kwargs)[source]¶
Bases:
DicomImageDICOM image taken on a linac. Also allows passing of gantry/coll/couch values via the filename.
Parameters¶
- pathstr, file-object
The path to the file or the data stream.
- dtypedtype, None, optional
The data type to cast the image data as. If None, will use whatever raw image format is.
- dpiint, float
The dots-per-inch of the image, defined at isocenter.
Note
If a DPI tag is found in the image, that value will override the parameter, otherwise this one will be used.
- sidint, float
The Source-to-Image distance in mm.
- sadfloat
The Source-to-Axis distance in mm.
- raw_pixelsbool
Whether to apply pixel intensity correction to the DICOM data. Typically, Rescale Slope, Rescale Intercept, and other tags are included and meant to be applied to the raw pixel data, which is potentially compressed. If True, no correction will be applied. This is typically used for scenarios when you want to match behavior to older or different software.
- invert_pixelsbool | None
Whether to invert the pixel values (inverted = max + min - original). If True, the pixel value will be inverted. If False, the pixel value will be not inverted. If None, the pixel value will be inverted if PixelIntensityRelationshipSign=-1
- property gantry_angle: float¶
Gantry angle of the irradiation.
- property collimator_angle: float¶
Collimator angle of the irradiation.
- property couch_angle: float¶
Couch angle of the irradiation.
- class pylinac.core.image.FileImage(path: str | Path | BinaryIO, *, dpi: float | None = None, sid: float | None = None, dtype: dtype | None = None)[source]¶
Bases:
BaseImageAn image from a “regular” file (.tif, .jpg, .bmp).
Attributes¶
- infodict
The info dictionary as generated by Pillow.
- sidfloat
The SID value as passed in upon construction.
Parameters¶
- pathstr, file-object
The path to the file or a data stream.
- dpiint, float
The dots-per-inch of the image, defined at isocenter.
Note
If a DPI tag is found in the image, that value will override the parameter, otherwise this one will be used.
- sidint, float
The Source-to-Image distance in mm.
- dtypenumpy.dtype
The data type to cast the array as. If None, will use the datatype stored in the file. If the file is multi-channel (e.g. RGB), it will be converted to int32
- property dpi: float | None¶
The dots-per-inch of the image, defined at isocenter.
- property dpmm: float | None¶
The Dots-per-mm of the image, defined at isocenter. E.g. if an EPID image is taken at 150cm SID, the dpmm will scale back to 100cm.
- class pylinac.core.image.ArrayImage(array: ndarray, *, dpi: float = None, sid: float = None, dtype=None)[source]¶
Bases:
BaseImageAn image constructed solely from a numpy array.
Parameters¶
- arraynumpy.ndarray
The image array.
- dpiint, float
The dots-per-inch of the image, defined at isocenter.
Note
If a DPI tag is found in the image, that value will override the parameter, otherwise this one will be used.
- sidint, float
The Source-to-Image distance in mm.
- dtypedtype, None, optional
The data type to cast the image data as. If None, will use whatever raw image format is.
- property dpmm: float | None¶
The Dots-per-mm of the image, defined at isocenter. E.g. if an EPID image is taken at 150cm SID, the dpmm will scale back to 100cm.
- property dpi: float | None¶
The dots-per-inch of the image, defined at isocenter.
- class pylinac.core.image.LazyZipDicomImageStack(folder: str | Path | BinaryIO, dtype: dtype | None = None, min_number: int = 39, check_uid: bool = True)[source]¶
Bases:
LazyDicomImageStackA variant of the lazy stack where a .zip archive is passed and the archive is NOT extracted to disk. The most memory-efficient for use cases like Cloud Run where disk=memory
Load a folder with DICOM CT images. This variant is more memory efficient than the standard DicomImageStack.
This is done by loading images from disk on the fly. This assumes all images remain on disk for the lifetime of the instance. This does not need to be true for the original implementation.
See the documentation for DicomImageStack for parameter descriptions.
- class pylinac.core.image.DicomImageStack(folder: str | Path, dtype: dtype | None = None, min_number: int = 39, check_uid: bool = True, raw_pixels: bool = False)[source]¶
Bases:
LazyDicomImageStackA class that loads and holds a stack of DICOM images (e.g. a CT dataset). The class can take a folder or zip file and will read CT images. The images must all be the same size. Supports indexing to individual images.
Attributes¶
- imageslist
Holds instances of
DicomImage. Can be accessed via index; i.e. self[0] == self.images[0].
Examples¶
Load a folder of Dicom images >>> from pylinac import image >>> img_folder = r”folder/qa/cbct/june” >>> dcm_stack = image.DicomImageStack(img_folder) # loads and sorts the images >>> dcm_stack.plot(3) # plot the 3rd image
Load a zip archive >>> img_folder_zip = r”archive/qa/cbct/june.zip” # save space and zip your CBCTs >>> dcm_stack = image.DicomImageStack.from_zip(img_folder_zip)
Load as a certain data type >>> dcm_stack_uint32 = image.DicomImageStack(img_folder, dtype=np.uint32)
Load a folder with DICOM CT images.
Parameters¶
- folderstr
Path to the folder.
- dtypedtype, None, optional
The data type to cast the image data as. If None, will use whatever raw image format is.
- class pylinac.core.image.NMImageStack(path: str | Path)[source]¶
Bases:
objectA class of frames of a nuclear medicine image. A single image can have N frames. For our purposes, we can treat this as a stack of images.
Load a single NM image with N frames.
- pylinac.core.image.tiff_to_dicom(tiff_file: str | Path | BytesIO, sid: float, gantry: float, coll: float, couch: float, dpi: float | None = None, extra_tags: dict | None = None) Dataset[source]¶
Converts a TIFF file into a simplistic DICOM file. Not meant to be a full-fledged tool. Used for conversion so that tools that are traditionally oriented towards DICOM have a path to accept TIFF. Currently used to convert files for WL.
Note
This will convert the image into an uint16 datatype to match the native EPID datatype.
Parameters¶
- tiff_file
The TIFF file to be converted.
- sid
The Source-to-Image distance in mm.
- dpi
The dots-per-inch value of the TIFF image.
- gantry
The gantry value that the image was taken at.
- coll
The collimator value that the image was taken at.
- couch
The couch value that the image was taken at.
- extra_tags
Additional keyword arguments to pass to the DICOM constructor. These are tags that should be included in the DICOM file. E.g. PatientName, etc.
- pylinac.core.image.load_raw_visionrt(path: str | ~pathlib.Path, shape: tuple[int, int] = (600, 960), dtype=<class 'numpy.uint32'>, **kwargs) ArrayImage[source]¶
Load a .raw file from a VisionRT system.
Parameters¶
- pathstr, Path
The path to the file.
- shapetuple
The shape of the image. Default is 960x600.
- dtypedtype
The datatype of the image.
- kwargs
Additional keyword arguments to pass to the ArrayImage. This most often is SID and DPI.
- pylinac.core.image.load_raw_cyberknife(path: str | ~pathlib.Path, shape: tuple[int, int] | None = None, dtype=<class 'numpy.uint16'>, **kwargs) ArrayImage[source]¶
Load a CyberKnife image.
Parameters¶
- pathstr, Path
The path to the file.
- shapetuple
The shape of the image. If None, will attempt to read the shape from the file.
- dtypedtype
The datatype of the image.
- kwargs
Additional keyword arguments to pass to the ArrayImage. This most often is SID and DPI.
- pylinac.core.image.load_raw(path: str | Path, shape: tuple[int, int], dtype: dtype, **kwargs) ArrayImage[source]¶
Load a raw file.
Parameters¶
- pathstr, Path
The path to the file.
- shapetuple
The shape of the image.
- dtypedtype
The datatype of the image.
- kwargs
Additional keyword arguments to pass to the ArrayImage. This most often is SID and DPI.
Geometry Module¶
Module for classes that represent common geometric objects or patterns.
- pylinac.core.geometry.tan(degrees: float) float[source]¶
Calculate the tangent of the given degrees.
- pylinac.core.geometry.atan(x: float, y: float) float[source]¶
Calculate the degrees of a given x/y from the origin
- pylinac.core.geometry.direction_to_coords(start_x: float, start_y: float, distance: float, angle_degrees: float)[source]¶
Calculate destination coordinates given a start position, distance, and angle.
The 0-angle position is pointing to the right (i.e. unit circle)
Parameters¶
- start_xfloat
Starting x position
- start_yfloat
Starting y position
- distancefloat
Distance to travel
- angle_degreesfloat
Angle to travel in degrees.
- class pylinac.core.geometry.Point(x: float | tuple | Point = 0, y: float = 0, z: float = 0, idx: int | None = None, value: float | None = None, as_int: bool = False)[source]¶
Bases:
objectA geometric point with x, y, and z coordinates/attributes.
Parameters¶
- xnumber-like, Point, iterable
x-coordinate or iterable type containing all coordinates. If iterable, values are assumed to be in order: (x,y,z).
- ynumber-like, optional
y-coordinate
- idxint, optional
Index of point. Useful for sequential coordinates; e.g. a point on a circle profile is sometimes easier to describe in terms of its index rather than x,y coords.
- valuenumber-like, optional
value at point location (e.g. pixel value of an image)
- as_intboolean
If True, coordinates are converted to integers.
- distance_to(thing: Point | Circle) float[source]¶
Calculate the distance to the given point.
Parameters¶
- thingCircle, Point, 2 element iterable
The other thing to calculate distance to.
- class pylinac.core.geometry.Circle(center_point: Point | Iterable = (0, 0), radius: float = 0)[source]¶
Bases:
objectA geometric circle with center Point, radius, and diameter.
Parameters¶
- center_pointPoint, optional
Center point of the wobble circle.
- radiusfloat, optional
Radius of the wobble circle.
- property area: float¶
The area of the circle.
- property diameter: float¶
Get the diameter of the circle.
- plotly(fig: Figure, line_color: str = 'black', fill: bool = False, **kwargs) None[source]¶
Draw the circle on a plotly figure.
- plot2axes(axes: Axes, edgecolor: str = 'black', fill: bool = False, text: str = '', fontsize: str = 'medium', ha: str = 'center', va: str = 'center', **kwargs) None[source]¶
Plot the Circle on the axes.
Parameters¶
- axesmatplotlib.axes.Axes
An MPL axes to plot to.
- edgecolorstr
The color of the circle.
- fillbool
Whether to fill the circle with color or leave hollow.
- text: str
If provided, plots the given text at the center. Useful for identifying ROIs on a plotted image apart.
- fontsize: str
The size of the text, if provided. See https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.text.html for options.
- class pylinac.core.geometry.Vector(x: float = 0, y: float = 0, z: float = 0)[source]¶
Bases:
objectA vector with x, y, and z coordinates.
- pylinac.core.geometry.vector_is_close(vector1: Vector, vector2: Vector, delta: float = 0.1) bool[source]¶
Determine if two vectors are with delta of each other; this is a simple coordinate comparison check.
- class pylinac.core.geometry.Line(point1: Point | tuple[float, float], point2: Point | tuple[float, float])[source]¶
Bases:
objectA line that is represented by two points or by m*x+b.
Notes¶
Calculations of slope, etc are from here: http://en.wikipedia.org/wiki/Linear_equation and here: http://www.mathsisfun.com/algebra/line-equation-2points.html
Parameters¶
- point1Point
One point of the line
- point2Point
Second point along the line.
- property m: float¶
Return the slope of the line.
m = (y1 - y2)/(x1 - x2)
- property b: float¶
Return the y-intercept of the line.
b = y - m*x
- property length: float¶
Return length of the line, if finite.
- distance_to(point: Point) float[source]¶
Calculate the minimum distance from the line to a point.
Equations are from here: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html #14
Parameters¶
- pointPoint, iterable
The point to calculate distance to.
- class pylinac.core.geometry.Rectangle(width: float, height: float, center: Point | tuple, rotation: float = 0.0)[source]¶
Bases:
objectA rectangle with 4 vertices.
This always assumes an image/screen coordinate system where +x is to the right and +y is down. Thus, the “top-left” corner are colloquial terms and is the point with the lowest x and y coordinate values of the UNROTATED rectangle. From the users’ perspective, it is the upper-most and left-most corner.
Parameters¶
- widthnumber
Width of the rectangle. Must be positive
- heightnumber
Height of the rectangle. Must be positive.
- centerPoint, iterable, optional
Center point of rectangle.
- rotationfloat
The rotation of the rectangle in degrees, using the “x goes to y” rule and assuming image coordinate system, a positive rotation is clockwise. Default is 0 (no rotation).
- property area: float¶
The area of the rectangle.
- plotly(fig: Figure, fill: bool = False, **kwargs) None[source]¶
Draw the rectangle on a plotly figure.
- plot2axes(axes: Axes, edgecolor: str = 'black', fill: bool = False, alpha: float = 1, facecolor: str = 'g', label=None, text: str = '', fontsize: str = 'medium', text_rotation: float = 0, ha='center', va='center', **kwargs)[source]¶
Plot the Rectangle to the axes.
Parameters¶
- axesmatplotlib.axes.Axes
An MPL axes to plot to.
- edgecolorstr
The color of the circle.
- fillbool
Whether to fill the rectangle with color or leave hollow.
- text: str
If provided, plots the given text at the center. Useful for identifying ROIs on a plotted image apart.
- fontsize: str
The size of the text, if provided. See https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.text.html for options.
- text_rotation: float
The rotation of the text in degrees.
- ha: str
Horizontal alignment of the text. See https://matplotlib.org/stable/api/text_api.html#matplotlib.text.Text
- va: str
Vertical alignment of the text. See https://matplotlib.org/stable/api/text_api.html#matplotlib.text.Text
Profile Module¶
I/O Module¶
I/O helper functions for pylinac.
- pylinac.core.io.is_dicom(file: str | Path) bool[source]¶
Boolean specifying if the file is a proper DICOM file.
This function is a pared down version of read_preamble meant for a fast return. The file is read for a proper preamble (‘DICM’), returning True if so, and False otherwise. This is a conservative approach.
Parameters¶
- filestr
The path to the file.
See Also¶
pydicom.filereader.read_preamble pydicom.filereader.read_partial
- pylinac.core.io.is_dicom_image(file: str | Path | BinaryIO) bool[source]¶
Boolean specifying if file is a proper DICOM file with a image
Parameters¶
- filestr
The path to the file.
See Also¶
pydicom.filereader.read_preamble pydicom.filereader.read_partial
- pylinac.core.io.retrieve_dicom_file(file: str | Path | BinaryIO) FileDataset[source]¶
Read and return the DICOM dataset.
Parameters¶
- filestr
The path to the file.
- class pylinac.core.io.TemporaryZipDirectory(zfile: str | Path | BinaryIO, delete: bool = True)[source]¶
Bases:
TemporaryDirectoryCreates a temporary directory that unpacks a ZIP archive. Shockingly useful
Parameters¶
- zfilestr
String that points to a ZIP archive.
- deletebool
Whether to delete the temporary directory when the context manager exits.
- pylinac.core.io.retrieve_filenames(directory: str | Path, func: Callable | None = None, recursive: bool = True, **kwargs) list[str][source]¶
Retrieve file names in a directory.
Parameters¶
- directorystr
The directory to walk over recursively.
- funcfunction, None
The function that validates if the file name should be kept. If None, no validation will be performed and all file names will be returned.
- recursivebool
Whether to search only the root directory.
- kwargs
Additional arguments passed to the func parameter.
- pylinac.core.io.retrieve_demo_file(name: str, force: bool = False) Path[source]¶
Retrieve the demo file either by getting it from file or from a URL.
If the file is already on disk it returns the file name. If the file isn’t on disk, get the file from the URL and put it at the expected demo file location on disk for lazy loading next time.
Parameters¶
- namestr
The suffix to the url (location within the S3 bucket) pointing to the demo file.
- pylinac.core.io.is_url(url: str) bool[source]¶
Determine whether a given string is a valid URL.
Parameters¶
url : str
Returns¶
bool
- pylinac.core.io.get_url(url: str, destination: str | Path | None = None, progress_bar: bool = True) str[source]¶
Download a URL to a local file.
Parameters¶
- urlstr
The URL to download.
- destinationstr, None
The destination of the file. If None is given the file is saved to a temporary directory.
- progress_barbool
Whether to show a command-line progress bar while downloading.
Returns¶
- filenamestr
The location of the downloaded file.
Notes¶
Progress bar use/example adapted from tqdm documentation: https://github.com/tqdm/tqdm
- class pylinac.core.io.SNCProfiler(path: str, gain_row: int = 20, detector_row: int = 106, bias_row: int = 107, calibration_row: int = 108, data_row: int = -1, data_columns: slice = slice(5, 259, None))[source]¶
Bases:
objectLoad a file from a Sun Nuclear Profiler device. This accepts .prs files.
Parameters¶
- pathstr
Path to the .prs file.
- detector_row
The row that contains the detector data.
- bias_row
The row that contains the bias data.
- calibration_row
The row that contains the calibration data.
- data_row
The row that contains the data.
- data_columns
The range of columns that the data is in. Usually, there are some columns before and after the real data.
- to_profiles(n_detectors_row: int = 63, **kwargs) tuple[SingleProfile, SingleProfile, SingleProfile, SingleProfile][source]¶
Convert the SNC data to SingleProfiles. These can be analyzed directly or passed to other modules like flat/sym. For the horizontal/cross-plane profile, the detectors on either side of the central detector are missing. We adjust the x-values to reflect this.
Parameters¶
- n_detectors_rowint
The number of detectors in a given row. Note that they Y profile includes 2 extra detectors from the other 3.
ROI Module¶
- pylinac.core.roi.bbox_center(region: RegionProperties) Point[source]¶
Return the center of the bounding box of an scikit-image region.
Parameters¶
- region
A scikit-image region as calculated by skimage.measure.regionprops().
Returns¶
point :
Point
- class pylinac.core.roi.DiskROI(array: ndarray, radius: float, center: Point)[source]¶
Bases:
CircleA class representing a disk-shaped Region of Interest.
Parameters¶
- arrayndarray
The 2D array representing the image the disk is on.
- radiusfloat
The radius of the ROI in pixels
- centerPoint
The center of the Disk ROI.
- classmethod from_phantom_center(array: ndarray, angle: float, roi_radius: float, dist_from_center: float, phantom_center: tuple | Point)[source]¶
Parameters¶
- arrayndarray
The 2D array representing the image the disk is on.
- angleint, float
The angle of the ROI in degrees from the phantom center.
- roi_radiusint, float
The radius of the ROI from the center of the phantom.
- dist_from_centerint, float
The distance of the ROI from the phantom center.
- phantom_centertuple
The location of the phantom center.
Notes¶
Parameter names are different from the regular class constructor due to historical reasons and semi-backwards compatibility.
- property pixel_value: float¶
The median pixel value of the ROI.
- property std: float¶
The standard deviation of the pixel values.
- plot2axes(axes: Axes | None = None, edgecolor: str = 'black', fill: bool = False, text: str = '', fontsize: str = 'medium', **kwargs) None[source]¶
Plot the Circle on the axes.
Parameters¶
- axesmatplotlib.axes.Axes
An MPL axes to plot to.
- edgecolorstr
The color of the circle.
- fillbool
Whether to fill the circle with color or leave hollow.
- text: str
If provided, plots the given text at the center. Useful for differentiating ROIs on a plotted image.
- fontsize: str
The size of the text, if provided. See https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.text.html for options.
- class pylinac.core.roi.LowContrastDiskROI(array: np.ndarray | ArrayImage, radius: float, center: Point, contrast_threshold: float | None = None, contrast_reference: float | None = None, cnr_threshold: float | None = None, contrast_method: str = 'Michelson', visibility_threshold: float = 0.1)[source]¶
Bases:
DiskROIA class for analyzing the low-contrast disks.
Parameters¶
- arrayndarray
The 2D array representing the image the disk is on.
- radiusint, float
The radius of the ROI.
- centerPoint
The ROI center location.
- contrast_thresholdfloat, int
The threshold for considering a bubble to be “seen”.
- contrast_referencefloat, int
The reference contrast value.
- cnr_thresholdfloat, int
The threshold for the CNR constant.
- contrast_methodstr
The method to calculate contrast.
- visibility_thresholdfloat, int
The threshold for the visibility to be considered passing.
- classmethod from_phantom_center(array: np.ndarray | ArrayImage, angle: float, roi_radius: float, dist_from_center: float, phantom_center: tuple | Point, contrast_threshold: float | None = None, contrast_reference: float | None = None, cnr_threshold: float | None = None, contrast_method: str = 'Michelson', visibility_threshold: float | None = 0.1)[source]¶
Parameters¶
- arrayndarray
The 2D array representing the image the disk is on.
- angleint, float
The angle of the ROI in degrees from the phantom center.
- roi_radiusint, float
The radius of the ROI from the center of the phantom.
- dist_from_centerint, float
The distance of the ROI from the phantom center.
- phantom_centertuple
The location of the phantom center.
- contrast_thresholdfloat, int
The threshold for considering a bubble to be “seen”.
- contrast_referencefloat, int
The reference contrast value.
- cnr_thresholdfloat, int
The threshold for the CNR constant.
- contrast_methodstr
The method to calculate contrast.
- visibility_thresholdfloat, int
The threshold for the visibility. If not provided, no visibility is calculated.
Notes¶
Parameter names are different from the regular class constructor due to historical reasons and semi-backwards compatibility.
- property signal_to_noise: float¶
The signal-to-noise ratio. Cast to numpy first to use numpy overflow handling.
- property contrast_to_noise: float¶
The contrast to noise ratio of the ROI. Cast to numpy first to use numpy overflow handling.
- property michelson: float¶
The Michelson contrast
- property weber: float¶
The Weber contrast
- property rms: float¶
The root-mean-square contrast
- property ratio: float¶
The ratio contrast
- property contrast: float¶
The contrast of the bubble. Uses the contrast method passed in the constructor. See https://en.wikipedia.org/wiki/Contrast_(vision).
- property cnr_constant: float¶
The contrast-to-noise value times the bubble diameter.
- property visibility: float¶
The visual perception of CNR. Uses the model from A Rose: https://www.osapublishing.org/josa/abstract.cfm?uri=josa-38-2-196. See also here: https://howradiologyworks.com/x-ray-cnr/. Finally, a review paper here: http://xrm.phys.northwestern.edu/research/pdf_papers/1999/burgess_josaa_1999.pdf Importantly, the Rose model is not applicable for high-contrast use cases.
- property contrast_constant: float¶
The contrast value times the bubble diameter.
- property passed: bool¶
Whether the disk ROI contrast passed.
- property passed_visibility: bool¶
Whether the disk ROI’s visibility passed.
- property passed_contrast_constant: bool¶
Boolean specifying if ROI pixel value was within tolerance of the nominal value.
- property passed_cnr_constant: bool¶
Boolean specifying if ROI pixel value was within tolerance of the nominal value.
- property plot_color: str¶
Return one of two colors depending on if ROI passed.
- property plot_color_constant: str¶
Return one of two colors depending on if ROI passed.
- property plot_color_cnr: str¶
Return one of two colors depending on if ROI passed.
- as_dict() dict[source]¶
Dump important data as a dictionary. Useful when exporting a results_data output
- property std: float¶
The std within the ROI.
- property max: float¶
The max pixel value of the ROI.
- property min: float¶
The min pixel value of the ROI.
- class pylinac.core.roi.HighContrastDiskROI(array: ndarray, radius: float, center: Point, contrast_threshold: float)[source]¶
Bases:
DiskROIA class for analyzing the high-contrast disks.
Parameters¶
- arrayndarray
The 2D array representing the image the disk is on.
- radiusint, float
The radius of the ROI.
- centerPoint
The ROI center location.
- contrast_thresholdfloat, int
The threshold for considering a bubble to be “seen”.
- classmethod from_phantom_center(array: ndarray, angle: float, roi_radius: float, dist_from_center: float, phantom_center: tuple | Point, contrast_threshold: float)[source]¶
Parameters¶
- arrayndarray
The 2D array representing the image the disk is on.
- angleint, float
The angle of the ROI in degrees from the phantom center.
- roi_radiusint, float
The radius of the ROI from the center of the phantom.
- dist_from_centerint, float
The distance of the ROI from the phantom center.
- phantom_centertuple
The location of the phantom center.
- contrast_thresholdfloat, int
The threshold for considering a bubble to be “seen”.
Notes¶
Parameter names are different from the regular class constructor due to historical reasons and semi-backwards compatibility.
- property max: float¶
The max pixel value of the ROI.
- property min: float¶
The min pixel value of the ROI.
- property mean: float¶
The mean pixel value of the ROI.
- class pylinac.core.roi.RectangleROI(array: ndarray, width: float, height: float, center: Point, rotation: float = 0.0)[source]¶
Bases:
RectangleClass that represents a rectangular ROI.
Parameters¶
- arrayndarray
The 2D array representing the image the disk is on.
- widthfloat
The width of the ROI in pixels.
- heightfloat
The height of the ROI in pixels.
- centerPoint
The location of the ROI center.
- rotationfloat
The rotation of the ROI itself in degrees. Defaults to 0.0.
Warning
This is separate from the angle parameter, which is the angle of the ROI from the phantom center.
- classmethod from_phantom_center(array: ndarray, width: float, height: float, angle: float, dist_from_center: float, phantom_center: Point, rotation: float = 0.0)[source]¶
Parameters¶
- arrayndarray
The 2D array representing the image the disk is on.
- widthfloat
The width of the ROI in pixels.
- heightfloat
The height of the ROI in pixels.
- anglefloat
The angle of the ROI in degrees from the phantom center.
- dist_from_centerfloat
The distance of the ROI from the phantom center.
- phantom_centertuple
The location of the phantom center.
- rotationfloat
The rotation of the ROI itself in degrees. Defaults to 0.0.
Warning
This is separate from the angle parameter, which is the angle of the ROI from the phantom center.
Notes¶
Parameter names are different from the regular class constructor due to historical reasons and semi-backwards compatibility.
- plotly_debug()[source]¶
Plot the ROI against the image array along with highlighting of the pixels within the ROI.
Useful for debugging and visualizing the ROI.
- property masked_array: ndarray¶
A 2D array the same shape as the underlying image array, with the pixels within the ROI set to their pixel values, and the rest set to NaN.
This can be useful for plotting. We can also calculate non-spatial statistics on this array, but requires using special functions like np.nanmean() or np.nanstd().
It’s better to calculate statistics on the pixels_flat property, which is always available.
- property pixels_flat: ndarray¶
A flattened array of the pixel values within the ROI.
This is always available, even for rotated ROIs. However, it is flattened, so spatial statistics cannot be calculated.
- property pixel_array: ndarray¶
A 2D array of the pixel values within the ROI. Only available for non-rotated ROIs.
Raises¶
- ValueError
If the rotation is != 0, the array cannot be reshaped into a 2D array.
- property pixel_value: float¶
The pixel array within the ROI.
- property mean: float¶
The mean value within the ROI.
- property std: float¶
The std within the ROI.
- property min: float¶
The min value within the ROI.
- property max: float¶
The max value within the ROI.
Mask Module¶
Module for processing “masked” arrays, i.e. binary images.
Utilities Module¶
Utility functions for pylinac.
- pylinac.core.utilities.convert_to_enum(value: str | Enum | None, enum: type[Enum]) Enum[source]¶
Convert a value to an enum representation from an enum value if needed
- class pylinac.core.utilities.OptionListMixin[source]¶
Bases:
objectA mixin class that will create a list of the class attributes. Used for enum-like classes
- pydantic model pylinac.core.utilities.ResultBase[source]¶
Bases:
BaseModelCreate a new model by parsing and validating input data from keyword arguments.
Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.
self is explicitly positional-only to allow self as a field name.
- field pylinac_version: str = '3.36.0'¶
The version of Pylinac used for the analysis.
- field date_of_analysis: datetime [Optional]¶
The date the analysis was performed.
- field warnings: list[dict] [Optional]¶
Code warnings that occurred during the analysis.
- class pylinac.core.utilities.ResultsDataMixin(*args, **kwargs)[source]¶
Bases:
Generic[T],WarningCollectorMixinA mixin for classes that generate results data. This mixin is used to generate the results data and present it in different formats. The generic types allow correct type hinting of the results data.
- results_data(as_dict: bool = False, as_json: bool = False, by_alias: bool = False, exclude: set[str] | None = None) T | dict | str[source]¶
Present the results data and metadata as a dataclass, dict, or tuple. The default return type is a dataclass.
Parameters¶
- as_dictbool
If True, return the results as a dictionary.
- as_jsonbool
If True, return the results as a JSON string. Cannot be True if as_dict is True.
- by_aliasbool
If True, use the alias names of the dataclass fields. These are generally the more human-readable names.
- excludeset
A set of fields to exclude from the results data.
- pylinac.core.utilities.clear_data_files()[source]¶
Delete all demo files, image classifiers, etc from the demo folder
- pylinac.core.utilities.assign2machine(source_file: str, machine_file: str)[source]¶
Assign a DICOM RT Plan file to a specific machine. The source file is overwritten to contain the machine of the machine file.
Parameters¶
- source_filestr
Path to the DICOM RTPlan file that contains the fields/plan desired (e.g. a Winston Lutz set of fields or Varian’s default PF files).
- machine_filestr
Path to a DICOM RTPlan file that has the desired machine. This is easily obtained from pushing a plan from the TPS for that specific machine. The file must contain at least one valid field.
- pylinac.core.utilities.is_close(val: float, target: float | Sequence, delta: float = 1)[source]¶
Return whether the value is near the target value(s).
Parameters¶
- valnumber
The value being compared against.
- targetnumber, iterable
If a number, the values are simply evaluated. If a sequence, each target is compared to
val. If any values oftargetare close, the comparison is considered True.
Returns¶
bool
- pylinac.core.utilities.is_close_degrees(angle1: float, angle2: float, delta: float = 1) bool[source]¶
A sister function to is_close that takes into account the circular nature of degrees.
Parameters¶
- angle1float
The first angle in degrees.
- angle2float
The second angle in degrees.
- deltafloat
The maximum difference allowed between the angles in degrees
- pylinac.core.utilities.simple_round(number: float | int, decimals: int | None = 0) float | int[source]¶
Round a number to the given number of decimals. Fixes small floating number errors. If decimals is None, no rounding is performed
- class pylinac.core.utilities.TemporaryAttribute(cls, attribute_name, temporary_value)[source]¶
Bases:
objectContext manager to temporarily set a class attribute.
- class pylinac.core.utilities.Structure(**kwargs)[source]¶
Bases:
objectA simple structure that assigns the arguments to the object.
- pylinac.core.utilities.decode_binary(file: BinaryIO, dtype: type[int] | type[float] | type[str] | str | dtype, num_values: int = 1, cursor_shift: int = 0, strip_empty: bool = True) int | float | str | ndarray | list[source]¶
Read in a raw binary file and convert it to given data types.
Parameters¶
- file
The open file object.
- dtype
The expected data type to return. If int or float and num_values > 1, will return numpy array.
- num_values
The expected number of dtype to return
Note
This is not the same as the number of bytes.
- cursor_shiftint
The number of bytes to move the cursor forward after decoding. This is used if there is a reserved section after the read-in segment.
- strip_emptybool
Whether to strip trailing empty/null values for strings.
- class pylinac.core.utilities.QuaacDatum(value: str | float | int, unit: str = '', description: str = '', reference_value: str | float | int | None = None)[source]¶
Bases:
objectIndividual data point to be saved to a QuAAC file.
- class pylinac.core.utilities.QuaacMixin[source]¶
Bases:
objectA mixin for pylinac analysis classes to save results to a QuAAC file.
- to_quaac(path: str | Path, performer: User, primary_equipment: Equipment, format: Literal['json', 'yaml'] = 'yaml', attachments: list[Attachment] | None = None, overwrite: bool = False, **kwargs) None[source]¶
Write an analysis to a QuAAC file. This will include the items from results_data() and the PDF report.
Parameters¶
- pathstr, Path
The file to write the results to.
- performerUser
The user who performed the analysis.
- primary_equipmentEquipment
The equipment used in the analysis.
- format{‘json’, ‘yaml’}
The format to write the file in.
- attachmentslist of Attachment
Additional attachments to include in the QuAAC file.
- overwritebool
Whether to overwrite the file if it already exists.
- kwargs
Additional keyword arguments to pass to the Document instantiation.