#You can ignore this class, it is just a subclass of SizedDiskLocator to plot a number next to each ROI
class CustomSizedDiskLocator(SizedDiskLocator):
def set_numero(self,value):
self.numero=value
def plot(self, axis: plt.Axes, show_boundaries: bool = True, color: str = "red", markersize: float = 3, alpha: float = 0.25) -> None:
"""Plot the BB center"""
for point in self.points:
axis.text(point.x, point.y, f"{self.numero}", color=color, fontsize=10)
axis.plot(point.x, point.y, color=color, marker="o", alpha=1, markersize=markersize)
img_path=r"OTP-EPID_qualiformed_path.dcm"
img= DicomImage(img_path)
liste_metrics=[CustomSizedDiskLocator.from_center_physical(
expected_position_mm=Point(x=0, y=0, z=0.00),
search_window_mm=(5,5),
radius_mm=1.2,
radius_tolerance_mm=0.3,
invert=False,
),
CustomSizedDiskLocator.from_center_physical(
expected_position_mm=Point(x=24, y=0, z=0.00),
search_window_mm=(5,5),
radius_mm=1.2,
radius_tolerance_mm=0.4,
invert=False
)
]
for i, metric in enumerate(liste_metrics):
metric.set_numero(i)
results_metrics=img.compute(liste_metrics)
print(results_metrics)
img.plot()
This plots all the points I want, but it only prints this: {‘Disk Region’: [Point(x=860.14, y=38.11, z=0.00)]} (I expect it to print 2 points)
Is there a way to get all the points printed without messing too much with pylinac’s code ?
class customBaseImage(BaseImage):
def customCompute(self, metrics: list[MetricBase] | MetricBase) -> Any | dict[str, Any]:
"""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 ``metrics`` attribute.
The ``metrics`` attribute will store all metrics every calculated.
The metrics returned are only those passed in the ``metrics`` argument.
Parameters
----------
metrics : list[MetricBase] | MetricBase
The metric(s) to compute.
"""
metric_data = {}
if isinstance(metrics, MetricBase):
metrics = [metrics]
for i, metric in enumerate(metrics):
metric.inject_image(self)
value = metric.context_calculate()
self.metrics.append(metric)
metric_data[f"{metric.name}{i}"] = value
# TODO: use |= when 3.9 is min supported version
self.metric_values.update(metric_data)
if len(metrics) == 1:
return metric_data[f"{metrics[0].name}{0}"]
return metric_data
This works fine but it is a bit fastidious because to use this function I need my image to be an object that derives from customBaseImage, so I have to change quite a lot of things in my script. My issue is solved but if anyone with a better level in python knows an elegant solution I would be happy to hear it
The names of the metrics have to be different. I didn’t realize this until digging in. The name is some default value. If it’s the same, it will be overwritten. I’ll have to figure out how to avoid doing this.
To work around this, you should be able to do:
liste_metrics=[CustomSizedDiskLocator.from_center_physical(
expected_position_mm=Point(x=0, y=0, z=0.00),
search_window_mm=(5,5),
radius_mm=1.2,
radius_tolerance_mm=0.3,
invert=False,
name="metric 1" # note the name
),
CustomSizedDiskLocator.from_center_physical(
expected_position_mm=Point(x=24, y=0, z=0.00),
search_window_mm=(5,5),
radius_mm=1.2,
radius_tolerance_mm=0.4,
invert=False,
name="metric 2" # different name
)
]