mediml 0.9.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- MEDiml/MEDscan.py +1696 -0
- MEDiml/__init__.py +21 -0
- MEDiml/biomarkers/BatchExtractor.py +806 -0
- MEDiml/biomarkers/BatchExtractorTexturalFilters.py +840 -0
- MEDiml/biomarkers/__init__.py +16 -0
- MEDiml/biomarkers/diagnostics.py +125 -0
- MEDiml/biomarkers/get_oriented_bound_box.py +158 -0
- MEDiml/biomarkers/glcm.py +1602 -0
- MEDiml/biomarkers/gldzm.py +523 -0
- MEDiml/biomarkers/glrlm.py +1315 -0
- MEDiml/biomarkers/glszm.py +555 -0
- MEDiml/biomarkers/int_vol_hist.py +527 -0
- MEDiml/biomarkers/intensity_histogram.py +615 -0
- MEDiml/biomarkers/local_intensity.py +89 -0
- MEDiml/biomarkers/morph.py +1756 -0
- MEDiml/biomarkers/ngldm.py +780 -0
- MEDiml/biomarkers/ngtdm.py +414 -0
- MEDiml/biomarkers/stats.py +373 -0
- MEDiml/biomarkers/utils.py +389 -0
- MEDiml/filters/TexturalFilter.py +299 -0
- MEDiml/filters/__init__.py +9 -0
- MEDiml/filters/apply_filter.py +134 -0
- MEDiml/filters/gabor.py +215 -0
- MEDiml/filters/laws.py +283 -0
- MEDiml/filters/log.py +147 -0
- MEDiml/filters/mean.py +121 -0
- MEDiml/filters/textural_filters_kernels.py +1738 -0
- MEDiml/filters/utils.py +107 -0
- MEDiml/filters/wavelet.py +237 -0
- MEDiml/learning/DataCleaner.py +198 -0
- MEDiml/learning/DesignExperiment.py +480 -0
- MEDiml/learning/FSR.py +667 -0
- MEDiml/learning/Normalization.py +112 -0
- MEDiml/learning/RadiomicsLearner.py +714 -0
- MEDiml/learning/Results.py +2237 -0
- MEDiml/learning/Stats.py +694 -0
- MEDiml/learning/__init__.py +10 -0
- MEDiml/learning/cleaning_utils.py +107 -0
- MEDiml/learning/ml_utils.py +1015 -0
- MEDiml/processing/__init__.py +6 -0
- MEDiml/processing/compute_suv_map.py +121 -0
- MEDiml/processing/discretisation.py +149 -0
- MEDiml/processing/interpolation.py +275 -0
- MEDiml/processing/resegmentation.py +66 -0
- MEDiml/processing/segmentation.py +912 -0
- MEDiml/utils/__init__.py +25 -0
- MEDiml/utils/batch_patients.py +45 -0
- MEDiml/utils/create_radiomics_table.py +131 -0
- MEDiml/utils/data_frame_export.py +42 -0
- MEDiml/utils/find_process_names.py +16 -0
- MEDiml/utils/get_file_paths.py +34 -0
- MEDiml/utils/get_full_rad_names.py +21 -0
- MEDiml/utils/get_institutions_from_ids.py +16 -0
- MEDiml/utils/get_patient_id_from_scan_name.py +22 -0
- MEDiml/utils/get_patient_names.py +26 -0
- MEDiml/utils/get_radiomic_names.py +27 -0
- MEDiml/utils/get_scan_name_from_rad_name.py +22 -0
- MEDiml/utils/image_reader_SITK.py +37 -0
- MEDiml/utils/image_volume_obj.py +22 -0
- MEDiml/utils/imref.py +340 -0
- MEDiml/utils/initialize_features_names.py +62 -0
- MEDiml/utils/inpolygon.py +159 -0
- MEDiml/utils/interp3.py +43 -0
- MEDiml/utils/json_utils.py +78 -0
- MEDiml/utils/mode.py +31 -0
- MEDiml/utils/parse_contour_string.py +58 -0
- MEDiml/utils/save_MEDscan.py +30 -0
- MEDiml/utils/strfind.py +32 -0
- MEDiml/utils/textureTools.py +188 -0
- MEDiml/utils/texture_features_names.py +115 -0
- MEDiml/utils/write_radiomics_csv.py +47 -0
- MEDiml/wrangling/DataManager.py +1724 -0
- MEDiml/wrangling/ProcessDICOM.py +512 -0
- MEDiml/wrangling/__init__.py +3 -0
- mediml-0.9.9.dist-info/LICENSE.md +674 -0
- mediml-0.9.9.dist-info/METADATA +232 -0
- mediml-0.9.9.dist-info/RECORD +78 -0
- mediml-0.9.9.dist-info/WHEEL +4 -0
MEDiml/filters/log.py
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from itertools import product
|
|
3
|
+
from typing import Union
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
from ..MEDscan import MEDscan
|
|
8
|
+
from ..utils.image_volume_obj import image_volume_obj
|
|
9
|
+
from .utils import convolve
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class LaplacianOfGaussian():
|
|
13
|
+
"""The Laplacian of gaussian filter class."""
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
ndims: int,
|
|
18
|
+
size: int,
|
|
19
|
+
sigma: float=0.1,
|
|
20
|
+
padding: str="symmetric"):
|
|
21
|
+
"""The constructor of the laplacian of gaussian (LoG) filter
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
ndims (int): Number of dimension of the kernel filter
|
|
25
|
+
size (int): An integer that represent the length along one dimension of the kernel.
|
|
26
|
+
sigma (float): The gaussian standard deviation parameter of the laplacian of gaussian filter
|
|
27
|
+
padding (str): The padding type that will be used to produce the convolution
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
None
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
assert isinstance(ndims, int) and ndims > 0, "ndims should be a positive integer"
|
|
34
|
+
assert ((size+1)/2).is_integer() and size > 0, "size should be a positive odd number."
|
|
35
|
+
assert sigma > 0, "alpha should be a positive float."
|
|
36
|
+
|
|
37
|
+
self.dim = ndims
|
|
38
|
+
self.padding = padding
|
|
39
|
+
self.size = int(size)
|
|
40
|
+
self.sigma = sigma
|
|
41
|
+
self.create_kernel()
|
|
42
|
+
|
|
43
|
+
def create_kernel(self) -> np.ndarray:
|
|
44
|
+
"""This method construct the LoG kernel using the parameters specified to the constructor
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
ndarray: The laplacian of gaussian kernel as a numpy multidimensional array
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def compute_weight(position):
|
|
51
|
+
distance_2 = np.sum(position**2)
|
|
52
|
+
# $\frac{-1}{\sigma^2} * \frac{1}{\sqrt{2 \pi} \sigma}^D = \frac{-1}{\sqrt{D/2}{2 \pi} * \sigma^{D+2}}$
|
|
53
|
+
first_part = -1/((2*math.pi)**(self.dim/2) * self.sigma**(self.dim+2))
|
|
54
|
+
|
|
55
|
+
# $(D - \frac{||k||^2}{\sigma^2}) * e^{\frac{-||k||^2}{2 \sigma^2}}$
|
|
56
|
+
second_part = (self.dim - distance_2/self.sigma**2)*math.e**(-distance_2/(2 * self.sigma**2))
|
|
57
|
+
|
|
58
|
+
return first_part * second_part
|
|
59
|
+
|
|
60
|
+
# Initialize the kernel as tensor of zeros
|
|
61
|
+
kernel = np.zeros([self.size for _ in range(self.dim)])
|
|
62
|
+
|
|
63
|
+
for k in product(range(self.size), repeat=self.dim):
|
|
64
|
+
kernel[k] = compute_weight(np.array(k)-int((self.size-1)/2))
|
|
65
|
+
|
|
66
|
+
kernel -= np.sum(kernel)/np.prod(kernel.shape)
|
|
67
|
+
self.kernel = np.expand_dims(kernel, axis=(0, 1))
|
|
68
|
+
|
|
69
|
+
def convolve(self,
|
|
70
|
+
images: np.ndarray,
|
|
71
|
+
orthogonal_rot=False) -> np.ndarray:
|
|
72
|
+
"""Filter a given image using the LoG kernel defined during the construction of this instance.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
images (ndarray): A n-dimensional numpy array that represent the images to filter
|
|
76
|
+
orthogonal_rot (bool): If true, the 3D images will be rotated over coronal, axial and sagittal axis
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
ndarray: The filtered image
|
|
80
|
+
"""
|
|
81
|
+
# Swap the second axis with the last, to convert image B, W, H, D --> B, D, H, W
|
|
82
|
+
image = np.swapaxes(images, 1, 3)
|
|
83
|
+
result = np.squeeze(convolve(self.dim, self.kernel, image, orthogonal_rot, self.padding), axis=1)
|
|
84
|
+
return np.swapaxes(result, 1, 3)
|
|
85
|
+
|
|
86
|
+
def apply_log(
|
|
87
|
+
input_images: Union[np.ndarray, image_volume_obj],
|
|
88
|
+
medscan: MEDscan = None,
|
|
89
|
+
ndims: int = 3,
|
|
90
|
+
voxel_length: float = 0.0,
|
|
91
|
+
sigma: float = 0.1,
|
|
92
|
+
padding: str = "symmetric",
|
|
93
|
+
orthogonal_rot: bool = False
|
|
94
|
+
) -> np.ndarray:
|
|
95
|
+
"""Apply the mean filter to the input image
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
input_images (ndarray): The images to filter.
|
|
99
|
+
medscan (MEDscan, optional): The MEDscan object that will provide the filter parameters.
|
|
100
|
+
ndims (int, optional): The number of dimensions of the input image.
|
|
101
|
+
voxel_length (float, optional): The voxel size of the input image.
|
|
102
|
+
sigma (float, optional): standard deviation of the Gaussian, controls the scale of the convolutional operator.
|
|
103
|
+
padding (str, optional): The padding type that will be used to produce the convolution.
|
|
104
|
+
Check options here: `numpy.pad <https://numpy.org/doc/stable/reference/generated/numpy.pad.html>`__.
|
|
105
|
+
orthogonal_rot (bool, optional): If true, the 3D images will be rotated over coronal, axial and sagittal axis.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
ndarray: The filtered image.
|
|
109
|
+
"""
|
|
110
|
+
# Check if the input is a numpy array or a Image volume object
|
|
111
|
+
spatial_ref = None
|
|
112
|
+
if type(input_images) == image_volume_obj:
|
|
113
|
+
spatial_ref = input_images.spatialRef
|
|
114
|
+
input_images = input_images.data
|
|
115
|
+
|
|
116
|
+
# Convert to shape : (B, W, H, D)
|
|
117
|
+
input_images = np.expand_dims(input_images.astype(np.float64), axis=0)
|
|
118
|
+
|
|
119
|
+
if medscan:
|
|
120
|
+
# Initialize filter class params & instance
|
|
121
|
+
sigma = medscan.params.filter.log.sigma / voxel_length
|
|
122
|
+
length = 2 * int(4 * sigma + 0.5) + 1
|
|
123
|
+
_filter = LaplacianOfGaussian(
|
|
124
|
+
ndims=medscan.params.filter.log.ndims,
|
|
125
|
+
size=length,
|
|
126
|
+
sigma=sigma,
|
|
127
|
+
padding=medscan.params.filter.log.padding
|
|
128
|
+
)
|
|
129
|
+
# Run convolution
|
|
130
|
+
result = _filter.convolve(input_images, orthogonal_rot=medscan.params.filter.log.orthogonal_rot)
|
|
131
|
+
else:
|
|
132
|
+
# Initialize filter class params & instance
|
|
133
|
+
sigma = sigma / voxel_length
|
|
134
|
+
length = 2 * int(4 * sigma + 0.5) + 1
|
|
135
|
+
_filter = LaplacianOfGaussian(
|
|
136
|
+
ndims=ndims,
|
|
137
|
+
size=length,
|
|
138
|
+
sigma=sigma,
|
|
139
|
+
padding=padding
|
|
140
|
+
)
|
|
141
|
+
# Run convolution
|
|
142
|
+
result = _filter.convolve(input_images, orthogonal_rot=orthogonal_rot)
|
|
143
|
+
|
|
144
|
+
if spatial_ref:
|
|
145
|
+
return image_volume_obj(np.squeeze(result), spatial_ref)
|
|
146
|
+
else:
|
|
147
|
+
return np.squeeze(result)
|
MEDiml/filters/mean.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
from abc import ABC
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from ..MEDscan import MEDscan
|
|
7
|
+
from ..utils.image_volume_obj import image_volume_obj
|
|
8
|
+
from .utils import convolve
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Mean():
|
|
12
|
+
"""The mean filter class"""
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
ndims: int,
|
|
17
|
+
size: int,
|
|
18
|
+
padding="symmetric"):
|
|
19
|
+
"""The constructor of the mean filter
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
ndims (int): Number of dimension of the kernel filter
|
|
23
|
+
size (int): An integer that represent the length along one dimension of the kernel.
|
|
24
|
+
padding: The padding type that will be used to produce the convolution
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
None
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
assert isinstance(ndims, int) and ndims > 0, "ndims should be a positive integer"
|
|
31
|
+
assert ((size+1)/2).is_integer() and size > 0, "size should be a positive odd number."
|
|
32
|
+
|
|
33
|
+
self.padding = padding
|
|
34
|
+
self.dim = ndims
|
|
35
|
+
self.size = int(size)
|
|
36
|
+
self.create_kernel()
|
|
37
|
+
|
|
38
|
+
def create_kernel(self):
|
|
39
|
+
"""This method construct the mean kernel using the parameters specified to the constructor.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
ndarray: The mean kernel as a numpy multidimensional array
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
# Initialize the kernel as tensor of zeros
|
|
46
|
+
weight = 1 / np.prod(self.size ** self.dim)
|
|
47
|
+
kernel = np.ones([self.size for _ in range(self.dim)]) * weight
|
|
48
|
+
|
|
49
|
+
self.kernel = np.expand_dims(kernel, axis=(0, 1))
|
|
50
|
+
|
|
51
|
+
def convolve(self,
|
|
52
|
+
images: np.ndarray,
|
|
53
|
+
orthogonal_rot: bool = False)-> np.ndarray:
|
|
54
|
+
"""Filter a given image using the LoG kernel defined during the construction of this instance.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
images (ndarray): A n-dimensional numpy array that represent the images to filter
|
|
58
|
+
orthogonal_rot (bool, optional): If true, the 3D images will be rotated over coronal, axial and sagittal axis
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
ndarray: The filtered image
|
|
62
|
+
"""
|
|
63
|
+
# Swap the second axis with the last, to convert image B, W, H, D --> B, D, H, W
|
|
64
|
+
image = np.swapaxes(images, 1, 3)
|
|
65
|
+
result = np.squeeze(convolve(self.dim, self.kernel, image, orthogonal_rot, self.padding), axis=1)
|
|
66
|
+
return np.swapaxes(result, 1, 3)
|
|
67
|
+
|
|
68
|
+
def apply_mean(
|
|
69
|
+
input_images: Union[np.ndarray, image_volume_obj],
|
|
70
|
+
medscan: MEDscan = None,
|
|
71
|
+
ndims: int = 3,
|
|
72
|
+
size: int = 15,
|
|
73
|
+
padding: str = "symmetric",
|
|
74
|
+
orthogonal_rot: bool = False
|
|
75
|
+
) -> np.ndarray:
|
|
76
|
+
"""Apply the mean filter to the input image
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
input_images (ndarray): The images to filter.
|
|
80
|
+
medscan (MEDscan, optional): The MEDscan object that will provide the filter parameters.
|
|
81
|
+
ndims (int, optional): The number of dimensions of the input image.
|
|
82
|
+
size (int, optional): The size of the kernel.
|
|
83
|
+
padding (str, optional): The padding type that will be used to produce the convolution.
|
|
84
|
+
Check options here: `numpy.pad <https://numpy.org/doc/stable/reference/generated/numpy.pad.html>`__.
|
|
85
|
+
orthogonal_rot (bool, optional): If true, the 3D images will be rotated over coronal, axial and sagittal axis.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
ndarray: The filtered image.
|
|
89
|
+
"""
|
|
90
|
+
# Check if the input is a numpy array or a Image volume object
|
|
91
|
+
spatial_ref = None
|
|
92
|
+
if type(input_images) == image_volume_obj:
|
|
93
|
+
spatial_ref = input_images.spatialRef
|
|
94
|
+
input_images = input_images.data
|
|
95
|
+
|
|
96
|
+
# Convert to shape : (B, W, H, D)
|
|
97
|
+
input_images = np.expand_dims(input_images.astype(np.float64), axis=0)
|
|
98
|
+
|
|
99
|
+
if medscan:
|
|
100
|
+
# Initialize filter class instance
|
|
101
|
+
_filter = Mean(
|
|
102
|
+
ndims=medscan.params.filter.mean.ndims,
|
|
103
|
+
size=medscan.params.filter.mean.size,
|
|
104
|
+
padding=medscan.params.filter.mean.padding
|
|
105
|
+
)
|
|
106
|
+
# Run convolution
|
|
107
|
+
result = _filter.convolve(input_images, orthogonal_rot=medscan.params.filter.mean.orthogonal_rot)
|
|
108
|
+
else:
|
|
109
|
+
# Initialize filter class instance
|
|
110
|
+
_filter = Mean(
|
|
111
|
+
ndims=ndims,
|
|
112
|
+
size=size,
|
|
113
|
+
padding=padding,
|
|
114
|
+
)
|
|
115
|
+
# Run convolution
|
|
116
|
+
result = _filter.convolve(input_images, orthogonal_rot=orthogonal_rot)
|
|
117
|
+
|
|
118
|
+
if spatial_ref:
|
|
119
|
+
return image_volume_obj(np.squeeze(result), spatial_ref)
|
|
120
|
+
else:
|
|
121
|
+
return np.squeeze(result)
|