Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
@value_accept(kind=('median', 'gaussian'))
def filter(self, size: NumberLike=0.05, kind: str='median'):
"""Filter the profile.
Parameters
----------
size : float, int
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.
"""
if isinstance(size, float):
if 0 < size < 1:
size = int(round(len(self.values)*size))
@value_accept(side=(LEFT, RIGHT), kind=(VALUE, INDEX))
@lru_cache()
def _penumbra_point(self, side: str='left', x: int=50, interpolate: bool=False, kind: str='index'):
"""Return the index of the given penumbra. Search starts at the peak and moves index-by-index
outward until the penumbra value is hit.
Parameters
----------
side : {'left', 'right'}
Which side to look for the penumbra.
x : int
The penumbra value to search for. E.g. if passed 20, the method finds
the index of 0.2*max profile value.
interpolate : bool
Whether to interpolate the profile array values to get subpixel precision.
kind : {'value', 'index'}
What kind of return is given. If 'index' (default), returns the *index* of the point
@value_accept(kind=(INDEX, VALUE))
def find_peaks(self, threshold: Union[float, int]=0.3, min_distance: Union[float, int]=0.05, max_number: int=None,
search_region: Tuple=(0.0, 1.0), kind: str='index') -> np.ndarray:
"""Find the peaks of the profile using a simple maximum value search. This also sets the `peaks` attribute.
Parameters
----------
threshold : int, float
The value the peak must be above to be considered a peak. This removes "peaks"
that are in a low-value region.
If passed an int, the actual value is the threshold.
E.g. when passed 15, any peak less with a value <15 is removed.
If passed a float, it will threshold as a percent. Must be between 0 and 1.
E.g. when passed 0.4, any peak <40% of the maximum value will be removed.
min_distance : int, float
If passed an int, parameter is the number of elements apart a peak must be from neighboring peaks.
If passed a float, must be between 0 and 1 and represents the ratio of the profile to exclude.
@value_accept(mode=('mean', 'median', 'max'))
def combine_surrounding_slices(dicomstack, nominal_slice_num, slices_plusminus=1, mode='mean'):
"""Return an array that is the combination of a given slice and a number of slices surrounding it.
Parameters
----------
dicomstack : `~pylinac.core.image.DicomImageStack`
The CBCT DICOM stack.
nominal_slice_num : int
The slice of interest (along 3rd dim).
slices_plusminus: int
How many slices plus and minus to combine (also along 3rd dim).
mode : {'mean', 'median', 'max}
Specifies the method of combination.
Returns
-------
@value_accept(kind=('median', 'gaussian'))
def filter(self, size: Union[float, int]=0.05, kind: str='median'):
"""Filter the profile.
Parameters
----------
size : int, 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.
"""
if isinstance(size, float):
if 0 < size < 1:
size *= len(self.array)
@value_accept(tolerance=(0, 8))
def analyze(self, tolerance: Union[float, int]=1.5):
"""Analyze the open and DMLC field VMAT images, according to 1 of 2 possible tests.
Parameters
----------
tolerance : float, int, optional
The tolerance of the sample deviations in percent. Default is 1.5.
Must be between 0 and 8.
"""
self._tolerance = tolerance/100
"""Analysis"""
points = self._calculate_segment_centers()
self._construct_segments(points)
@value_accept(x=(0, 100))
def find_fwxm_peaks(self, x:int =50, threshold: Union[float, int]=0.3, min_distance: Union[float, int]=0.05,
max_number: int=None, search_region: Tuple=(0.0, 1.0), kind: str='index',
interpolate: bool=False, interpolation_factor: int=100, interpolation_type: str='linear') -> List:
"""Find peaks using the center of the FWXM (rather than by max value).
Parameters
----------
x : int, float
The Full-Width-X-Maximum desired. E.g. 0.7 will return the FW70%M.
Values must be between 0 and 100.
interpolate : bool
Whether to interpolate the profile to determine a more accurate peak location.
interpolation_factor : int
The interpolation multiplication factor. E.g. if 10, the profile is interpolated to have 10x the number
of values. Only used if `interpolate` is True.
interpolation_type : {'linear', 'cubic'}
@value_accept(radius=(0.2, 0.95), min_peak_height=(0.05, 0.95))
def analyze(self, radius: float=0.85, min_peak_height: float=0.25, tolerance: float=1.0,
start_point: Point=None, fwhm: bool=True, recursive: bool=True, invert=False):
"""Analyze the starshot image.
Analyze finds the minimum radius and center of a circle that touches all the lines
(i.e. the wobble circle diameter and wobble center).
Parameters
----------
radius : float, optional
Distance in % between starting point and closest image edge; used to build the circular profile which finds
the radiation lines. Must be between 0.05 and 0.95.
min_peak_height : float, optional
The percentage minimum height a peak must be to be considered a valid peak. A lower value catches
radiation peaks that vary in magnitude (e.g. different MU delivered or gantry shot), but could also pick up noise.
If necessary, lower value for gantry shots and increase for noisy images.
@value_accept(field_width=(0, 1))
def field_values(self, field_width: float=0.8) -> np.ndarray:
"""Return a subarray of the values of the profile for the given field width.
This is helpful for doing, e.g., flatness or symmetry calculations, where you
want to calculate something over the field, not the whole profile.
Parameters
----------
field_width : float
The field width of the profile, based on the fwhm. Must be between 0 and 1.
Returns
-------
ndarray
"""
left, right = self.field_edges(field_width)
field_values = self.values[left:right]
@value_accept(subimage=(DMLC, OPEN, PROFILE))
def _save_analyzed_subimage(self, filename: str, subimage: str, **kwargs):
"""Save the analyzed images as a png file.
Parameters
----------
filename : str, file-object
Where to save the file to.
kwargs
Passed to matplotlib.
"""
self._plot_analyzed_subimage(subimage=subimage, show=False)
plt.savefig(filename, **kwargs)