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.
Files changed (78) hide show
  1. MEDiml/MEDscan.py +1696 -0
  2. MEDiml/__init__.py +21 -0
  3. MEDiml/biomarkers/BatchExtractor.py +806 -0
  4. MEDiml/biomarkers/BatchExtractorTexturalFilters.py +840 -0
  5. MEDiml/biomarkers/__init__.py +16 -0
  6. MEDiml/biomarkers/diagnostics.py +125 -0
  7. MEDiml/biomarkers/get_oriented_bound_box.py +158 -0
  8. MEDiml/biomarkers/glcm.py +1602 -0
  9. MEDiml/biomarkers/gldzm.py +523 -0
  10. MEDiml/biomarkers/glrlm.py +1315 -0
  11. MEDiml/biomarkers/glszm.py +555 -0
  12. MEDiml/biomarkers/int_vol_hist.py +527 -0
  13. MEDiml/biomarkers/intensity_histogram.py +615 -0
  14. MEDiml/biomarkers/local_intensity.py +89 -0
  15. MEDiml/biomarkers/morph.py +1756 -0
  16. MEDiml/biomarkers/ngldm.py +780 -0
  17. MEDiml/biomarkers/ngtdm.py +414 -0
  18. MEDiml/biomarkers/stats.py +373 -0
  19. MEDiml/biomarkers/utils.py +389 -0
  20. MEDiml/filters/TexturalFilter.py +299 -0
  21. MEDiml/filters/__init__.py +9 -0
  22. MEDiml/filters/apply_filter.py +134 -0
  23. MEDiml/filters/gabor.py +215 -0
  24. MEDiml/filters/laws.py +283 -0
  25. MEDiml/filters/log.py +147 -0
  26. MEDiml/filters/mean.py +121 -0
  27. MEDiml/filters/textural_filters_kernels.py +1738 -0
  28. MEDiml/filters/utils.py +107 -0
  29. MEDiml/filters/wavelet.py +237 -0
  30. MEDiml/learning/DataCleaner.py +198 -0
  31. MEDiml/learning/DesignExperiment.py +480 -0
  32. MEDiml/learning/FSR.py +667 -0
  33. MEDiml/learning/Normalization.py +112 -0
  34. MEDiml/learning/RadiomicsLearner.py +714 -0
  35. MEDiml/learning/Results.py +2237 -0
  36. MEDiml/learning/Stats.py +694 -0
  37. MEDiml/learning/__init__.py +10 -0
  38. MEDiml/learning/cleaning_utils.py +107 -0
  39. MEDiml/learning/ml_utils.py +1015 -0
  40. MEDiml/processing/__init__.py +6 -0
  41. MEDiml/processing/compute_suv_map.py +121 -0
  42. MEDiml/processing/discretisation.py +149 -0
  43. MEDiml/processing/interpolation.py +275 -0
  44. MEDiml/processing/resegmentation.py +66 -0
  45. MEDiml/processing/segmentation.py +912 -0
  46. MEDiml/utils/__init__.py +25 -0
  47. MEDiml/utils/batch_patients.py +45 -0
  48. MEDiml/utils/create_radiomics_table.py +131 -0
  49. MEDiml/utils/data_frame_export.py +42 -0
  50. MEDiml/utils/find_process_names.py +16 -0
  51. MEDiml/utils/get_file_paths.py +34 -0
  52. MEDiml/utils/get_full_rad_names.py +21 -0
  53. MEDiml/utils/get_institutions_from_ids.py +16 -0
  54. MEDiml/utils/get_patient_id_from_scan_name.py +22 -0
  55. MEDiml/utils/get_patient_names.py +26 -0
  56. MEDiml/utils/get_radiomic_names.py +27 -0
  57. MEDiml/utils/get_scan_name_from_rad_name.py +22 -0
  58. MEDiml/utils/image_reader_SITK.py +37 -0
  59. MEDiml/utils/image_volume_obj.py +22 -0
  60. MEDiml/utils/imref.py +340 -0
  61. MEDiml/utils/initialize_features_names.py +62 -0
  62. MEDiml/utils/inpolygon.py +159 -0
  63. MEDiml/utils/interp3.py +43 -0
  64. MEDiml/utils/json_utils.py +78 -0
  65. MEDiml/utils/mode.py +31 -0
  66. MEDiml/utils/parse_contour_string.py +58 -0
  67. MEDiml/utils/save_MEDscan.py +30 -0
  68. MEDiml/utils/strfind.py +32 -0
  69. MEDiml/utils/textureTools.py +188 -0
  70. MEDiml/utils/texture_features_names.py +115 -0
  71. MEDiml/utils/write_radiomics_csv.py +47 -0
  72. MEDiml/wrangling/DataManager.py +1724 -0
  73. MEDiml/wrangling/ProcessDICOM.py +512 -0
  74. MEDiml/wrangling/__init__.py +3 -0
  75. mediml-0.9.9.dist-info/LICENSE.md +674 -0
  76. mediml-0.9.9.dist-info/METADATA +232 -0
  77. mediml-0.9.9.dist-info/RECORD +78 -0
  78. mediml-0.9.9.dist-info/WHEEL +4 -0
@@ -0,0 +1,615 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ import warnings
5
+ from typing import Dict, Tuple
6
+
7
+ import numpy as np
8
+ from scipy.stats import scoreatpercentile, variation
9
+
10
+
11
+ def init_IH(vol: np.ndarray) -> Tuple[np.ndarray, np.ndarray, int, np.ndarray, np.ndarray]:
12
+ """Initialize Intensity Histogram Features.
13
+
14
+ Args:
15
+ vol (ndarray): 3D volume, QUANTIZED (e.g. nBins = 100,
16
+ levels = [1, ..., max]), with NaNs outside the region of interest.
17
+
18
+ Returns:
19
+ Dict: Dict of the Intensity Histogram Features.
20
+ """
21
+ warnings.simplefilter("ignore")
22
+
23
+ # INITIALIZATION
24
+
25
+ x = vol[~np.isnan(vol[:])]
26
+ n_v = x.size
27
+
28
+ # CONSTRUCTION OF HISTOGRAM AND ASSOCIATED NUMBER OF GRAY-LEVELS
29
+
30
+ # Always defined from 1 to the maximum value of
31
+ # the volume to remove any ambiguity
32
+ levels = np.arange(1, np.max(x) + 100*np.finfo(float).eps)
33
+ n_g = levels.size # Number of gray-levels
34
+ h = np.zeros(n_g) # The histogram of x
35
+
36
+ for i in np.arange(0, n_g):
37
+ # == i or == levels(i) is equivalent since levels = 1:max(x),
38
+ # and n_g = numel(levels)
39
+ h[i] = np.sum(x == i + 1) # h[i] = sum(x == i+1)
40
+
41
+ p = (h / n_v) # Occurence probability for each grey level bin i
42
+ pt = p.transpose()
43
+
44
+ return x, levels, n_g, h, p, pt
45
+
46
+ def extract_all(vol: np.ndarray) -> Dict:
47
+ """Computes Intensity Histogram Features.
48
+ These features refer to Intensity histogram family in
49
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
50
+
51
+ Args:
52
+ vol (ndarray): 3D volume, QUANTIZED (e.g. nBins = 100,
53
+ levels = [1, ..., max]), with NaNs outside the region of interest.
54
+
55
+ Returns:
56
+ Dict: Dict of the Intensity Histogram Features.
57
+ """
58
+ warnings.simplefilter("ignore")
59
+
60
+ # INITIALIZATION
61
+ x, levels, n_g, h, p, pt = init_IH(vol)
62
+
63
+ # Initialization of final structure (Dictionary) containing all features.
64
+ int_hist = {'Fih_mean': [],
65
+ 'Fih_var': [],
66
+ 'Fih_skew': [],
67
+ 'Fih_kurt': [],
68
+ 'Fih_median': [],
69
+ 'Fih_min': [],
70
+ 'Fih_P10': [],
71
+ 'Fih_P90': [],
72
+ 'Fih_max': [],
73
+ 'Fih_mode': [],
74
+ 'Fih_iqr': [],
75
+ 'Fih_range': [],
76
+ 'Fih_mad': [],
77
+ 'Fih_rmad': [],
78
+ 'Fih_medad': [],
79
+ 'Fih_cov': [],
80
+ 'Fih_qcod': [],
81
+ 'Fih_entropy': [],
82
+ 'Fih_uniformity': [],
83
+ 'Fih_max_grad': [],
84
+ 'Fih_max_grad_gl': [],
85
+ 'Fih_min_grad': [],
86
+ 'Fih_min_grad_gl': []
87
+ }
88
+
89
+ # STARTING COMPUTATION
90
+ # Intensity histogram mean
91
+ u = np.matmul(levels, pt)
92
+ int_hist['Fih_mean'] = u
93
+
94
+ # Intensity histogram variance
95
+ var = np.matmul(np.power(levels - u, 2), pt)
96
+ int_hist['Fih_var'] = var
97
+
98
+ # Intensity histogram skewness and kurtosis
99
+ skew = 0
100
+ kurt = 0
101
+
102
+ if var != 0:
103
+ skew = np.matmul(np.power(levels - u, 3), pt) / np.power(var, 3/2)
104
+ kurt = np.matmul(np.power(levels - u, 4), pt) / np.power(var, 2) - 3
105
+
106
+ int_hist['Fih_skew'] = skew
107
+ int_hist['Fih_kurt'] = kurt
108
+
109
+ # Intensity histogram median
110
+ int_hist['Fih_median'] = np.median(x)
111
+
112
+ # Intensity histogram minimum grey level
113
+ int_hist['Fih_min'] = np.min(x)
114
+
115
+ # Intensity histogram 10th percentile
116
+ p10 = scoreatpercentile(x, 10)
117
+ int_hist['Fih_P10'] = p10
118
+
119
+ # Intensity histogram 90th percentile
120
+ p90 = scoreatpercentile(x, 90)
121
+ int_hist['Fih_P90'] = p90
122
+
123
+ # Intensity histogram maximum grey level
124
+ int_hist['Fih_max'] = np.max(x)
125
+
126
+ # Intensity histogram mode
127
+ # levels = 1:max(x), so the index of the ith bin of h is the same as i
128
+ mh = np.max(h)
129
+ mode = np.where(h == mh)[0] + 1
130
+
131
+ if np.size(mode) > 1:
132
+ dist = np.abs(mode - u)
133
+ ind_min = np.argmin(dist)
134
+ int_hist['Fih_mode'] = mode[ind_min]
135
+ else:
136
+ int_hist['Fih_mode'] = mode[0]
137
+
138
+ # Intensity histogram interquantile range
139
+ # Since x goes from 1:max(x), all with integer values,
140
+ # the result is an integer
141
+ int_hist['Fih_iqr'] = scoreatpercentile(x, 75) - scoreatpercentile(x, 25)
142
+
143
+ # Intensity histogram range
144
+ int_hist['Fih_range'] = np.max(x) - np.min(x)
145
+
146
+ # Intensity histogram mean absolute deviation
147
+ int_hist['Fih_mad'] = np.mean(abs(x - u))
148
+
149
+ # Intensity histogram robust mean absolute deviation
150
+ x_10_90 = x[np.where((x >= p10) & (x <= p90), True, False)]
151
+ int_hist['Fih_rmad'] = np.mean(np.abs(x_10_90 - np.mean(x_10_90)))
152
+
153
+ # Intensity histogram median absolute deviation
154
+ int_hist['Fih_medad'] = np.mean(np.absolute(x - np.median(x)))
155
+
156
+ # Intensity histogram coefficient of variation
157
+ int_hist['Fih_cov'] = variation(x)
158
+
159
+ # Intensity histogram quartile coefficient of dispersion
160
+ x_75_25 = scoreatpercentile(x, 75) + scoreatpercentile(x, 25)
161
+ int_hist['Fih_qcod'] = int_hist['Fih_iqr'] / x_75_25
162
+
163
+ # Intensity histogram entropy
164
+ p = p[p > 0]
165
+ int_hist['Fih_entropy'] = -np.sum(p * np.log2(p))
166
+
167
+ # Intensity histogram uniformity
168
+ int_hist['Fih_uniformity'] = np.sum(np.power(p, 2))
169
+
170
+ # Calculation of histogram gradient
171
+ hist_grad = np.zeros(n_g)
172
+ hist_grad[0] = h[1] - h[0]
173
+ hist_grad[-1] = h[-1] - h[-2]
174
+
175
+ for i in np.arange(1, n_g-1):
176
+ hist_grad[i] = (h[i+1] - h[i-1])/2
177
+
178
+ # Maximum histogram gradient
179
+ int_hist['Fih_max_grad'] = np.max(hist_grad)
180
+
181
+ # Maximum histogram gradient grey level
182
+ ind_max = np.where(hist_grad == int_hist['Fih_max_grad'])[0][0]
183
+ int_hist['Fih_max_grad_gl'] = levels[ind_max]
184
+
185
+ # Minimum histogram gradient
186
+ int_hist['Fih_min_grad'] = np.min(hist_grad)
187
+
188
+ # Minimum histogram gradient grey level
189
+ ind_min = np.where(hist_grad == int_hist['Fih_min_grad'])[0][0]
190
+ int_hist['Fih_min_grad_gl'] = levels[ind_min]
191
+
192
+ return int_hist
193
+
194
+ def mean(vol: np.ndarray) -> float:
195
+ """Compute Intensity histogram mean feature of the input dataset (3D Array).
196
+ This feature refers to "Fih_mean" (ID = X6K6) in
197
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
198
+
199
+ Args:
200
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
201
+ (continuous imaging intensity distribution)
202
+
203
+ Returns:
204
+ float: Intensity histogram mean
205
+ """
206
+ _, levels, _, _, _, pt = init_IH(vol) # Initialization
207
+
208
+ return np.matmul(levels, pt) # Intensity histogram mean
209
+
210
+ def var(vol: np.ndarray) -> float:
211
+ """Compute Intensity histogram variance feature of the input dataset (3D Array).
212
+ This feature refers to "Fih_var" (ID = CH89) in
213
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
214
+
215
+ Args:
216
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
217
+ (continuous imaging intensity distribution)
218
+
219
+ Returns:
220
+ float: Intensity histogram variance
221
+ """
222
+ _, levels, _, _, _, pt = init_IH(vol) # Initialization
223
+ u = np.matmul(levels, pt) # Intensity histogram mean
224
+
225
+ return np.matmul(np.power(levels - u, 2), pt) # Intensity histogram variance
226
+
227
+ def skewness(vol: np.ndarray) -> float:
228
+ """Compute Intensity histogram skewness feature of the input dataset (3D Array).
229
+ This feature refers to "Fih_skew" (ID = 88K1) in
230
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
231
+
232
+ Args:
233
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
234
+ (continuous imaging intensity distribution)
235
+
236
+ Returns:
237
+ float: Intensity histogram skewness.
238
+ """
239
+ _, levels, _, _, _, pt = init_IH(vol) # Initialization
240
+ u = np.matmul(levels, pt) # Intensity histogram mean
241
+ var = np.matmul(np.power(levels - u, 2), pt) # Intensity histogram variance
242
+ if var != 0:
243
+ skew = np.matmul(np.power(levels - u, 3), pt) / np.power(var, 3/2)
244
+
245
+ return skew # Skewness
246
+
247
+ def kurt(vol: np.ndarray) -> float:
248
+ """Compute Intensity histogram kurtosis feature of the input dataset (3D Array).
249
+ This feature refers to "Fih_kurt" (ID = C3I7) in
250
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
251
+
252
+ Args:
253
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
254
+ (continuous imaging intensity distribution)
255
+
256
+ Returns:
257
+ float: The Intensity histogram kurtosis feature
258
+ """
259
+ _, levels, _, _, _, pt = init_IH(vol) # Initialization
260
+ u = np.matmul(levels, pt) # Intensity histogram mean
261
+ var = np.matmul(np.power(levels - u, 2), pt) # Intensity histogram variance
262
+ if var != 0:
263
+ kurt = np.matmul(np.power(levels - u, 4), pt) / np.power(var, 2) - 3
264
+
265
+ return kurt # Kurtosis
266
+
267
+ def median(vol: np.ndarray) -> float:
268
+ """Compute Intensity histogram median feature along the specified axis of the input dataset (3D Array).
269
+ This feature refers to "Fih_median" (ID = WIFQ) in
270
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
271
+
272
+ Args:
273
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
274
+ (continuous imaging intensity distribution)
275
+
276
+ Returns:
277
+ float: Intensity histogram median feature.
278
+ """
279
+ x = vol[~np.isnan(vol[:])] # Initialization
280
+
281
+ return np.median(x) # Median
282
+
283
+ def min(vol: np.ndarray) -> float:
284
+ """Compute Intensity histogram minimum grey level feature of the input dataset (3D Array).
285
+ This feature refers to "Fih_min" (ID = 1PR8) in
286
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
287
+
288
+ Args:
289
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
290
+ (continuous imaging intensity distribution)
291
+
292
+ Returns:
293
+ float: Intensity histogram minimum grey level feature.
294
+ """
295
+ x = vol[~np.isnan(vol[:])] # Initialization
296
+
297
+ return np.min(x) # Minimum grey level
298
+
299
+ def p10(vol: np.ndarray) -> float:
300
+ """Compute Intensity histogram 10th percentile feature of the input dataset (3D Array).
301
+ This feature refers to "Fih_P10" (ID = GPMT) in
302
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
303
+
304
+ Args:
305
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
306
+ (continuous imaging intensity distribution)
307
+
308
+ Returns:
309
+ float: Intensity histogram 10th percentile feature.
310
+ """
311
+ x = vol[~np.isnan(vol[:])] # Initialization
312
+
313
+ return scoreatpercentile(x, 10) # 10th percentile
314
+
315
+ def p90(vol: np.ndarray) -> float:
316
+ """Compute Intensity histogram 90th percentile feature of the input dataset (3D Array).
317
+ This feature refers to "Fih_P90" (ID = OZ0C) in
318
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
319
+
320
+ Args:
321
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
322
+ (continuous imaging intensity distribution)
323
+ Returns:
324
+ float: Intensity histogram 90th percentile feature.
325
+ """
326
+ x = vol[~np.isnan(vol[:])] # Initialization
327
+
328
+ return scoreatpercentile(x, 90) # 90th percentile
329
+
330
+ def max(vol: np.ndarray) -> float:
331
+ """Compute Intensity histogram maximum grey level feature of the input dataset (3D Array).
332
+ This feature refers to "Fih_max" (ID = 3NCY) in
333
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
334
+
335
+ Args:
336
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
337
+ (continuous imaging intensity distribution)
338
+
339
+ Returns:
340
+ float: Intensity histogram maximum grey level feature.
341
+ """
342
+ x = vol[~np.isnan(vol[:])] # Initialization
343
+
344
+ return np.max(x) # Maximum grey level
345
+
346
+ def mode(vol: np.ndarray) -> int:
347
+ """Compute Intensity histogram mode feature of the input dataset (3D Array).
348
+ This feature refers to "Fih_mode" (ID = AMMC) in
349
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
350
+
351
+ Args:
352
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
353
+ (continuous imaging intensity distribution)
354
+
355
+ Returns:
356
+ integer: Intensity histogram mode.
357
+ levels = 1:max(x), so the index of the ith bin of h is the same as i
358
+ """
359
+ _, levels, _, h, _, pt = init_IH(vol) # Initialization
360
+ u = np.matmul(levels, pt)
361
+ mh = np.max(h)
362
+ mode = np.where(h == mh)[0] + 1
363
+
364
+ if np.size(mode) > 1:
365
+ dist = np.abs(mode - u)
366
+ ind_min = np.argmin(dist)
367
+
368
+ return mode[ind_min] # Intensity histogram mode.
369
+ else:
370
+
371
+ return mode[0] # Intensity histogram mode.
372
+
373
+ def iqrange(vol: np.ndarray) -> float:
374
+ r"""Compute Intensity histogram interquantile range feature of the input dataset (3D Array).
375
+ This feature refers to "Fih_iqr" (ID = WR0O) in
376
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
377
+
378
+ Args:
379
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
380
+ (continuous imaging intensity distribution)
381
+
382
+ Returns:
383
+ float: Interquartile range. If :math:`axis ≠ None` , the output data-type is the same as that of the input.
384
+ Since x goes from :math:`1:max(x)` , all with integer values, the result is an integer.
385
+ """
386
+ x = vol[~np.isnan(vol[:])] # Initialization
387
+
388
+ return scoreatpercentile(x, 75) - scoreatpercentile(x, 25) # Intensity histogram interquantile range
389
+
390
+ def range(vol: np.ndarray) -> float:
391
+ """Compute Intensity histogram range of values (maximum - minimum) feature of the input dataset (3D Array).
392
+ This feature refers to "Fih_range" (ID = 5Z3W) in
393
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
394
+
395
+ Args:
396
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
397
+ (continuous imaging intensity distribution)
398
+
399
+ Returns:
400
+ float: Intensity histogram range.
401
+ """
402
+ x = vol[~np.isnan(vol[:])] # Initialization
403
+
404
+ return np.max(x) - np.min(x) # Intensity histogram range
405
+
406
+ def mad(vol: np.ndarray) -> float:
407
+ """Compute Intensity histogram mean absolute deviation feature of the input dataset (3D Array).
408
+ This feature refers to "Fih_mad" (ID = D2ZX) in
409
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
410
+
411
+ Args:
412
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
413
+ (continuous imaging intensity distribution)
414
+
415
+ Returns:
416
+ float : Intensity histogram mean absolute deviation feature.
417
+ """
418
+ x, levels, _, _, _, pt = init_IH(vol) # Initialization
419
+ u = np.matmul(levels, pt)
420
+
421
+ return np.mean(abs(x - u)) # Intensity histogram mean absolute deviation
422
+
423
+ def rmad(vol: np.ndarray) -> float:
424
+ """Compute Intensity histogram robust mean absolute deviation feature of the input dataset (3D Array).
425
+ This feature refers to "Fih_rmad" (ID = WRZB) in
426
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
427
+
428
+ Args:
429
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
430
+ (continuous imaging intensity distribution)
431
+ P10(ndarray): Score at 10th percentil.
432
+ P90(ndarray): Score at 90th percentil.
433
+
434
+ Returns:
435
+ float: Intensity histogram robust mean absolute deviation
436
+ """
437
+ x = vol[~np.isnan(vol[:])] # Initialization
438
+ P10 = scoreatpercentile(x, 10) # 10th percentile
439
+ P90 = scoreatpercentile(x, 90) # 90th percentile
440
+ x_10_90 = x[np.where((x >= P10) &
441
+ (x <= P90), True, False)] # Holding x for (x >= P10) and (x<= P90)
442
+
443
+ return np.mean(np.abs(x_10_90 - np.mean(x_10_90))) # Intensity histogram robust mean absolute deviation
444
+
445
+ def medad(vol: np.ndarray) -> float:
446
+ """Intensity histogram median absolute deviation feature of the input dataset (3D Array).
447
+ This feature refers to "Fih_medad" (ID = 4RNL) in
448
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
449
+
450
+ Args:
451
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
452
+ (continuous imaging intensity distribution)
453
+
454
+ Returns:
455
+ float: Intensity histogram median absolute deviation feature.
456
+ """
457
+ x = vol[~np.isnan(vol[:])] # Initialization
458
+
459
+ return np.mean(np.absolute(x - np.median(x))) # Intensity histogram median absolute deviation
460
+
461
+ def cov(vol: np.ndarray) -> float:
462
+ """Compute Intensity histogram coefficient of variation feature of the input dataset (3D Array).
463
+ This feature refers to "Fih_cov" (ID = CWYJ) in
464
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
465
+
466
+ Args:
467
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
468
+ (continuous imaging intensity distribution)
469
+
470
+ Returns:
471
+ float: Intensity histogram coefficient of variation feature.
472
+ """
473
+ x = vol[~np.isnan(vol[:])] # Initialization
474
+
475
+ return variation(x) # Intensity histogram coefficient of variation
476
+
477
+ def qcod(vol: np.ndarray) -> float:
478
+ """Compute the quartile coefficient of dispersion feature of the input dataset (3D Array).
479
+ This feature refers to "Fih_qcod" (ID = SLWD) in
480
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
481
+
482
+ Args:
483
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
484
+ (continuous imaging intensity distribution)
485
+
486
+ Returns:
487
+ ndarray: A new array holding the quartile coefficient of dispersion feature.
488
+ """
489
+ x = vol[~np.isnan(vol[:])] # Initialization
490
+ x_75_25 = scoreatpercentile(x, 75) + scoreatpercentile(x, 25)
491
+
492
+ return iqrange(x) / x_75_25 # Quartile coefficient of dispersion
493
+
494
+ def entropy(vol: np.ndarray) -> float:
495
+ """Compute Intensity histogram entropy feature of the input dataset (3D Array).
496
+ This feature refers to "Fih_entropy" (ID = TLU2) in
497
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
498
+
499
+ Args:
500
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
501
+ (continuous imaging intensity distribution)
502
+
503
+ Returns:
504
+ float: Intensity histogram entropy feature.
505
+ """
506
+ x, _, _, _, p, _ = init_IH(vol) # Initialization
507
+ p = p[p > 0]
508
+
509
+ return -np.sum(p * np.log2(p)) # Intensity histogram entropy
510
+
511
+ def uniformity(vol: np.ndarray) -> float:
512
+ """Compute Intensity histogram uniformity feature of the input dataset (3D Array).
513
+ This feature refers to "Fih_uniformity" (ID = BJ5W) in
514
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
515
+
516
+ Args:
517
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
518
+ (continuous imaging intensity distribution)
519
+
520
+ Returns:
521
+ float: Intensity histogram uniformity feature.
522
+ """
523
+ x, _, _, _, p, _ = init_IH(vol) # Initialization
524
+ p = p[p > 0]
525
+
526
+ return np.sum(np.power(p, 2)) # Intensity histogram uniformity
527
+
528
+ def hist_grad_calc(vol: np.ndarray) -> np.ndarray:
529
+ """Calculation of histogram gradient.
530
+ This feature refers to "Fih_hist_grad_calc" (ID = 12CE) in
531
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
532
+
533
+ Args:
534
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
535
+ (continuous imaging intensity distribution)
536
+
537
+ Returns:
538
+ ndarray: Histogram gradient
539
+ """
540
+ _, _, n_g, h, _, _ = init_IH(vol) # Initialization
541
+ hist_grad = np.zeros(n_g)
542
+ hist_grad[0] = h[1] - h[0]
543
+ hist_grad[-1] = h[-1] - h[-2]
544
+ for i in np.arange(1, n_g-1):
545
+ hist_grad[i] = (h[i+1] - h[i-1])/2
546
+
547
+ return hist_grad # Intensity histogram uniformity
548
+
549
+ def max_grad(vol: np.ndarray) -> float:
550
+ """Calculation of Maximum histogram gradient feature.
551
+ This feature refers to "Fih_max_grad" (ID = 12CE) in
552
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
553
+
554
+ Args:
555
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
556
+ (continuous imaging intensity distribution)
557
+
558
+ Returns:
559
+ float: Maximum histogram gradient feature.
560
+ """
561
+ hist_grad = hist_grad_calc(vol) # Initialization
562
+
563
+ return np.max(hist_grad) # Maximum histogram gradient
564
+
565
+ def max_grad_gl(vol: np.ndarray) -> float:
566
+ """Calculation of Maximum histogram gradient grey level feature.
567
+ This feature refers to "Fih_max_grad_gl" (ID = 8E6O) in
568
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
569
+
570
+ Args:
571
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
572
+ (continuous imaging intensity distribution)
573
+
574
+ Returns:
575
+ float: Maximum histogram gradient grey level feature.
576
+ """
577
+ _, levels, _, _, _, _ = init_IH(vol) # Initialization
578
+ hist_grad = hist_grad_calc(vol)
579
+ ind_max = np.where(hist_grad == np.max(hist_grad))[0][0]
580
+
581
+ return levels[ind_max] # Maximum histogram gradient grey level
582
+
583
+ def min_grad(vol: np.ndarray) -> float:
584
+ """Calculation of Minimum histogram gradient feature.
585
+ This feature refers to "Fih_min_grad" (ID = VQB3) in
586
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
587
+
588
+ Args:
589
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
590
+ (continuous imaging intensity distribution)
591
+
592
+ Returns:
593
+ float: Minimum histogram gradient feature.
594
+ """
595
+ hist_grad = hist_grad_calc(vol) # Initialization
596
+
597
+ return np.min(hist_grad) # Minimum histogram gradient
598
+
599
+ def min_grad_gl(vol: np.ndarray) -> float:
600
+ """Calculation of Minimum histogram gradient grey level feature.
601
+ This feature refers to "Fih_min_grad_gl" (ID = RHQZ) in
602
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
603
+
604
+ Args:
605
+ vol(ndarray): 3D volume, NON-QUANTIZED, with NaNs outside the region of interest
606
+ (continuous imaging intensity distribution)
607
+
608
+ Returns:
609
+ float: Minimum histogram gradient grey level feature.
610
+ """
611
+ _, levels, _, _, _, _ = init_IH(vol) # Initialization
612
+ hist_grad = hist_grad_calc(vol)
613
+ ind_min = np.where(hist_grad == np.min(hist_grad))[0][0]
614
+
615
+ return levels[ind_min] # Minimum histogram gradient grey level
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from typing import Dict
5
+
6
+ from numpy import ndarray
7
+
8
+ from ..biomarkers.utils import get_glob_peak, get_loc_peak
9
+
10
+
11
+ def extract_all(img_obj: ndarray,
12
+ roi_obj: ndarray,
13
+ res: ndarray,
14
+ intensity_type: str,
15
+ compute_global: bool = False) -> Dict:
16
+ """Compute Local Intensity Features.
17
+ This features refer to Local Intensity family in
18
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
19
+
20
+ Args:
21
+ img_obj (ndarray): Continuous image intensity distribution, with no NaNs
22
+ outside the ROI.
23
+ roi_obj (ndarray): Array of the mask defining the ROI.
24
+ res (List[float]): [a,b,c] vector specifying the resolution of the volume in mm.
25
+ XYZ resolution (world), or JIK resolution (intrinsic matlab).
26
+ intensity_type (str): Type of intensity to compute. Can be "arbitrary", "definite" or "filtered".
27
+ Will compute features only for "definite" intensity type.
28
+ compute_global (bool, optional): If True, will compute global intensity peak, we
29
+ recommend you don't set it to True if not necessary in your study or analysis as it
30
+ takes too much time for calculation. Default: False.
31
+
32
+ Returns:
33
+ Dict: Dict of the Local Intensity Features.
34
+
35
+ Raises:
36
+ ValueError: If `intensity_type` is not "arbitrary", "definite" or "filtered".
37
+ """
38
+ assert intensity_type in ["arbitrary", "definite", "filtered"], \
39
+ "intensity_type must be 'arbitrary', 'definite' or 'filtered'"
40
+
41
+ loc_int = {'Floc_peak_local': [], 'Floc_peak_global': []}
42
+
43
+ if intensity_type == "definite":
44
+ loc_int['Floc_peak_local'] = (get_loc_peak(img_obj, roi_obj, res))
45
+
46
+ # NEEDS TO BE VECTORIZED FOR FASTER CALCULATION! OR
47
+ # SIMPLY JUST CONVOLUTE A 3D AVERAGING FILTER!
48
+ if compute_global:
49
+ loc_int['Floc_peak_global'] = (get_glob_peak(img_obj,roi_obj, res))
50
+
51
+ return loc_int
52
+
53
+ def peak_local(img_obj: ndarray,
54
+ roi_obj: ndarray,
55
+ res: ndarray) -> float:
56
+ """Computes local intensity peak.
57
+ This feature refers to "Floc_peak_local" (ID = VJGA) in
58
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
59
+
60
+ Args:
61
+ img_obj (ndarray): Continuous image intensity distribution, with no NaNs
62
+ outside the ROI.
63
+ roi_obj (ndarray): Array of the mask defining the ROI.
64
+ res (List[float]): [a,b,c] vector specifying the resolution of the volume in mm.
65
+ XYZ resolution (world), or JIK resolution (intrinsic matlab).
66
+
67
+ Returns:
68
+ float: Local intensity peak.
69
+ """
70
+ return get_loc_peak(img_obj, roi_obj, res)
71
+
72
+ def peak_global(img_obj: ndarray,
73
+ roi_obj: ndarray,
74
+ res: ndarray) -> float:
75
+ """Computes global intensity peak.
76
+ This feature refers to "Floc_peak_global" (ID = 0F91) in
77
+ the `IBSI1 reference manual <https://arxiv.org/pdf/1612.07003.pdf>`__.
78
+
79
+ Args:
80
+ img_obj (ndarray): Continuous image intensity distribution, with no NaNs
81
+ outside the ROI.
82
+ roi_obj (ndarray): Array of the mask defining the ROI.
83
+ res (List[float]): [a,b,c] vector specifying the resolution of the volume in mm.
84
+ XYZ resolution (world), or JIK resolution (intrinsic matlab).
85
+
86
+ Returns:
87
+ float: Global intensity peak.
88
+ """
89
+ return get_glob_peak(img_obj, roi_obj, res)