Source code for CPAC.sca.utils

# Copyright (C) 2012-2024  C-PAC Developers

# This file is part of C-PAC.

# C-PAC is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.

# C-PAC is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
# License for more details.

# You should have received a copy of the GNU Lesser General Public
# License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.
import os

from CPAC.utils.monitoring import IFLOGGER


[docs] def compute_fisher_z_score(correlation_file, timeseries_one_d): """ Computes the fisher z transform of the input correlation map If the correlation map contains data for multiple ROIs then the function returns z score for each ROI as a seperate nifti file. Parameters ---------- correlation_file : string Input correlations file Returns ------- out_file : list (nifti files) list of z_scores for mask or ROI """ import os import numpy as np import nibabel as nib roi_numbers = [] if "#" in open(timeseries_one_d, "r").readline().rstrip("\r\n"): roi_numbers = ( open(timeseries_one_d, "r") .readline() .rstrip("\r\n") .replace("#", "") .split("\t") ) corr_img = nib.load(correlation_file) corr_data = corr_img.get_fdata() hdr = corr_img.header corr_data = np.log((1 + corr_data) / (1 - corr_data)) / 2.0 dims = corr_data.shape out_file = [] if len(dims) == 5 or len(roi_numbers) > 0: if len(dims) == 5: x, y, z, one, roi_number = dims corr_data = np.reshape(corr_data, (x * y * z, roi_number), order="F") for i in range(0, len(roi_numbers)): sub_data = corr_data if len(dims) == 5: sub_data = np.reshape(corr_data[:, i], (x, y, z), order="F") sub_img = nib.Nifti1Image( sub_data, header=corr_img.header, affine=corr_img.affine ) sub_z_score_file = os.path.join( os.getcwd(), "z_score_ROI_number_%s.nii.gz" % (roi_numbers[i]) ) sub_img.to_filename(sub_z_score_file) out_file.append(sub_z_score_file) else: z_score_img = nib.Nifti1Image(corr_data, header=hdr, affine=corr_img.affine) z_score_file = os.path.join(os.getcwd(), "z_score.nii.gz") z_score_img.to_filename(z_score_file) out_file.append(z_score_file) return out_file
def check_ts(in_file): import os import numpy as np if in_file.endswith(".txt"): try: timepoints, rois = np.loadtxt(in_file).shape except ValueError: timepoints = np.loadtxt(in_file).shape[0] rois = 1 out_file = in_file elif in_file.endswith(".csv") or in_file.endswith(".1D"): csv_array = np.genfromtxt(in_file, delimiter=",") if np.isnan(csv_array[0][0]): csv_array = csv_array[1:] timepoints, rois = csv_array.shape # multiple regression (fsl_glm) needs this format for -design input out_file = os.path.join( os.getcwd(), os.path.basename(in_file).replace(".csv", ".txt") ) np.savetxt(out_file, csv_array, delimiter="\t") if rois > timepoints: message = ( f"\n\n\n****The number of timepoints ({timepoints}) is smaller than the" f" number of ROIs to run ({rois}) - therefore the GLM is underspecified" " and can't run.****\n\n\n" ) raise ValueError(message) else: return out_file
[docs] def map_to_roi(timeseries, maps): r""" Renames the outputs of the temporal multiple regression workflow for sca according to the header information of the timeseries.txt file that was passed NOTE: This is only run if the temporal regression is run as part of sca (which = 'RT') when calling the temporal regression workflow. If you run the temporal regression workflow manually, don\'t set (which = 'RT') unless you provide a timeseries.txt file with a header containing the names of the timeseries. Parameters ---------- timeseries : string Input timeseries.txt file maps : List (nifti files) List of output files generated by the temporal regression workflow if (which == 'RT') Returns ------- labels : List (strings) List of names that the output files should be renamed to maps : List (nifti files) List of output files generated by the temporal regression workflow if (which == 'RT') """ import pandas as pd testMat = pd.read_csv(timeseries) timepoints, rois = testMat.shape if rois > timepoints: IFLOGGER.warning( "The number of timepoints is smaller than the number " "of ROIs to run - therefore the GLM is " "underspecified and can't run." ) # pull in the ROI labels from the header of the extracted timeseries # CSV file with open(timeseries, "r") as f: roi_file_lines = f.read().splitlines() roi_err = ( "\n\n[!] The output of 3dROIstats, used in extracting " "the timeseries, was not in the expected format.\n\nROI " f"output file: {timeseries}\n\n" ) for line in roi_file_lines: if "Mean_" in line: try: roi_list = line.split(",") # clear out any blank strings/non ROI labels in the list roi_list = [x for x in roi_list if "Mean" in x] # rename labels roi_list = [ x.replace("Mean", "sca_tempreg_z_maps_roi") .replace(" ", "") .replace("#", "") for x in roi_list ] except: raise Exception(roi_err) break else: raise Exception(roi_err) new_labels = [] for roi_label in roi_list: new_labels.append(os.path.join(os.getcwd(), roi_label)) len(maps) maps.sort() # if not numMaps / 2 == rois: # raise Exception('You specified {0} timeseries but only {1} spatial ' # 'maps were generated'.format(str(rois), # str(numMaps/2))) maps = maps[:rois] return roi_list, maps