Skip to content

oxytcmri.domain.use_cases.segment_dti_abnormal_values

This module segments the abnormal values in DTI images using the normative values computed in each center from healthy subjects.

Classes:

Name Description
DTIThresholds

Encapsulates thresholds for detecting abnormal DTI values.

ThresholdStrategy

Strategy interface for computing thresholds for abnormal DTI values.

QuantileThresholdStrategy

A strategy that computes thresholds based on quantiles of normative values.

MeanThresholdStrategy

A strategy that computes thresholds based on the mean and standard deviation of normative values.

InterQuartileRangeThresholdStrategy

A strategy that computes thresholds based on the interquartile range (IQR) of normative values.

SegmentationMerger

Abstract interface for merging MRI segmentations.

SegmentDTIAbnormalValues

Segment abnormal values in DTI images compared to normative values (computed in each center from healthy subjects).

Attributes:

Name Type Description
logger

logger = logging.getLogger(__name__) module-attribute

DTIThresholds(high_threshold, low_threshold) dataclass

Encapsulates thresholds for detecting abnormal DTI values.

Parameters:

Name Type Description Default
high_threshold float

The upper threshold - values above this are considered abnormally high. If None, threshold will be set to inf.

required
low_threshold float

The lower threshold - values below this are considered abnormally low. If None, threshold will be set to -inf.

required

Methods:

Name Description
get_abnormality_type

Determine if a value is abnormal and return the type of abnormality.

Attributes:

Name Type Description
high_threshold Optional[float]
low_threshold Optional[float]

high_threshold instance-attribute

low_threshold instance-attribute

get_abnormality_type(value)

Determine if a value is abnormal and return the type of abnormality.

Parameters:

Name Type Description Default
value float

The DTI value to check

required

Returns:

Type Description
Optional[AbnormalValueType]

The type of abnormality (HIGH or LOW), or None if normal

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def get_abnormality_type(self, value: float) -> Optional[AbnormalValueType]:
    """
    Determine if a value is abnormal and return the type of abnormality.

    Parameters
    ----------
    value : float
        The DTI value to check

    Returns
    -------
    Optional[AbnormalValueType]
        The type of abnormality (HIGH or LOW), or None if normal
    """
    if value > self.high_threshold:
        return AbnormalValueType.HIGH
    elif value < self.low_threshold:
        return AbnormalValueType.LOW
    return None

ThresholdStrategy(normative_value_repository, center_repository)

Bases: ABC

Strategy interface for computing thresholds for abnormal DTI values.

Initialize the strategy with a normative value repository and center.

Parameters:

Name Type Description Default
normative_value_repository NormativeValueRepository

The repository to fetch normative values

required
center_repository CenterRepository

The repository to fetch center information

required

Methods:

Name Description
compute_thresholds

Compute thresholds for a specific DTI metric, atlas, and label.

Attributes:

Name Type Description
normative_value_repository
center_repository
Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
def __init__(self,
             normative_value_repository: NormativeValueRepository,
             center_repository: CenterRepository):
    """
    Initialize the strategy with a normative value repository and center.

    Parameters
    ----------
    normative_value_repository : NormativeValueRepository
        The repository to fetch normative values
    center_repository : CenterRepository
        The repository to fetch center information
    """
    self.normative_value_repository = normative_value_repository
    self.center_repository = center_repository

normative_value_repository = normative_value_repository instance-attribute

center_repository = center_repository instance-attribute

compute_thresholds(dti_image, atlas, atlas_label) abstractmethod

Compute thresholds for a specific DTI metric, atlas, and label.

Parameters:

Name Type Description Default
dti_image DTIMap

The DTI map for which to compute thresholds

required
atlas Atlas

The atlas used for segmentation

required
atlas_label int

The specific atlas label for which to compute thresholds

required

Returns:

Type Description
DTIThresholds

Computed thresholds for the given parameters

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
@abstractmethod
def compute_thresholds(self, dti_image: DTIMap, atlas: Atlas, atlas_label: int) -> DTIThresholds:
    """
    Compute thresholds for a specific DTI metric, atlas, and label.

    Parameters
    ----------
    dti_image : DTIMap
        The DTI map for which to compute thresholds
    atlas : Atlas
        The atlas used for segmentation
    atlas_label : int
        The specific atlas label for which to compute thresholds

    Returns
    -------
    DTIThresholds
        Computed thresholds for the given parameters
    """

QuantileThresholdStrategy(normative_value_repository, center_repository, high_quantile=95, low_quantile=5)

Bases: ThresholdStrategy

A strategy that computes thresholds based on quantiles of normative values.

Initialize with quantiles for threshold computation.

Parameters:

Name Type Description Default
normative_value_repository NormativeValueRepository

The repository to fetch normative values

required
center_repository CenterRepository

The repository to fetch center information

required
high_quantile int

The quantile for the high threshold

95
low_quantile int

The quantile for the low threshold

5

Methods:

Name Description
compute_thresholds

Compute thresholds based on quantiles of normative values.

Attributes:

Name Type Description
high_quantile
low_quantile
Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
def __init__(self,
             normative_value_repository: NormativeValueRepository,
             center_repository: CenterRepository,
             high_quantile: int = 95,
             low_quantile: int = 5):
    """
    Initialize with quantiles for threshold computation.

    Parameters
    ----------
    normative_value_repository : NormativeValueRepository
        The repository to fetch normative values
    center_repository : CenterRepository
        The repository to fetch center information
    high_quantile : int
        The quantile for the high threshold
    low_quantile : int
        The quantile for the low threshold
    """
    super().__init__(normative_value_repository, center_repository)
    self.high_quantile = high_quantile
    self.low_quantile = low_quantile

high_quantile = high_quantile instance-attribute

low_quantile = low_quantile instance-attribute

compute_thresholds(dti_image, atlas, atlas_label)

Compute thresholds based on quantiles of normative values.

Parameters:

Name Type Description Default
dti_image DTIMap

The DTI map for which to compute thresholds

required
atlas Atlas

The atlas used for segmentation

required
atlas_label int

The specific atlas label for which to compute thresholds

required

Returns:

Type Description
DTIThresholds

Computed thresholds for the given parameters

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
def compute_thresholds(self, dti_image: DTIMap, atlas: Atlas, atlas_label: int) -> DTIThresholds:
    """
    Compute thresholds based on quantiles of normative values.

    Parameters
    ----------
    dti_image : DTIMap
        The DTI map for which to compute thresholds
    atlas : Atlas
        The atlas used for segmentation
    atlas_label : int
        The specific atlas label for which to compute thresholds

    Returns
    -------
    DTIThresholds
        Computed thresholds for the given parameters
    """
    # Get the center from the DTI image
    center = self.center_repository.get_by_mri_exam_id(dti_image.mri_exam_id)

    # Create a partial function to avoid passing the same parameters multiple times
    get_stat_value = partial(
        self._get_normative_value,
        center=center,
        atlas_label=atlas_label,
        atlas=atlas,
        dti_metric=dti_image.dti_metric
    )

    # Use the partial function to get the quantiles
    high_threshold = get_stat_value(
        statistic_strategy=StatisticsStrategies.get_by_name(f"quantile {self.high_quantile}")
    )
    low_threshold = get_stat_value(
        statistic_strategy=StatisticsStrategies.get_by_name(f"quantile {self.low_quantile}")
    )

    return DTIThresholds(high_threshold=high_threshold, low_threshold=low_threshold)

MeanThresholdStrategy(normative_value_repository, center_repository, high_deviation_factor=2.0, low_deviation_factor=2.0)

Bases: ThresholdStrategy

A strategy that computes thresholds based on the mean and standard deviation of normative values.

This is a dummy implementation for development and testing. In a real application, the computation would depend on the DTI metric and atlas.

Initialize with a z-score for threshold computation.

Parameters:

Name Type Description Default
normative_value_repository NormativeValueRepository

The repository to fetch normative values

required
center_repository CenterRepository

The repository to fetch center information

required
high_deviation_factor float

The factor to multiply the standard deviation for high threshold

2.0
low_deviation_factor float

The factor to multiply the standard deviation for low threshold

2.0

Methods:

Name Description
compute_thresholds

Compute thresholds based on the mean and standard deviation of normative values.

Attributes:

Name Type Description
high_deviation_factor
low_deviation_factor
Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
def __init__(self,
             normative_value_repository: NormativeValueRepository,
             center_repository: CenterRepository,
             high_deviation_factor: float = 2.0,
             low_deviation_factor: float = 2.0):
    """
    Initialize with a z-score for threshold computation.

    Parameters
    ----------
    normative_value_repository : NormativeValueRepository
        The repository to fetch normative values
    center_repository : CenterRepository
        The repository to fetch center information
    high_deviation_factor : float
        The factor to multiply the standard deviation for high threshold
    low_deviation_factor : float
        The factor to multiply the standard deviation for low threshold
    """
    super().__init__(normative_value_repository, center_repository)
    self.high_deviation_factor = high_deviation_factor
    self.low_deviation_factor = low_deviation_factor

high_deviation_factor = high_deviation_factor instance-attribute

low_deviation_factor = low_deviation_factor instance-attribute

compute_thresholds(dti_image, atlas, atlas_label)

Compute thresholds based on the mean and standard deviation of normative values.

Parameters:

Name Type Description Default
dti_image DTIMap

The DTI map for which to compute thresholds

required
atlas Atlas

The atlas used for segmentation

required
atlas_label int

The specific atlas label for which to compute thresholds

required

Returns:

Type Description
DTIThresholds

Computed thresholds for the given parameters

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
def compute_thresholds(self, dti_image: DTIMap, atlas: Atlas, atlas_label: int) -> DTIThresholds:
    """
    Compute thresholds based on the mean and standard deviation of normative values.

    Parameters
    ----------
    dti_image : DTIMap
        The DTI map for which to compute thresholds
    atlas : Atlas
        The atlas used for segmentation
    atlas_label : int
        The specific atlas label for which to compute thresholds

    Returns
    -------
    DTIThresholds
        Computed thresholds for the given parameters
    """
    # Get the center from the DTI image
    center = self.center_repository.get_by_mri_exam_id(dti_image.mri_exam_id)

    # Create a partial function to avoid passing the same parameters multiple times
    get_stat_value = partial(
        self._get_normative_value,
        center=center,
        atlas_label=atlas_label,
        atlas=atlas,
        dti_metric=dti_image.dti_metric
    )

    # Use the partial function to get the mean and standard deviation
    mean_value = get_stat_value(statistic_strategy=StatisticsStrategies.get_by_name("mean"))
    std_value = get_stat_value(statistic_strategy=StatisticsStrategies.get_by_name("standard deviation"))

    high_threshold = mean_value + self.high_deviation_factor * std_value
    low_threshold = mean_value - self.low_deviation_factor * std_value
    return DTIThresholds(high_threshold=high_threshold, low_threshold=low_threshold)

InterQuartileRangeThresholdStrategy(normative_value_repository, center_repository, high_deviation_factor=2.0, low_deviation_factor=2.0)

Bases: ThresholdStrategy

A strategy that computes thresholds based on the interquartile range (IQR) of normative values.

Initialize with a z-score for threshold computation.

Parameters:

Name Type Description Default
normative_value_repository NormativeValueRepository

The repository to fetch normative values

required
center_repository CenterRepository

The repository to fetch center information

required
high_deviation_factor float

The factor to multiply the interquartile range for high threshold

2.0
low_deviation_factor float

The factor to multiply the interquartile range for low threshold

2.0

Methods:

Name Description
compute_thresholds

Compute thresholds based on the interquartile range of normative values.

Attributes:

Name Type Description
high_deviation_factor
low_deviation_factor
Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
def __init__(self,
             normative_value_repository: NormativeValueRepository,
             center_repository: CenterRepository,
             high_deviation_factor: float = 2.0, low_deviation_factor: float = 2.0):
    """
    Initialize with a z-score for threshold computation.

    Parameters
    ----------
    normative_value_repository : NormativeValueRepository
        The repository to fetch normative values
    center_repository : CenterRepository
        The repository to fetch center information
    high_deviation_factor : float
        The factor to multiply the interquartile range for high threshold
    low_deviation_factor : float
        The factor to multiply the interquartile range for low threshold
    """
    super().__init__(normative_value_repository, center_repository)
    self.high_deviation_factor = high_deviation_factor
    self.low_deviation_factor = low_deviation_factor

high_deviation_factor = high_deviation_factor instance-attribute

low_deviation_factor = low_deviation_factor instance-attribute

compute_thresholds(dti_image, atlas, atlas_label)

Compute thresholds based on the interquartile range of normative values.

Parameters:

Name Type Description Default
dti_image DTIMap

The DTI map for which to compute thresholds

required
atlas Atlas

The atlas used for segmentation

required
atlas_label int

The specific atlas label for which to compute thresholds

required

Returns:

Type Description
DTIThresholds

Computed thresholds for the given parameters

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
def compute_thresholds(self, dti_image: DTIMap, atlas: Atlas, atlas_label: int) -> DTIThresholds:
    """
    Compute thresholds based on the interquartile range of normative values.

    Parameters
    ----------
    dti_image : DTIMap
        The DTI map for which to compute thresholds
    atlas : Atlas
        The atlas used for segmentation
    atlas_label : int
        The specific atlas label for which to compute thresholds

    Returns
    -------
    DTIThresholds
        Computed thresholds for the given parameters
    """
    # Get the center from the DTI image
    center = self.center_repository.get_by_mri_exam_id(dti_image.mri_exam_id)

    # Create a partial function to avoid passing the same parameters multiple times
    get_stat_value = partial(
        self._get_normative_value,
        center=center,
        atlas_label=atlas_label,
        atlas=atlas,
        dti_metric=dti_image.dti_metric
    )

    # Use the partial function to get the first and third quartiles
    q1 = get_stat_value(statistic_strategy=StatisticsStrategies.get_by_name("quartile 25"))
    q3 = get_stat_value(statistic_strategy=StatisticsStrategies.get_by_name("quartile 75"))

    iqr = q3 - q1

    high_threshold = q3 + self.high_deviation_factor * iqr
    low_threshold = q1 - self.low_deviation_factor * iqr

    return DTIThresholds(high_threshold=high_threshold, low_threshold=low_threshold)

SegmentationMerger

Bases: ABC

Abstract interface for merging MRI segmentations. This interface respects the dependency inversion principle.

Methods:

Name Description
merge

Merges multiple segmentations into a single one.

merge(segmentations) abstractmethod

Merges multiple segmentations into a single one.

Parameters:

Name Type Description Default
segmentations List[DTIAbnormalValues]

List of segmentations to merge.

required

Returns:

Type Description
DTIAbnormalValues

The merged segmentation.

Raises:

Type Description
RuntimeError

If the segmentations cannot be merged.

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
@abstractmethod
def merge(self, segmentations: List[DTIAbnormalValues]) -> DTIAbnormalValues:
    """
    Merges multiple segmentations into a single one.

    Parameters
    ----------
    segmentations : List[DTIAbnormalValues]
        List of segmentations to merge.

    Returns
    -------
    DTIAbnormalValues
        The merged segmentation.

    Raises
    -------
    RuntimeError
        If the segmentations cannot be merged.
    """

SegmentDTIAbnormalValues(repositories_registry, threshold_strategy=None, segmentation_merger=None, dispatcher=None)

Segment abnormal values in DTI images compared to normative values (computed in each center from healthy subjects).

Initializes the SegmentDtiAbnormalValues use-case.

Methods:

Name Description
initialize_progress_bar

Initialize the progress bar with the total number of steps.

update_progress_bar

Update the progress bar by incrementing the current step and dispatching a progress event.

segment_all_mri_exams_of_patients

Segments all the MRI exams of all patients.

segment_dti_maps_associated_to_mri_exam

Segments the DTI maps associated with a given MRI exam.

segment_dti_map

Segments the DTI map, i.e. build a map with values indicating the abnormal values in the input DTI map.

segment_dti_map_for_atlas

Segments the DTI map for a given atlas, using the normative values.

merge_segmentations

Merges the segmentations into a single MRIData object.

compute_thresholds

Compute thresholds for abnormal values detection.

mark_abnormal_voxels

Mark voxels with abnormal values in the specified atlas region.

Attributes:

Name Type Description
subjects_repository SubjectRepository
mri_repository MRIExamRepository
atlas_repository AtlasRepository
centers_repository CenterRepository
normative_values_repository NormativeValueRepository
dispatcher
threshold_strategy
segmentation_merger
current_step
total_steps
Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
def __init__(self,
             repositories_registry: RepositoriesRegistry,
             threshold_strategy: Optional[ThresholdStrategy] = None,
             segmentation_merger: Optional[SegmentationMerger] = None,
             dispatcher: Optional[EventDispatcher] = None):
    """
    Initializes the SegmentDtiAbnormalValues use-case.
    """
    self.threshold_strategy = None
    self.subjects_repository: SubjectRepository = repositories_registry.get_repository(Subject)
    self.mri_repository: MRIExamRepository = repositories_registry.get_repository(MRIExam)
    self.atlas_repository: AtlasRepository = repositories_registry.get_repository(Atlas)
    self.centers_repository: CenterRepository = repositories_registry.get_repository(Center)
    self.normative_values_repository: NormativeValueRepository = (
        repositories_registry.get_repository(NormativeValue))

    self.dispatcher = dispatcher

    # Define the default threshold strategy to MeanThresholdStrategy
    default_threshold_strategy = QuantileThresholdStrategy(
        normative_value_repository=self.normative_values_repository,
        center_repository=self.centers_repository
    )
    self.threshold_strategy = threshold_strategy or default_threshold_strategy

    # Define the default segmentation merger
    self.segmentation_merger = segmentation_merger

    # Initialize the progress bar attributes
    self.current_step = None
    self.total_steps = None

subjects_repository = repositories_registry.get_repository(Subject) instance-attribute

mri_repository = repositories_registry.get_repository(MRIExam) instance-attribute

atlas_repository = repositories_registry.get_repository(Atlas) instance-attribute

centers_repository = repositories_registry.get_repository(Center) instance-attribute

normative_values_repository = repositories_registry.get_repository(NormativeValue) instance-attribute

dispatcher = dispatcher instance-attribute

threshold_strategy = threshold_strategy or default_threshold_strategy instance-attribute

segmentation_merger = segmentation_merger instance-attribute

current_step = None instance-attribute

total_steps = None instance-attribute

initialize_progress_bar(total_steps)

Initialize the progress bar with the total number of steps.

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
483
484
485
486
487
488
489
490
491
def initialize_progress_bar(self,
                            total_steps: int) -> None:
    """
    Initialize the progress bar with the total number of steps.
    """
    self.current_step = 0
    self.total_steps = total_steps
    if self.dispatcher is not None:
        self.dispatcher.dispatch(ProgressEvent(0, self.total_steps))

update_progress_bar()

Update the progress bar by incrementing the current step and dispatching a progress event.

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
493
494
495
496
497
498
499
def update_progress_bar(self) -> None:
    """
    Update the progress bar by incrementing the current step and dispatching a progress event.
    """
    if self.dispatcher is not None:
        self.current_step += 1
        self.dispatcher.dispatch(ProgressEvent(self.current_step, self.total_steps))

segment_all_mri_exams_of_patients(dti_metrics)

Segments all the MRI exams of all patients.

It will look for all the patients in the SubjectRepository and for each patient, it will segment the DTI images. This segmentation process will have access to the normative values stored in the NormativeValuesRepository.

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
527
528
529
530
531
532
533
534
535
536
537
538
539
540
def segment_all_mri_exams_of_patients(self,
                                      dti_metrics: List[DTIMetric]):
    """
    Segments all the MRI exams of all patients.

    It will look for all the patients in the SubjectRepository and for each patient, it will segment the DTI images.
    This segmentation process will have access to the normative values stored in the NormativeValuesRepository.
    """
    # Get all the patients
    patients = self.subjects_repository.list_all_patients()
    for patient in patients:
        # Get the MRI exam for the patient
        mri_exam = self.mri_repository.get_exam_for_subject(patient)
        self.segment_dti_maps_associated_to_mri_exam(mri_exam, dti_metrics)

segment_dti_maps_associated_to_mri_exam(mri_exam, dti_metrics)

Segments the DTI maps associated with a given MRI exam. This method will look for all the DTI maps associated with the MRI exam and segment them.

Parameters:

Name Type Description Default
dti_metrics List[DTIMetric]

The DTI metrics to segment.

required
mri_exam MRIExam

The MRI exam to segment the DTI maps for.

required
Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
def segment_dti_maps_associated_to_mri_exam(self,
                                            mri_exam: MRIExam,
                                            dti_metrics: List[DTIMetric]) -> None:
    """
    Segments the DTI maps associated with a given MRI exam.
    This method will look for all the DTI maps associated with the MRI exam and segment them.

    Parameters
    ----------
    dti_metrics : List[DTIMetric]
        The DTI metrics to segment.
    mri_exam : MRIExam
        The MRI exam to segment the DTI maps for.
    """
    for dti_metric in dti_metrics:
        # Check if the segmentation is already done for this DTI metric
        try:
            mri_exam.get_segmented_dti_abnormal_values(dti_metric)
            logger.info(f"DTI metric {dti_metric} already segmented for MRI exam {mri_exam.id}")
        except LookupError:
            logger.info(f"Segmentation for DTI metric {dti_metric} not found in MRI exam {mri_exam.id}: "
                        f"proceeding with segmentation.")
            # Get the DTI map associated with the DTI metric
            dti_image = mri_exam.get_dti_map(dti_metric)
            segmented_dti_map = self.segment_dti_map(dti_image)

            # Add the segmented DTI map to the MRI exam
            mri_exam.add_mri_data(segmented_dti_map)

        self.update_progress_bar()

    # Save the whole MRI exam in the repository
    self.mri_repository.save(mri_exam)

segment_dti_map(dti_image)

Segments the DTI map, i.e. build a map with values indicating the abnormal values in the input DTI map.

Parameters:

Name Type Description Default
dti_image DTIMap

The DTI map to segment.

required
Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
576
577
578
579
580
581
582
583
584
585
586
587
588
589
def segment_dti_map(self, dti_image: DTIMap) -> DTIAbnormalValues:
    """
    Segments the DTI map, i.e. build a map with values indicating the abnormal values in the input DTI map.

    Parameters
    ----------
    dti_image : DTIMap
        The DTI map to segment.
    """
    logger.info(f"Segmenting DTI map: {dti_image}")
    segmentations = []
    for atlas in self.atlas_repository.list_all():
        segmentations.append(self.segment_dti_map_for_atlas(dti_image, atlas))
    return self.merge_segmentations(segmentations)

segment_dti_map_for_atlas(dti_image, atlas)

Segments the DTI map for a given atlas, using the normative values.

Parameters:

Name Type Description Default
dti_image DTIMap

The DTI map to segment.

required
atlas Atlas

The atlas to use for segmentation.

required

Returns:

Type Description
DTIAbnormalValues

The segmented DTI map with abnormal values.

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
def segment_dti_map_for_atlas(self, dti_image: DTIMap, atlas: Atlas) -> DTIAbnormalValues:
    """
    Segments the DTI map for a given atlas, using the normative values.

    Parameters
    ----------
    dti_image : DTIMap
        The DTI map to segment.
    atlas : Atlas
        The atlas to use for segmentation.

    Returns
    -------
    DTIAbnormalValues
        The segmented DTI map with abnormal values.
    """
    logger.info(f"Segmenting DTI map: {dti_image} for atlas: {atlas}")
    result = DTIAbnormalValues.from_dti_map(dti_image)
    for atlas_label in atlas.labels:
        thresholds = self.compute_thresholds(dti_image, atlas, atlas_label)
        self.mark_abnormal_voxels(dti_image, atlas, atlas_label, thresholds, result)
    return result

merge_segmentations(segmentations)

Merges the segmentations into a single MRIData object.

Parameters:

Name Type Description Default
segmentations List[DTIAbnormalValues]

The list of segmentations to merge.

required

Returns:

Type Description
DTIAbnormalValues

The merged segmentation.

Raises:

Type Description
RuntimeError

If the segmentation merger is not set.

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
def merge_segmentations(self, segmentations: List[DTIAbnormalValues]) -> DTIAbnormalValues:
    """
    Merges the segmentations into a single MRIData object.

    Parameters
    ----------
    segmentations : List[DTIAbnormalValues]
        The list of segmentations to merge.

    Returns
    -------
    DTIAbnormalValues
        The merged segmentation.

    Raises
    -------
    RuntimeError
        If the segmentation merger is not set.
    """
    if not self.segmentation_merger:
        raise RuntimeError("Segmentation merger is not set. Cannot merge segmentations.")

    return self.segmentation_merger.merge(segmentations)

compute_thresholds(dti_image, atlas, atlas_label)

Compute thresholds for abnormal values detection.

Parameters:

Name Type Description Default
dti_image DTIMap

The DTI map image to compute thresholds for

required
atlas Atlas

The atlas used for segmentation

required
atlas_label int

The atlas label to compute thresholds for

required

Returns:

Type Description
DTIThresholds

Thresholds for detecting abnormal values

Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
def compute_thresholds(self, dti_image: DTIMap, atlas: Atlas, atlas_label: int) -> DTIThresholds:
    """
    Compute thresholds for abnormal values detection.

    Parameters
    ----------
    dti_image : DTIMap
        The DTI map image to compute thresholds for
    atlas : Atlas
        The atlas used for segmentation
    atlas_label : int
        The atlas label to compute thresholds for

    Returns
    -------
    DTIThresholds
        Thresholds for detecting abnormal values
    """
    # Use the configured strategy to compute thresholds
    logger.debug(f"Computing thresholds for abnormal values in DTI map {dti_image} "
                 f"for atlas {atlas} and label {atlas_label}")
    return self.threshold_strategy.compute_thresholds(dti_image, atlas, atlas_label)

mark_abnormal_voxels(dti_image, atlas, atlas_label, thresholds, result)

Mark voxels with abnormal values in the specified atlas region.

Parameters:

Name Type Description Default
dti_image DTIMap

The DTI map image to analyze

required
atlas Atlas

The atlas used for segmentation

required
atlas_label int

The atlas label defining the region to analyze

required
thresholds DTIThresholds

Thresholds for detecting abnormal values

required
result DTIAbnormalValues

The result object where abnormal voxels will be marked

required
Source code in oxytcmri/domain/use_cases/segment_dti_abnormal_values.py
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
def mark_abnormal_voxels(self,
                         dti_image: DTIMap,
                         atlas: Atlas,
                         atlas_label: int,
                         thresholds: DTIThresholds,
                         result: DTIAbnormalValues) -> None:
    """
    Mark voxels with abnormal values in the specified atlas region.

    Parameters
    ----------
    dti_image : DTIMap
        The DTI map image to analyze
    atlas : Atlas
        The atlas used for segmentation
    atlas_label : int
        The atlas label defining the region to analyze
    thresholds : DTIThresholds
        Thresholds for detecting abnormal values
    result : DTIAbnormalValues
        The result object where abnormal voxels will be marked
    """
    logger.debug(f"Mark abnormal values for DTI map {dti_image}, "
                 f"in label {atlas_label} of atlas {atlas},"
                 f"with threshold {thresholds}")

    # Get the MRI exam associated with the DTI image
    mri_exam = cast(MRIExam, self.mri_repository.get_by_id(dti_image.mri_exam_id))

    # Get the atlas mask for the specified label
    atlas_segmentation = mri_exam.get_atlas_segmentation(atlas)
    atlas_mask = atlas_segmentation.create_mask([atlas_label])

    # Get the abnormal values mask for the DTI image
    abnormal_voxel_data = cast(AbnormalVoxelData, result.get_voxel_data())

    # Detect high and low values
    abnormally_high_mask = dti_image.get_mask_of_values_above_threshold(thresholds.high_threshold)
    high_in_region_mask = abnormally_high_mask.mask_with(atlas_mask)
    abnormal_voxel_data.mark_voxels_as(high_in_region_mask, AbnormalValueType.HIGH)

    abnormally_low_mask = dti_image.get_mask_of_values_below_threshold(thresholds.low_threshold)
    low_in_region_mask = abnormally_low_mask.mask_with(atlas_mask)
    abnormal_voxel_data.mark_voxels_as(low_in_region_mask, AbnormalValueType.LOW)