示例#1
0
    def __compute_subcortical_structures_location(self, volume, spacing, category=None, reference='BCB'):
        distances = {}
        overlaps = {}
        distances_columns = []
        overlaps_columns = []
        tract_cutoff = 0.5
        if reference == 'BrainLab':
            tract_cutoff = 0.25

        tracts_dict = ResourcesConfiguration.getInstance().subcortical_structures['MNI'][reference]
        for i, tfn in enumerate(tracts_dict.keys()):
            reg_tract_ni = nib.load(tracts_dict[tfn])
            reg_tract = reg_tract_ni.get_data()[:]
            reg_tract[reg_tract < tract_cutoff] = 0
            reg_tract[reg_tract >= tract_cutoff] = 1
            overlap_volume = np.logical_and(reg_tract, volume).astype('uint8')
            distances_columns.append('distance_' + tfn.split('.')[0][:-4] + '_' + category)
            overlaps_columns.append('overlap_' + tfn.split('.')[0][:-4] + '_' + category)
            if np.count_nonzero(overlap_volume) != 0:
                distances[tfn] = -1.
                overlaps[tfn] = (np.count_nonzero(overlap_volume) / np.count_nonzero(volume)) * 100.
            else:
                dist = -1.
                if np.count_nonzero(reg_tract) > 0:
                    dist = hd95(volume, reg_tract, voxelspacing=reg_tract_ni.header.get_zooms(), connectivity=1)
                distances[tfn] = dist
                overlaps[tfn] = 0.

        self.diagnosis_parameters.statistics[category]['Overall'].mni_space_subcortical_structures_overlap[reference] = overlaps
        self.diagnosis_parameters.statistics[category]['Overall'].mni_space_subcortical_structures_distance[reference] = distances
示例#2
0
    def __init__(self, input_filename, input_segmentation, preprocessing_scheme):
        self.input_filename = input_filename
        self.input_segmentation = input_segmentation
        self.preprocessing_scheme = preprocessing_scheme
        self.output_path = ResourcesConfiguration.getInstance().output_folder

        # Working with Gd-enhanced T1-weighted MRI volume as input for now.
        self.atlas_brain_filepath = ResourcesConfiguration.getInstance().mni_atlas_filepath_T1
        self.from_slicer = ResourcesConfiguration.getInstance().from_slicer
        self.registration_runner = ANTsRegistration()
        self.diagnosis_parameters = NeuroDiagnosisParameters()

        self.output_report_filepath = os.path.join(self.output_path, 'report.txt')
        if os.path.exists(self.output_report_filepath):
            os.remove(self.output_report_filepath)

        self.tumor_multifocal = None
示例#3
0
    def __compute_resection_features(self, volume, category=None):
        resection_probability_map_filepath = None
        if self.diagnosis_parameters.statistics[category]['Overall'].left_laterality_percentage >= 50.:  # Tumor in the left hemi-sphere
            resection_probability_map_filepath = ResourcesConfiguration.getInstance().mni_resection_maps['Probability']['Left']
        else:
            resection_probability_map_filepath = ResourcesConfiguration.getInstance().mni_resection_maps['Probability']['Right']

        resection_probability_map_ni = nib.load(resection_probability_map_filepath)
        resection_probability_map = resection_probability_map_ni.get_data()[:]
        resection_probability_map = np.nan_to_num(resection_probability_map)
        tumor_voxels_count = np.count_nonzero(volume)
        total_resectability = np.sum(resection_probability_map[volume != 0])
        resectable_volume = total_resectability * 1e-3
        residual_tumor_volume = (tumor_voxels_count * 1e-3) - resectable_volume
        avg_resectability = total_resectability / tumor_voxels_count

        self.diagnosis_parameters.statistics[category]['Overall'].mni_space_expected_residual_tumor_volume = residual_tumor_volume
        self.diagnosis_parameters.statistics[category]['Overall'].mni_space_expected_resectable_tumor_volume = resectable_volume
        self.diagnosis_parameters.statistics[category]['Overall'].mni_space_resectability_index = avg_resectability
示例#4
0
def diagnose_main(input_volume_filename,
                  input_segmentation_filename,
                  output_folder,
                  preprocessing_scheme='P2',
                  gpu_id='-1'):
    env = ResourcesConfiguration.getInstance()
    env.set_environment(output_dir=output_folder)
    os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
    os.environ["CUDA_VISIBLE_DEVICES"] = gpu_id

    diagnose(input_filename=input_volume_filename,
             input_segmentation=input_segmentation_filename,
             preprocessing_scheme=preprocessing_scheme)
示例#5
0
    def __compute_lateralisation(self, volume, category=None):
        brain_lateralisation_mask_ni = load_nifti_volume(ResourcesConfiguration.getInstance().mni_atlas_lateralisation_mask_filepath)
        brain_lateralisation_mask = brain_lateralisation_mask_ni.get_data()[:]

        right_side_percentage = np.count_nonzero((brain_lateralisation_mask == 1) & (volume != 0)) / np.count_nonzero(
            (volume != 0))
        left_side_percentage = np.count_nonzero((brain_lateralisation_mask == 2) & (volume != 0)) / np.count_nonzero(
            (volume != 0))

        left_laterality_percentage = np.round(left_side_percentage * 100., 2)
        right_laterality_percentage = np.round(right_side_percentage * 100., 2)
        midline_crossing = True if max(left_laterality_percentage, right_laterality_percentage) < 100. else False

        self.diagnosis_parameters.statistics[category]['Overall'].left_laterality_percentage = left_side_percentage
        self.diagnosis_parameters.statistics[category]['Overall'].right_laterality_percentage = right_side_percentage
        self.diagnosis_parameters.statistics[category]['Overall'].laterality_midline_crossing = midline_crossing
示例#6
0
    def run_diagnosis(self):
        if not os.path.exists(self.input_image_filepath) or not os.path.exists(
                self.output_folderpath):
            self.standardOutputWritten(
                'Process could not be started - The 1st and 2nd above-fields must be filled in.\n'
            )
            return

        self.run_button.setEnabled(False)
        self.prompt_lineedit.clear()
        self.main_display_tabwidget.setCurrentIndex(1)
        QApplication.processEvents(
        )  # to immidiently update GUI after button is clicked
        self.seg_preprocessing_scheme = 'P1' if self.settings_seg_preproc_menu_p1_action.isChecked(
        ) else 'P2'

        try:
            start_time = time.time()
            print('Initialize - Begin (Step 0/6)')
            from diagnosis.main import diagnose_main
            print('Initialize - End (Step 0/6)')
            print('Step runtime: {} seconds.'.format(
                np.round(time.time() - start_time, 3)) + "\n")
            diagnose_main(
                input_volume_filename=self.input_image_filepath,
                input_segmentation_filename=self.input_annotation_filepath,
                output_folder=self.output_folderpath,
                preprocessing_scheme=self.seg_preprocessing_scheme)
        except Exception as e:
            print('{}'.format(traceback.format_exc()))
            self.run_button.setEnabled(True)
            self.standardOutputWritten(
                'Process could not be completed - Issue arose.\n')
            QApplication.processEvents()
            return

        self.run_button.setEnabled(True)
        results_filepath = os.path.join(
            ResourcesConfiguration.getInstance().output_folder, 'report.txt')
        self.results_textedit.setPlainText(open(results_filepath, 'r').read())
        self.main_display_tabwidget.setCurrentIndex(2)
示例#7
0
    def __compute_cortical_structures_location(self, volume, category=None, reference='MNI'):
        regions_data = ResourcesConfiguration.getInstance().cortical_structures['MNI'][reference]
        region_mask_ni = nib.load(regions_data['Mask'])
        region_mask = region_mask_ni.get_data()
        lobes_description = pd.read_csv(regions_data['Description'])

        total_lobes_labels = np.unique(region_mask)[1:]  # Removing the background label with value 0.
        overlap_per_lobe = {}
        for li in total_lobes_labels:
            overlap = volume[region_mask == li]
            ratio_in_lobe = np.count_nonzero(overlap) / np.count_nonzero(volume)
            overlap = np.round(ratio_in_lobe * 100., 2)
            region_name = ''
            if reference == 'MNI':
                region_name = reference + '_' + lobes_description.loc[lobes_description['Label'] == li]['Region'].values[0] + '_' + lobes_description.loc[lobes_description['Label'] == li]['Laterality'].values[0] + '_' + category
            elif reference == 'Harvard-Oxford':
                region_name = reference + '_' + lobes_description.loc[lobes_description['Label'] == li]['Region'].values[0] + '_' + category
            else:
                region_name = reference + '_' + lobes_description.loc[lobes_description['Label'] == li]['Region'].values[0] + '_' + category
            overlap_per_lobe[region_name] = overlap
        self.diagnosis_parameters.statistics[category]['Overall'].mni_space_cortical_structures_overlap[reference] = overlap_per_lobe
示例#8
0
def perform_brain_masking(image_filepath, mask_filepath):
    """
    Set to 0 any voxel that does not belong to the brain mask.
    :param image_filepath: path to the main MRI volume
    :param mask_filepath: path to the brain segmentation mask
    :return: masked_image_filepath
    """
    image_ni = load_nifti_volume(image_filepath)
    brain_mask_ni = load_nifti_volume(mask_filepath)

    image = image_ni.get_data()[:]
    brain_mask = brain_mask_ni.get_data()[:]
    image[brain_mask == 0] = 0

    tmp_folder = os.path.join(
        ResourcesConfiguration.getInstance().output_folder, 'tmp')
    os.makedirs(tmp_folder, exist_ok=True)
    masked_input_filepath = os.path.join(
        tmp_folder,
        os.path.basename(image_filepath).split('.')[0] + '_masked.nii.gz')
    nib.save(nib.Nifti1Image(image, affine=image_ni.affine),
             masked_input_filepath)
    return masked_input_filepath
示例#9
0
def perform_brain_extraction(image_filepath):
    brain_predictions_file = perform_custom_brain_extraction(
        image_filepath,
        ResourcesConfiguration.getInstance().output_folder)

    return brain_predictions_file
示例#10
0
    def run(self):
        tmp_timer = 0
        start_time = time.time()
        self.input_filename = adjust_input_volume_for_nifti(self.input_filename, self.output_path)

        # Generating the brain mask for the input file
        print('Brain extraction - Begin (Step 1/6)')
        brain_mask_filepath = perform_brain_extraction(image_filepath=self.input_filename)
        print('Brain extraction - End (Step 1/6)')
        print('Step runtime: {} seconds.'.format(round(time.time() - start_time - tmp_timer, 3)) + "\n")
        tmp_timer = time.time()

        # Generating brain-masked fixed and moving images
        print('Registration preprocessing - Begin (Step 2/6)')
        input_masked_filepath = perform_brain_masking(image_filepath=self.input_filename,
                                                      mask_filepath=brain_mask_filepath)
        atlas_masked_filepath = perform_brain_masking(image_filepath=self.atlas_brain_filepath,
                                                      mask_filepath=ResourcesConfiguration.getInstance().mni_atlas_brain_mask_filepath)
        print('Registration preprocessing - End (Step 2/6)')
        print('Step runtime: {} seconds.'.format(round(time.time() - tmp_timer, 3)) + "\n")
        tmp_timer = time.time()

        # Performing registration
        print('Registration - Begin (Step 3/6)')
        self.registration_runner.compute_registration(fixed=atlas_masked_filepath, moving=input_masked_filepath,
                                                      registration_method='sq')
        print('Registration - End (Step 3/6)')
        print('Step runtime: {} seconds.'.format(round(time.time() - tmp_timer, 3)) + "\n")
        tmp_timer = time.time()

        # Performing tumor segmentation
        if not os.path.exists(self.input_segmentation):
            print('Tumor segmentation - Begin (Step 4/6)')
            self.input_segmentation = self.__perform_tumor_segmentation(brain_mask_filepath)
            print('Tumor segmentation - End (Step 4/6)')
            print('Step runtime: {} seconds.'.format(round(time.time() - tmp_timer, 3)) + "\n")
            tmp_timer = time.time()

        print('Apply registration - Begin (Step 5/6)')
        # Registering the tumor to the atlas
        self.registration_runner.apply_registration_transform(moving=self.input_segmentation,
                                                              fixed=self.atlas_brain_filepath,
                                                              interpolation='nearestNeighbor')
        # Dumping the different atlas labels
        self.registration_runner.dump_mni_atlas_labels()

        # Registering the brain lobes to the patient's space
        self.registration_runner.apply_registration_inverse_transform(moving=ResourcesConfiguration.getInstance().cortical_structures['MNI']['MNI']['Mask'],
                                                                      fixed=self.input_filename,
                                                                      interpolation='nearestNeighbor',
                                                                      label='MNI')
        self.registration_runner.apply_registration_inverse_transform(moving=ResourcesConfiguration.getInstance().cortical_structures['MNI']['Schaefer7']['Mask'],
                                                                      fixed=self.input_filename,
                                                                      interpolation='nearestNeighbor',
                                                                      label='Schaefer7')
        self.registration_runner.apply_registration_inverse_transform(moving=ResourcesConfiguration.getInstance().cortical_structures['MNI']['Schaefer17']['Mask'],
                                                                      fixed=self.input_filename,
                                                                      interpolation='nearestNeighbor',
                                                                      label='Schaefer17')
        self.registration_runner.apply_registration_inverse_transform(moving=ResourcesConfiguration.getInstance().cortical_structures['MNI']['Harvard-Oxford']['Mask'],
                                                                      fixed=self.input_filename,
                                                                      interpolation='nearestNeighbor',
                                                                      label='Harvard-Oxford')
        print('Apply registration - End (Step 5/6)')
        print('Step runtime: {} seconds.'.format(round(time.time() - tmp_timer, 3)) + "\n")
        tmp_timer = time.time()

        # Computing tumor location and statistics
        print('Generate report - Begin (Step 6/6)')
        self.__compute_statistics()
        self.diagnosis_parameters.to_txt(self.output_report_filepath)
        self.diagnosis_parameters.to_csv(self.output_report_filepath[:-4] + '.csv')
        print('Generate report - End (Step 6/6)')
        print('Step runtime: {} seconds.'.format(time.time() - tmp_timer) + "\n")
        print('Total processing time: {} seconds.'.format(round(time.time() - start_time, 3)))
        print('--------------------------------')

        # Cleaning the temporary files
        tmp_folder = os.path.join(self.output_path, 'tmp')
        shutil.rmtree(tmp_folder)