Source code for niftynet.contrib.evaluation.segmentation_evaluations
"""
This module holds built-in segmentation evaluations without tests
"""
import os
import numpy as np
import pandas as pd
from scipy import ndimage
from niftynet.evaluation.base_evaluations import BaseEvaluation
from niftynet.evaluation.segmentation_evaluations import \
PerComponentEvaluation, connected_components, cached_label_binarizer, \
union_of_seg_for_each_ref_cc
from niftynet.io.misc_io import save_data_array
[docs]class com_ref(PerComponentEvaluation):
"""
Computes the centers of mass of each component in the reference standard
"""
[docs] def metric_from_binarized(self, seg, ref):
"""
:param seg: numpy array with binary mask from inferred segmentation
:param ref: numpy array with binary mask from reference segmentation
:return: dict of centers of mass in each axis
"""
return {d: 'com_ref_' + x
for d, x in zip('XYZ', ndimage.center_of_mass(ref))}
[docs]class ErrorMapsCC(BaseEvaluation):
"""
Create 3 maps of connected component detection:
tpc_map shows each detected ref cc (having at least on seg cc that
overlaps) and the union of all overlapping seg ccs
fnc_map shows all ref ccs that were not detected
fpc_map shows all seg ccs that did not overlap any ref ccs
Note we currently arbitrarily limit image generation to binary problems
"""
[docs] def layer_op(self, subject_id, data):
analyses = self.app_param.evaluation_units.split(',')
if 'label' not in analyses and 'foreground' not in analyses:
raise ValueError('ErrorMaps work with label or foreground '
'analyses only')
if self.app_param.num_classes > 2:
raise ValueError('ErrorMaps work with binary segmentations only')
binarizer = cached_label_binarizer(1, self.app_param.output_prob)
seg, ref = binarizer(data)
cc_func = connected_components
cc_seg, cc_ref = cc_func(seg, ref, self.app_param.output_prob)
cc_aggregator = union_of_seg_for_each_ref_cc
ccs = cc_aggregator(cc_ref, cc_seg)
tp_seg_labels = set(s for seg_l, ref_l in ccs for s in seg_l)
tp_ref_labels = set(r for seg_l, ref_l in ccs for r in ref_l if len(
seg_l))
fn_ref_labels = set(range(1, cc_ref[1])) - tp_ref_labels
fp_seg_labels = set(range(1, cc_seg[1])) - tp_seg_labels
maps = {}
maps['tpc_map'] = np.logical_or(cc_seg in tp_seg_labels,
cc_ref in tp_ref_labels)
maps['fnc_map'] = cc_ref in fn_ref_labels
maps['fpc_map'] = cc_seg in fp_seg_labels
image_idx = self.reader.get_image_index(subject_id)
file_path = os.path.join(self.eval_param.save_csv_dir, 'images')
out = {'subject_id': subject_id}
for key in maps:
out[key] = os.path.join(file_path, subject_id + '_' + key + '.nii')
save_data_array(file_path,
subject_id + '_' + key + '.nii',
maps[key],
self.reader.output_list[image_idx]['label'], 0)
pdf = pd.DataFrame.from_records([out], ('subject_id',))
return [pdf]