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
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
import logging
|
|
5
|
+
from typing import Dict, Tuple
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from ..biomarkers.utils import find_i_x, find_v_x
|
|
10
|
+
from ..MEDscan import MEDscan
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def init_ivh(
|
|
14
|
+
vol: np.ndarray,
|
|
15
|
+
vol_int_re: np.ndarray,
|
|
16
|
+
wd: int,
|
|
17
|
+
ivh: Dict = None,
|
|
18
|
+
im_range: np.ndarray = None,
|
|
19
|
+
medscan: MEDscan = None
|
|
20
|
+
) -> Tuple[np.ndarray, np.ndarray, int, int]:
|
|
21
|
+
"""Computes Intensity-volume Histogram Features.
|
|
22
|
+
|
|
23
|
+
Note:
|
|
24
|
+
For the input volume:
|
|
25
|
+
|
|
26
|
+
- Naturally discretised volume can be kept as it is (e.g. HU values of CT scans)
|
|
27
|
+
- All other volumes with continuous intensity distribution should be \
|
|
28
|
+
quantized (e.g., nBins = 100), with levels = [min, ..., max]
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
vol (ndarray): 3D volume, QUANTIZED, with NaNs outside the region of interest
|
|
32
|
+
vol_int_re (ndarray): 3D volume, with NaNs outside the region of interest
|
|
33
|
+
wd (int): Discretisation width.
|
|
34
|
+
ivh (Dict, optional): Dict of the Intensity-volume Histogram parameters (Discretization algo and value).
|
|
35
|
+
im_range (ndarray, optional): The intensity range.
|
|
36
|
+
medscan (MEDscan, optional): MEDscan instance containing processing parameters.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Dict: Dict of the Intensity Histogram Features.
|
|
40
|
+
"""
|
|
41
|
+
try:
|
|
42
|
+
# Retrieve relevant parameters from MEDscan instance.
|
|
43
|
+
if medscan is not None:
|
|
44
|
+
ivh = medscan.params.process.ivh
|
|
45
|
+
im_range = medscan.params.process.im_range
|
|
46
|
+
elif ivh is None or im_range is None:
|
|
47
|
+
raise ValueError('MEDscan instance or ivh and im_range must be provided.')
|
|
48
|
+
|
|
49
|
+
# Initialize relevant parameters.
|
|
50
|
+
user_set_range = []
|
|
51
|
+
if ivh and 'type' in ivh:
|
|
52
|
+
# PET example case (definite intensity units -- continuous case)
|
|
53
|
+
if ivh['type'] == 'FBS' or ivh['type'] == 'FBSequal':
|
|
54
|
+
range_fbs = [0, 0]
|
|
55
|
+
if not im_range:
|
|
56
|
+
range_fbs[0] = np.nanmin(vol_int_re)
|
|
57
|
+
range_fbs[1] = np.nanmax(vol_int_re)
|
|
58
|
+
else:
|
|
59
|
+
if im_range[0] == -np.inf:
|
|
60
|
+
range_fbs[0] = np.nanmin(vol_int_re)
|
|
61
|
+
else:
|
|
62
|
+
range_fbs[0] = im_range[0]
|
|
63
|
+
if im_range[1] == np.inf:
|
|
64
|
+
range_fbs[1] = np.nanmax(vol_int_re)
|
|
65
|
+
else:
|
|
66
|
+
range_fbs[1] = im_range[1]
|
|
67
|
+
# In this case, wd = wb (see discretisation.m)
|
|
68
|
+
range_fbs[0] = range_fbs[0] + 0.5*wd
|
|
69
|
+
# In this case, wd = wb (see discretisation.m)
|
|
70
|
+
range_fbs[1] = range_fbs[1] - 0.5*wd
|
|
71
|
+
user_set_range = range_fbs
|
|
72
|
+
|
|
73
|
+
else: # MRI example case (arbitrary intensity units)
|
|
74
|
+
user_set_range = None
|
|
75
|
+
|
|
76
|
+
else: # CT example case (definite intensity units -- discrete case)
|
|
77
|
+
user_set_range = im_range
|
|
78
|
+
|
|
79
|
+
# INITIALIZATION
|
|
80
|
+
X = vol[~np.isnan(vol[:])]
|
|
81
|
+
|
|
82
|
+
if (vol is not None) & (wd is not None) & (user_set_range is not None):
|
|
83
|
+
if user_set_range:
|
|
84
|
+
min_val = user_set_range[0]
|
|
85
|
+
max_val = user_set_range[1]
|
|
86
|
+
else:
|
|
87
|
+
min_val = np.min(X)
|
|
88
|
+
max_val = np.max(X)
|
|
89
|
+
else:
|
|
90
|
+
min_val = np.min(X)
|
|
91
|
+
max_val = np.max(X)
|
|
92
|
+
|
|
93
|
+
if max_val == np.inf:
|
|
94
|
+
max_val = np.max(X)
|
|
95
|
+
|
|
96
|
+
if min_val == -np.inf:
|
|
97
|
+
min_val = np.min(X)
|
|
98
|
+
|
|
99
|
+
# Vector of grey-levels.
|
|
100
|
+
# Values are generated within the half-open interval [min_val,max_val+wd)
|
|
101
|
+
levels = np.arange(min_val, max_val + wd, wd)
|
|
102
|
+
n_g = levels.size
|
|
103
|
+
n_v = X.size
|
|
104
|
+
|
|
105
|
+
except Exception as e:
|
|
106
|
+
print('PROBLEM WITH INITIALIZATION OF INTENSITY-VOLUME HISTOGRAM PARAMETERS \n {e}')
|
|
107
|
+
|
|
108
|
+
return X, levels, n_g, n_v
|
|
109
|
+
|
|
110
|
+
def extract_all(
|
|
111
|
+
vol: np.ndarray,
|
|
112
|
+
vol_int_re: np.ndarray,
|
|
113
|
+
wd: int,
|
|
114
|
+
ivh: Dict = None,
|
|
115
|
+
im_range: np.ndarray = None,
|
|
116
|
+
medscan: MEDscan = None
|
|
117
|
+
) -> Dict:
|
|
118
|
+
"""Computes Intensity-volume Histogram Features.
|
|
119
|
+
This features refer to Intensity-volume histogram family in
|
|
120
|
+
the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
|
|
121
|
+
|
|
122
|
+
Note:
|
|
123
|
+
For the input volume, naturally discretised volume can be kept as it is (e.g. HU values of CT scans).
|
|
124
|
+
All other volumes with continuous intensity distribution should be
|
|
125
|
+
quantized (e.g., nBins = 100), with levels = [min, ..., max]
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
vol (ndarray): 3D volume, QUANTIZED, with NaNs outside the region of interest
|
|
129
|
+
vol_int_re (ndarray): 3D volume, with NaNs outside the region of interest
|
|
130
|
+
wd (int): Discretisation width.
|
|
131
|
+
ivh (Dict, optional): Dict of the Intensity-volume Histogram parameters (Discretization algo and value).
|
|
132
|
+
im_range (ndarray, optional): The intensity range.
|
|
133
|
+
medscan (MEDscan, optional): MEDscan instance containing processing parameters.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Dict: Dict of the Intensity Histogram Features.
|
|
137
|
+
"""
|
|
138
|
+
try:
|
|
139
|
+
# Initialization of final structure (Dictionary) containing all features.
|
|
140
|
+
int_vol_hist = {
|
|
141
|
+
'Fivh_V10': [],
|
|
142
|
+
'Fivh_V90': [],
|
|
143
|
+
'Fivh_I10': [],
|
|
144
|
+
'Fivh_I90': [],
|
|
145
|
+
'Fivh_V10minusV90': [],
|
|
146
|
+
'Fivh_I10minusI90': [],
|
|
147
|
+
'Fivh_auc': []
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
# Retrieve relevant parameters
|
|
151
|
+
X, levels, n_g, n_v = init_ivh(vol, vol_int_re, wd, ivh, im_range, medscan)
|
|
152
|
+
|
|
153
|
+
# Calculating fractional volume
|
|
154
|
+
fract_vol = np.zeros(n_g)
|
|
155
|
+
for i in range(0, n_g):
|
|
156
|
+
fract_vol[i] = 1 - np.sum(X < levels[i])/n_v
|
|
157
|
+
|
|
158
|
+
# Calculating intensity fraction
|
|
159
|
+
fract_int = (levels - np.min(levels)) / (np.max(levels) - np.min(levels))
|
|
160
|
+
|
|
161
|
+
# Volume at intensity fraction 10
|
|
162
|
+
v10 = find_v_x(fract_int, fract_vol, 10)
|
|
163
|
+
int_vol_hist['Fivh_V10'] = v10
|
|
164
|
+
|
|
165
|
+
# Volume at intensity fraction 90
|
|
166
|
+
v90 = find_v_x(fract_int, fract_vol, 90)
|
|
167
|
+
int_vol_hist['Fivh_V90'] = v90
|
|
168
|
+
|
|
169
|
+
# Intensity at volume fraction 10
|
|
170
|
+
# For initial arbitrary intensities,
|
|
171
|
+
# we will always be discretising (1000 bins).
|
|
172
|
+
# So intensities are definite here.
|
|
173
|
+
i10 = find_i_x(levels, fract_vol, 10)
|
|
174
|
+
int_vol_hist['Fivh_I10'] = i10
|
|
175
|
+
|
|
176
|
+
# Intensity at volume fraction 90
|
|
177
|
+
# For initial arbitrary intensities,
|
|
178
|
+
# we will always be discretising (1000 bins).
|
|
179
|
+
# So intensities are definite here.
|
|
180
|
+
i90 = find_i_x(levels, fract_vol, 90)
|
|
181
|
+
int_vol_hist['Fivh_I90'] = i90
|
|
182
|
+
|
|
183
|
+
# Volume at intensity fraction difference v10-v90
|
|
184
|
+
int_vol_hist['Fivh_V10minusV90'] = v10 - v90
|
|
185
|
+
|
|
186
|
+
# Intensity at volume fraction difference i10-i90
|
|
187
|
+
# For initial arbitrary intensities,
|
|
188
|
+
# we will always be discretising (1000 bins).
|
|
189
|
+
# So intensities are definite here.
|
|
190
|
+
int_vol_hist['Fivh_I10minusI90'] = i10 - i90
|
|
191
|
+
|
|
192
|
+
# Area under IVH curve
|
|
193
|
+
int_vol_hist['Fivh_auc'] = np.trapz(fract_vol) / (n_g - 1)
|
|
194
|
+
|
|
195
|
+
except Exception as e:
|
|
196
|
+
message = f'PROBLEM WITH COMPUTATION OF INTENSITY-VOLUME HISTOGRAM FEATURES \n {e}'
|
|
197
|
+
if medscan is not None:
|
|
198
|
+
medscan.radiomics.image['intVolHist_3D'][medscan.params.radiomics.ivh_name].update(
|
|
199
|
+
{'error': 'ERROR_COMPUTATION'})
|
|
200
|
+
logging.error(message)
|
|
201
|
+
print(message)
|
|
202
|
+
|
|
203
|
+
return int_vol_hist
|
|
204
|
+
|
|
205
|
+
return int_vol_hist
|
|
206
|
+
|
|
207
|
+
def v10(
|
|
208
|
+
vol: np.ndarray,
|
|
209
|
+
vol_int_re: np.ndarray,
|
|
210
|
+
wd: int,
|
|
211
|
+
ivh: Dict = None,
|
|
212
|
+
im_range: np.ndarray = None,
|
|
213
|
+
medscan: MEDscan = None
|
|
214
|
+
) -> float:
|
|
215
|
+
"""Computes Volume at intensity fraction 10 feature.
|
|
216
|
+
This feature refers to "Fivh_V10" (ID = BC2M) in
|
|
217
|
+
the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
vol (ndarray): 3D volume, QUANTIZED, with NaNs outside the region of interest
|
|
221
|
+
vol_int_re (ndarray): 3D volume, with NaNs outside the region of interest
|
|
222
|
+
wd (int): Discretisation width.
|
|
223
|
+
ivh (Dict, optional): Dict of the Intensity-volume Histogram parameters (Discretization algo and value).
|
|
224
|
+
im_range (ndarray, optional): The intensity range.
|
|
225
|
+
medscan (MEDscan, optional): MEDscan instance containing processing parameters.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
float: Volume at intensity fraction 10 feature.
|
|
229
|
+
"""
|
|
230
|
+
try:
|
|
231
|
+
# Retrieve relevant parameters from init_ivh() method.
|
|
232
|
+
X, levels, n_g, n_v = init_ivh(vol, vol_int_re, wd, ivh, im_range, medscan)
|
|
233
|
+
|
|
234
|
+
# Calculating fractional volume
|
|
235
|
+
fract_vol = np.zeros(n_g)
|
|
236
|
+
for i in range(0, n_g):
|
|
237
|
+
fract_vol[i] = 1 - np.sum(X < levels[i]) / n_v
|
|
238
|
+
|
|
239
|
+
# Calculating intensity fraction
|
|
240
|
+
fract_int = (levels - np.min(levels))/(np.max(levels) - np.min(levels))
|
|
241
|
+
|
|
242
|
+
# Volume at intensity fraction 10
|
|
243
|
+
v10 = find_v_x(fract_int, fract_vol, 10)
|
|
244
|
+
|
|
245
|
+
except Exception as e:
|
|
246
|
+
print(f'PROBLEM WITH COMPUTATION OF V10 FEATURE \n {e}')
|
|
247
|
+
return None
|
|
248
|
+
|
|
249
|
+
return v10
|
|
250
|
+
|
|
251
|
+
def v90(
|
|
252
|
+
vol: np.ndarray,
|
|
253
|
+
vol_int_re: np.ndarray,
|
|
254
|
+
wd: int,
|
|
255
|
+
ivh: Dict = None,
|
|
256
|
+
im_range: np.ndarray = None,
|
|
257
|
+
medscan: MEDscan = None
|
|
258
|
+
) -> float:
|
|
259
|
+
"""Computes Volume at intensity fraction 90 feature.
|
|
260
|
+
This feature refers to "Fivh_V90" (ID = BC2M) in
|
|
261
|
+
the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
vol (ndarray): 3D volume, QUANTIZED, with NaNs outside the region of interest
|
|
265
|
+
vol_int_re (ndarray): 3D volume, with NaNs outside the region of interest
|
|
266
|
+
wd (int): Discretisation width.
|
|
267
|
+
ivh (Dict, optional): Dict of the Intensity-volume Histogram parameters (Discretization algo and value).
|
|
268
|
+
im_range (ndarray, optional): The intensity range.
|
|
269
|
+
medscan (MEDscan, optional): MEDscan instance containing processing parameters.
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
float: Volume at intensity fraction 90 feature.
|
|
273
|
+
"""
|
|
274
|
+
try:
|
|
275
|
+
# Retrieve relevant parameters from init_ivh() method.
|
|
276
|
+
X, levels, n_g, n_v = init_ivh(vol, vol_int_re, wd, ivh, im_range, medscan)
|
|
277
|
+
|
|
278
|
+
# Calculating fractional volume
|
|
279
|
+
fract_vol = np.zeros(n_g)
|
|
280
|
+
for i in range(0, n_g):
|
|
281
|
+
fract_vol[i] = 1 - np.sum(X < levels[i]) / n_v
|
|
282
|
+
|
|
283
|
+
# Calculating intensity fraction
|
|
284
|
+
fract_int = (levels - np.min(levels)) / (np.max(levels) - np.min(levels))
|
|
285
|
+
|
|
286
|
+
# Volume at intensity fraction 90
|
|
287
|
+
v90 = find_v_x(fract_int, fract_vol, 90)
|
|
288
|
+
|
|
289
|
+
except Exception as e:
|
|
290
|
+
print(f'PROBLEM WITH COMPUTATION OF V90 FEATURE \n {e}')
|
|
291
|
+
return None
|
|
292
|
+
|
|
293
|
+
return v90
|
|
294
|
+
|
|
295
|
+
def i10(
|
|
296
|
+
vol: np.ndarray,
|
|
297
|
+
vol_int_re: np.ndarray,
|
|
298
|
+
wd: int,
|
|
299
|
+
ivh: Dict = None,
|
|
300
|
+
im_range: np.ndarray = None,
|
|
301
|
+
medscan: MEDscan = None
|
|
302
|
+
) -> float:
|
|
303
|
+
"""Computes Intensity at volume fraction 10 feature.
|
|
304
|
+
This feature refers to "Fivh_I10" (ID = GBPN) in
|
|
305
|
+
the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
|
|
306
|
+
|
|
307
|
+
Args:
|
|
308
|
+
vol (ndarray): 3D volume, QUANTIZED, with NaNs outside the region of interest
|
|
309
|
+
vol_int_re (ndarray): 3D volume, with NaNs outside the region of interest
|
|
310
|
+
wd (int): Discretisation width.
|
|
311
|
+
ivh (Dict, optional): Dict of the Intensity-volume Histogram parameters (Discretization algo and value).
|
|
312
|
+
im_range (ndarray, optional): The intensity range.
|
|
313
|
+
medscan (MEDscan, optional): MEDscan instance containing processing parameters.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
float: Intensity at volume fraction 10 feature.
|
|
317
|
+
"""
|
|
318
|
+
try:
|
|
319
|
+
# Retrieve relevant parameters from init_ivh() method.
|
|
320
|
+
X, levels, n_g, n_v = init_ivh(vol, vol_int_re, wd, ivh, im_range, medscan)
|
|
321
|
+
|
|
322
|
+
# Calculating fractional volume
|
|
323
|
+
fract_vol = np.zeros(n_g)
|
|
324
|
+
for i in range(0, n_g):
|
|
325
|
+
fract_vol[i] = 1 - np.sum(X < levels[i]) / n_v
|
|
326
|
+
|
|
327
|
+
# Intensity at volume fraction 10
|
|
328
|
+
# For initial arbitrary intensities,
|
|
329
|
+
# we will always be discretising (1000 bins).
|
|
330
|
+
# So intensities are definite here.
|
|
331
|
+
i10 = find_i_x(levels, fract_vol, 10)
|
|
332
|
+
|
|
333
|
+
except Exception as e:
|
|
334
|
+
print(f'PROBLEM WITH COMPUTATION OF I10 FEATURE \n {e}')
|
|
335
|
+
return None
|
|
336
|
+
|
|
337
|
+
return i10
|
|
338
|
+
|
|
339
|
+
def i90(
|
|
340
|
+
vol: np.ndarray,
|
|
341
|
+
vol_int_re: np.ndarray,
|
|
342
|
+
wd: int,
|
|
343
|
+
ivh: Dict = None,
|
|
344
|
+
im_range: np.ndarray = None,
|
|
345
|
+
medscan: MEDscan = None
|
|
346
|
+
) -> float:
|
|
347
|
+
"""Computes Intensity at volume fraction 90 feature.
|
|
348
|
+
This feature refers to "Fivh_I90" (ID = GBPN) in
|
|
349
|
+
the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
vol (ndarray): 3D volume, QUANTIZED, with NaNs outside the region of interest
|
|
353
|
+
vol_int_re (ndarray): 3D volume, with NaNs outside the region of interest
|
|
354
|
+
wd (int): Discretisation width.
|
|
355
|
+
ivh (Dict, optional): Dict of the Intensity-volume Histogram parameters (Discretization algo and value).
|
|
356
|
+
im_range (ndarray, optional): The intensity range.
|
|
357
|
+
medscan (MEDscan, optional): MEDscan instance containing processing parameters.
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
float: Intensity at volume fraction 90 feature.
|
|
361
|
+
"""
|
|
362
|
+
try:
|
|
363
|
+
# Retrieve relevant parameters from init_ivh() method.
|
|
364
|
+
X, levels, n_g, n_v = init_ivh(vol, vol_int_re, wd, ivh, im_range, medscan)
|
|
365
|
+
|
|
366
|
+
# Calculating fractional volume
|
|
367
|
+
fract_vol = np.zeros(n_g)
|
|
368
|
+
for i in range(0, n_g):
|
|
369
|
+
fract_vol[i] = 1 - np.sum(X < levels[i]) / n_v
|
|
370
|
+
|
|
371
|
+
# Intensity at volume fraction 90
|
|
372
|
+
# For initial arbitrary intensities,
|
|
373
|
+
# we will always be discretising (1000 bins).
|
|
374
|
+
# So intensities are definite here.
|
|
375
|
+
i90 = find_i_x(levels, fract_vol, 90)
|
|
376
|
+
|
|
377
|
+
except Exception as e:
|
|
378
|
+
print(f'PROBLEM WITH COMPUTATION OF I90 FEATURE \n {e}')
|
|
379
|
+
return None
|
|
380
|
+
|
|
381
|
+
return i90
|
|
382
|
+
|
|
383
|
+
def v10_minus_v90(
|
|
384
|
+
vol: np.ndarray,
|
|
385
|
+
vol_int_re: np.ndarray,
|
|
386
|
+
wd: int,
|
|
387
|
+
ivh: Dict = None,
|
|
388
|
+
im_range: np.ndarray = None,
|
|
389
|
+
medscan: MEDscan = None
|
|
390
|
+
) -> float:
|
|
391
|
+
"""Computes Volume at intensity fraction difference v10-v90
|
|
392
|
+
This feature refers to "Fivh_V10minusV90" (ID = DDTU) in
|
|
393
|
+
the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
|
|
394
|
+
|
|
395
|
+
Args:
|
|
396
|
+
vol (ndarray): 3D volume, QUANTIZED, with NaNs outside the region of interest
|
|
397
|
+
vol_int_re (ndarray): 3D volume, with NaNs outside the region of interest
|
|
398
|
+
wd (int): Discretisation width.
|
|
399
|
+
ivh (Dict, optional): Dict of the Intensity-volume Histogram parameters (Discretization algo and value).
|
|
400
|
+
im_range (ndarray, optional): The intensity range.
|
|
401
|
+
medscan (MEDscan, optional): MEDscan instance containing processing parameters.
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
float: Volume at intensity fraction difference v10-v90 feature.
|
|
405
|
+
"""
|
|
406
|
+
try:
|
|
407
|
+
# Retrieve relevant parameters from init_ivh() method.
|
|
408
|
+
X, levels, n_g, n_v = init_ivh(vol, vol_int_re, wd, ivh, im_range, medscan)
|
|
409
|
+
|
|
410
|
+
# Calculating fractional volume
|
|
411
|
+
fract_vol = np.zeros(n_g)
|
|
412
|
+
for i in range(0, n_g):
|
|
413
|
+
fract_vol[i] = 1 - np.sum(X < levels[i]) / n_v
|
|
414
|
+
|
|
415
|
+
# Calculating intensity fraction
|
|
416
|
+
fract_int = (levels - np.min(levels)) / (np.max(levels) - np.min(levels))
|
|
417
|
+
|
|
418
|
+
# Volume at intensity fraction 10
|
|
419
|
+
v10 = find_v_x(fract_int, fract_vol, 10)
|
|
420
|
+
|
|
421
|
+
# Volume at intensity fraction 90
|
|
422
|
+
v90 = find_v_x(fract_int, fract_vol, 90)
|
|
423
|
+
|
|
424
|
+
except Exception as e:
|
|
425
|
+
print(f'PROBLEM WITH COMPUTATION OF V10minusV90 FEATURE \n {e}')
|
|
426
|
+
return None
|
|
427
|
+
|
|
428
|
+
return v10 - v90
|
|
429
|
+
|
|
430
|
+
def i10_minus_i90(
|
|
431
|
+
vol: np.ndarray,
|
|
432
|
+
vol_int_re: np.ndarray,
|
|
433
|
+
wd: int,
|
|
434
|
+
ivh: Dict = None,
|
|
435
|
+
im_range: np.ndarray = None,
|
|
436
|
+
medscan: MEDscan = None
|
|
437
|
+
) -> float:
|
|
438
|
+
"""Computes Intensity at volume fraction difference i10-i90
|
|
439
|
+
This feature refers to "Fivh_I10minusI90" (ID = CNV2) in
|
|
440
|
+
the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
|
|
441
|
+
|
|
442
|
+
Args:
|
|
443
|
+
vol (ndarray): 3D volume, QUANTIZED, with NaNs outside the region of interest
|
|
444
|
+
vol_int_re (ndarray): 3D volume, with NaNs outside the region of interest
|
|
445
|
+
wd (int): Discretisation width.
|
|
446
|
+
ivh (Dict, optional): Dict of the Intensity-volume Histogram parameters (Discretization algo and value).
|
|
447
|
+
im_range (ndarray, optional): The intensity range.
|
|
448
|
+
medscan (MEDscan, optional): MEDscan instance containing processing parameters.
|
|
449
|
+
|
|
450
|
+
Returns:
|
|
451
|
+
float: Intensity at volume fraction difference i10-i90 feature.
|
|
452
|
+
"""
|
|
453
|
+
try:
|
|
454
|
+
# Retrieve relevant parameters from init_ivh() method.
|
|
455
|
+
X, levels, n_g, n_v = init_ivh(vol, vol_int_re, wd, ivh, im_range, medscan)
|
|
456
|
+
|
|
457
|
+
# Calculating fractional volume
|
|
458
|
+
fract_vol = np.zeros(n_g)
|
|
459
|
+
for i in range(0, n_g):
|
|
460
|
+
fract_vol[i] = 1 - np.sum(X < levels[i]) / n_v
|
|
461
|
+
|
|
462
|
+
# Intensity at volume fraction 10
|
|
463
|
+
# For initial arbitrary intensities,
|
|
464
|
+
# we will always be discretising (1000 bins).
|
|
465
|
+
# So intensities are definite here.
|
|
466
|
+
i10 = find_i_x(levels, fract_vol, 10)
|
|
467
|
+
|
|
468
|
+
# Intensity at volume fraction 90
|
|
469
|
+
# For initial arbitrary intensities,
|
|
470
|
+
# we will always be discretising (1000 bins).
|
|
471
|
+
# So intensities are definite here.
|
|
472
|
+
i90 = find_i_x(levels, fract_vol, 90)
|
|
473
|
+
|
|
474
|
+
except Exception as e:
|
|
475
|
+
print(f'PROBLEM WITH COMPUTATION OF I10minusI90 FEATURE \n {e}')
|
|
476
|
+
return None
|
|
477
|
+
|
|
478
|
+
return i10 - i90
|
|
479
|
+
|
|
480
|
+
def auc(
|
|
481
|
+
vol: np.ndarray,
|
|
482
|
+
vol_int_re: np.ndarray,
|
|
483
|
+
wd: int,
|
|
484
|
+
ivh: Dict = None,
|
|
485
|
+
im_range: np.ndarray = None,
|
|
486
|
+
medscan: MEDscan = None
|
|
487
|
+
) -> float:
|
|
488
|
+
"""
|
|
489
|
+
Computes Area under IVH curve.
|
|
490
|
+
This feature refers to "Fivh_auc" (ID = 9CMM) in
|
|
491
|
+
the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
|
|
492
|
+
|
|
493
|
+
Note:
|
|
494
|
+
For the input volume:
|
|
495
|
+
|
|
496
|
+
* Naturally discretised volume can be kept as it is (e.g. HU values of CT scans)
|
|
497
|
+
* All other volumes with continuous intensity distribution should be \
|
|
498
|
+
quantized (e.g., nBins = 100), with levels = [min, ..., max]
|
|
499
|
+
|
|
500
|
+
Args:
|
|
501
|
+
vol(ndarray): 3D volume, QUANTIZED, with NaNs outside the region of interest
|
|
502
|
+
vol_int_re(ndarray): 3D volume, with NaNs outside the region of interest
|
|
503
|
+
wd(int): Discretisation width.
|
|
504
|
+
ivh (Dict, optional): Dict of the Intensity-volume Histogram parameters (Discretization algo and value).
|
|
505
|
+
im_range (ndarray, optional): The intensity range.
|
|
506
|
+
medscan (MEDscan, optional): MEDscan instance containing processing parameters.
|
|
507
|
+
|
|
508
|
+
Returns:
|
|
509
|
+
float: Area under IVH curve feature.
|
|
510
|
+
"""
|
|
511
|
+
try:
|
|
512
|
+
# Retrieve relevant parameters from init_ivh() method.
|
|
513
|
+
X, levels, n_g, n_v = init_ivh(vol, vol_int_re, wd, ivh, im_range, medscan)
|
|
514
|
+
|
|
515
|
+
# Calculating fractional volume
|
|
516
|
+
fract_vol = np.zeros(n_g)
|
|
517
|
+
for i in range(0, n_g):
|
|
518
|
+
fract_vol[i] = 1 - np.sum(X < levels[i]) / n_v
|
|
519
|
+
|
|
520
|
+
# Area under IVH curve
|
|
521
|
+
auc = np.trapz(fract_vol) / (n_g - 1)
|
|
522
|
+
|
|
523
|
+
except Exception as e:
|
|
524
|
+
print(f'PROBLEM WITH COMPUTATION OF AUC FEATURE \n {e}')
|
|
525
|
+
return None
|
|
526
|
+
|
|
527
|
+
return auc
|