Source code for patato.utils.roi_operations

#  Copyright (c) Thomas Else 2023-25.
#  License: MIT

from collections import defaultdict
from typing import TYPE_CHECKING, Tuple

import numpy as np

if TYPE_CHECKING:
    from ..io.msot_data import PAData
    from .rois.roi_type import ROI

import matplotlib


[docs] def split_roi_left_right(data: "PAData", base_roi="", split_template="unnamed"): from .rois.roi_type import ROI # Initial implementation - only supports one "dividing" roi. data_rois = data.get_rois() template_data = None names = None if (split_template + "_left", "0") in data_rois: template_data = data_rois[(split_template + "_left", "0")] names = ["left", "right"] elif (split_template + "_right", "0") in data_rois: template_data = data_rois[(split_template + "_right", "0")] names = ["right", "left"] else: return [] template_polygon = template_data.get_polygon() output = [] for (name, number), roi in data_rois.items(): if roi.position != "" or roi.generated: continue if base_roi in name: # Process base_polygon = roi.get_polygon() base_region_a = base_polygon & template_polygon base_region_b = base_polygon - base_region_a # Convert to numpy array try: x, y = base_region_a.exterior.coords.xy region_a = np.array([x[:-1], y[:-1]]).T x, y = base_region_b.exterior.coords.xy region_b = np.array([x[:-1], y[:-1]]).T except AttributeError: continue # Get the metadata. z_position = roi.z run = roi.run repetition = roi.repetition roi_class = roi.roi_class roi_a = ROI(region_a, z_position, run, repetition, roi_class, names[0]) roi_b = ROI(region_b, z_position, run, repetition, roi_class, names[1]) output.append(roi_a) output.append(roi_b) return output
ROI_NAMES = [ "brain", "body", "reference", "aorta", "tumour", "background", "artery", "vein", "muscle", "phantom", "unnamed", "kidney", "spleen", "spine", "skin", "fat", ] REGION_COLOURS = matplotlib.cm.hsv(np.linspace(0, 1, len(ROI_NAMES))) REGION_COLOUR_MAP = defaultdict(lambda: REGION_COLOURS[-1]) for x, y in zip(ROI_NAMES, REGION_COLOURS): REGION_COLOUR_MAP[x] = y
[docs] def close_loop(x): return np.concatenate([x, x[0:1, :]])
[docs] def get_rim_core_rois(roi_data: "ROI", distance: float, radius=False): from ..io.msot_data import ROI roi = roi_data.get_polygon() if radius: effective_radius = np.sqrt(roi.area / np.pi) # distance is the desired radius distance = -distance + effective_radius roi_buffer = roi.buffer(-distance) core_roi = ROI( roi_buffer, roi_data.z, roi_data.run, roi_data.repetition, roi_data.roi_class + ".core", roi_data.position, generated=True, ax0_index=roi_data.ax0_index, ) rim_roi = ROI( roi - roi_buffer, roi_data.z, roi_data.run, roi_data.repetition, roi_data.roi_class + ".rim", roi_data.position, generated=True, ax0_index=roi_data.ax0_index, ) return core_roi, rim_roi
[docs] def add_rim_core_data( data: "PAData", base_roi: Tuple[str, str], distance: float, radius=False ): roi_data: "ROI" = data.get_rois()[base_roi] return get_rim_core_rois(roi_data, distance, radius)