Welcome to cvrmap’s documentation!

class cvrmap.DataObj(data=None, sampling_frequency=None, data_type=None, path=None, label=None, figs=None, measurement_type=None, mask=None, baseline=None, units=None, img=None)

Class to keep together data with sampling freq and other useful information on the data

For most applications, we need the probe or fMRI data together with the corresponding sampling frequency. data_type must be “timecourse” or “map” or “bold”. Sampling frequency in Hz. label is a field used to put some human-readable struff to describe what the object is containing, e.g. ‘this is the denoised data’ fig is a figure object from plotly measurement_type is the type of the actual values, like ‘CVR’ or ‘delay’, or ‘concentration’. mask is a binary map, can be used to mask data in the case of ‘map’ or ‘bold’data_type.

bids_load(layout, filters, data_type, **kwargs)

Load DataObj from a BIDS layout and filters

data_type must be ‘timecourse’ or “map” or “bold”. The filter is used to extract both json and the actual data. kwargs is used to specify some options for the ‘timecourse’ type: if kwargs = {‘col’: 0}, then the first column of the .tsv file is extracted.

build_baseline()

Compute baseline of data and stores it in self.baseline. Only for self.data_type=’timecourse’

make_fig(fig_type, **kwargs)

Create figure object from the data in self

The figure is save in self.figs[fig_type]. fig_type: ‘plot’, ‘histogram’ or ‘lightbox’

If self.data_type is “timecourse”: fig_type must be ‘plot’ and plot the timecourse

kwargs in that case must have values for ‘title’, ‘xlabel’ and ‘ylabel’

If self.data_type is “map”:
If fig_type is histogram:

create a histogram. kwargs can be empty

If fig_type is lightbox:

create a lightbox. kwargs can be empty, but if not, it must have a single field called ‘background’. The corresponding value must be a DataObj of data_type = ‘map’ and will be used as a background image. Dimensions must match those of self.data. NB: the color scales are build automatically with hardcoded values, different for CVR and delays.

nifti_load(path)

Load a nifti image from path and stores it in a DataObj

save(path_to_save, path_to_ref=None)
For self.data_type == ‘map’ or self.data_type == ‘bold’:

Save data to path in nifti format using affine from ref path_to_ref: path to nifti file to extract affine data path_to_save: path where to save the nifti image

For self.data_type == ‘timecourse’:

Save timecourse data to path in .tsv.gz format - path_to_save must be something live /my/file/is/here and this function will write /my/file/is/here.tsv.gz and /my/file/is/here.json for timecourses path_to_save: path where to save the data path_to_ref: not needed in that case

cvrmap.add_cst_img_to_series(img, cst_img)

Take a 4D niimg and a 3D niimg and voxel-wise adds the value of the 3D img to the timeseries of the 4D img.

Args:

img: niimg, representing a 4D nifti cst_img: niimg, representing a 3D nifti

Returns:

niimg, sum of the 3D and the 4D img as described above.

cvrmap.arguments_manager(version)

Wrapper to define and read arguments for main function call

Args:

version: version to output when calling with -h

Returns:

args as read from command line call

class cvrmap.bcolors

Convenient colors for terminal prints

cvrmap.bold_denoising(bold_fn, mask_fn, melodic_mixing_df, noise_indexes, parameters)

BOLD signal denoising based on non-aggressive denoising.

Steps:
  • non-aggressive denoising (similar to what fsl_regfilt do)

  • highpass filtering (similar to fslmaths -bptf), using parameters[‘highpass_frequency’] (value in Hz)

  • re-add mean BOLD signal to filtered data

  • spatial smoothing using parameters[‘fwhm’]

Note: this function does not rely on FSL.

Args:

bold_fn: path to 4D nii to denoise mask_fn: path to BOLD mask melodic_mixing_df: pandas df with IC’s noise_indexes: list of int labelling the noise, 0-based parameters: dict, whose elements ‘fwhm’ and ‘highpass_frequency’ only are used. If parameters[‘fwhm’] is None, no smoothing is applied. parameters[‘highpass_frequency’] is passed to nilean.image.clean_img.

Returns:

DataObj, containing denoised data. Voxels outside mask as set to 0.

cvrmap.build_shifted_signal(probe, target, delta_t)

Shifts the probe signal by the amount delta_t, putting baseline values when extrapolation is needed. The baseline is read from probe.baseline; if undefined, the function first calls probe.build_baseline() to ensure it exists. Target is a signal used as a reference for the length and sampling frequency of the output.

Arguments:

probe: a DataObj with probe.data_type = ‘timecourse’ target: a DataObj with probe.data_type = ‘timecourse’. delta_t: an integer (positive, negative or zero)

Return:

DataObj with self.data with shifted points according to the given delta_t. Moreover, it is resampled to the sampling frequency in target, and it’s length is also adjusted to the one of the target.

cvrmap.compute_delays(reference, probe, shifts_option)

This function optimize linear correlation between the reference signal and shifted versions of the probe signal. This script involve potentially many recursion. It has several levels of usage, each with its own inputs/outputs.

Level 1:

  • Arguments:

    • reference: a DataObj with data_type=’timecourse’ and data of length N

    • probe: a DataObj with data_type=’timecourse’ and data of length N

    • shifts_option: must be set to None

  • Outputs:

    • slope, intercept, r, p, std: as in scipy.stats.linregress

  • Description:

    At this level the function simply calls scipy.stats.linregress(probe.data, reference.data)

Level 2:

  • Arguments:

    • reference: a DataObj with data_type=’timecourse’

    • probe: a DataObj with data_type=’timecourse’

    • shifts_option: an integer

  • Outputs:

    • slope, intercept, r, p, std: as in scipy.signal.linregress

  • Description:

    At this level the function first computes the shifted version of the probe timecourse, using shifts_option as the shift value. Note that reference.data and probe.data must not be of same lengths or sampling frequencies: the script takes care of harmonzing the sampling frequencies and array length.

Level 3:

  • Arguments:

    • reference: a DataObj with data_type=’timecourse’ and data of length N

    • probe: a DataObj with data_type=’timecourse’

    • shifts_option: a numpy array of any length

  • Outputs: delay, slope, intercept, correlation with:

    • delay: the time-shift that gave the best correlation coefficient for the shifted probe signal versus reference.data

    • slope, intercept, correlation: results of the corresponding fit (thus at optimal delay)

  • Description:

    Iterates over elements of shifts_option and calls each time itself at level 2 to extract all data from the fits at various shifts Then the shift giving the highest r-correlation score is selected and is returned, alongside the corresponding fit results (slope, intercept, r-score)

Level 4:

  • Arguments:

    • reference: a DataObj with data_type=’bold’. reference.mask must be set to some mask on which the computation will be done. reference.mask must have the same shape as reference.data[:,:,:,t]

    • probe: a DataObj with data_type=’timecourse’

    • shifts_option: dict with two keys:

      ** shifts_option[‘origin’]: an integer, used as the origin of times for the delay maps ** shifts_option[‘relative_values’]: a numpy array of any length, used to compute the delays

  • Outputs: a dict() with the following keys/values:

    • key: delay, value: a DataObj with data_type=’map’, measurement_type=’delay’, and delay.data[x,y,z] = delay optimizing the correlation between probe[‘signal].data and reference.data[x,y,z,:]

    • keys: intercept, slope, correlation, values: DataObjs with data_type=’map’, with data corresponding to the fit at optimum shift.

  • Description:

    This is the top-level usage of this function. It takes a bold series specified in reference.data, and loop over all it’s voxels provided reference.mask > 0. For each voxel, say (x,y,z), the corresponding time series reference.data[x,y,z,:] is then extracted and compute_delay is called at level 3 to find optimum time delay bewteen reference.data[x,y,z,:] and probe.data. The array shifts_option[‘relative_values’] gives the values on which the optimum search must be run over. The origin of time, given by shifts_option[‘origin’], will appear as 0 in the delay map.

    Helper on delay and origin of time:

    Say the probe signal has a delay of 8s with the global brain bold signal and we set shifts_option[‘origin’] = 0. Then if shifts_option[‘relative_values’] = [-10 -5 0 5 10], a voxel having a delay of 0s is to be thought as synced with the probe signal. So in that case, it might be more relevant to set shifts_option[‘origin’] to 8, so that a voxel with delay = 0 is now synced with the global signal instead.

cvrmap.compute_global_signal(data)

Computes whole-brain signal

Args:

data, a DataObj for some fMRI data

Returns:

DataObj of timecourse type with computed global signal

cvrmap.compute_response(intercept, slope, regressorbaseline, regressormean)

This function computes slope/(intercept + (regressorbaseline)*slope)

cvrmap.endtidalextract(physio)

Analyse physiological breathing data to extract etco2 curve

Inputs:

physio is DataObj

Returns:

etco2: DataObj with basically the upper enveloppe of physio.data baseline: DataObj with the baseline of the etco2 curve

cvrmap.gather_figures(objs)

Create fig from several DataObj of ‘timecourse’ type by superimposing their individual plots If two objects are given, the first one will have its y-axis on the left and the second on the right.

cvrmap.get_aroma_noise_ic_list(bids_filter, layout)

Get the list of Independent Components that were classified as noise by ICA-AROMA, from fmriprep outputs

Args:

bids_filter: dict, BIDS filter layout: BIDSlayout

Returns:

list, list of noise ICs

cvrmap.get_corrected_noiselist(probe, aroma_noise_ic_list, melodic_mixing_df, sf, noise_ic_pearson_r_threshold, aroma_flag)

Finds the noise independent components that do not correlate with the probe signal

Args:

probe: DataObj, the probe data aroma_noise_ic_list: list, noise IC from AROMA melodic_mixing_df: pandas dataframe, all MELODIC components sf: float, BOLD sampling frequency noise_ic_pearson_r_threshold: float, threshold for correlation to correct noise classification aroma_flag: bool, flag to use orignal aroma classification or not

Returns:

list, refined classification of noise regressors

cvrmap.get_custom_label(args)

Create custom label if specified

Args:

args: return from arguments_manager

Returns:

string for task entity

cvrmap.get_fmriprep_dir(args)

Get and check existence of fmriprep dir from options or default

Args:

args: return from arguments_manager

Returns:

path to fmriprep dir

cvrmap.get_mask(basic_filter, layout)

Load brain mask for subject

Args:

basic_filter: dict, BIDS filter layout: BIDS layout

Returns:

DataObj, brain mask

cvrmap.get_meanepi(img)

Compute temporal mean for fMRI data (calls nilearn.image.mean_img)

Args:

img: DataObj for the input fMRI data

Returns:

niimg, the mean of fMRI data

cvrmap.get_melodic_mixing(bids_filter, layout)

Get all IC’s as found by MELODIC

Args:

bids_filter: dict, BIDS filter layout: BIDSlayout

Returns:

panda dataframe, all MELODIC mixing matrix from fmriprep outputs str, path to melodic mixing matrix file

cvrmap.get_physio_data(bids_filter, layout)

Fetch raw physiological data

Args:

bids_filter: dict, basic BIDS filter layout: BIDS layout

Returns:

DataObj for raw physiological data

cvrmap.get_preproc(basic_filter, layout)

Load preprocessed image for subject

Args:

basic_filter: dict, BIDS filter layout: BIDS layout

Returns:

DataObj, BOLD preprocessed image of the subject

cvrmap.get_space(args, layout)

Get space (and res, if any) and checks if present in layout (rawdata and derivatives)

Args:

args: return from arguments_manager layout: BIDS layout

Returns:

string for space entity

cvrmap.get_subjects_to_analyze(args, layout)

Generate list of subjects to analyze given the options and available subjects

Args:

args: return from arguments_manager layout: BIDS layout

Returns:

list of subjects to loop over

cvrmap.get_t1w(basic_filter, space, layout)

Load t1w image for subject

Args:

basic_filter: dict, BIDS filter space: str layout: BIDS layout

Returns:

DataObj, t1w image of the subject

cvrmap.get_task(args, layout)

Get and check task option or set to default

Args:

args: return from arguments_manager layout: BIDS layout

Returns:

string for task entity

cvrmap.get_version()

Print version from git info

Returns:

__version__

cvrmap.get_vesselmask(preproc, threshold)

Get the vessel density atlas and binarize it to build the vessel mask

Args:

preproc: DataObj, used only to get the properties of the fMRI data to have the mask on same grid threshold: str, threshold value such as “95%”, passed to nilearn.image.binarize_img

Returns:

niimg, mask for vessels in MNI space

cvrmap.masksignalextract(preproc, mask)

Return time series from masked fMRI data

Args:

preproc: DataObj, fMRI data mask: str, path to mask

Returns:

probe: DataObj, containing the extracted time course baseline: DataObj, baseline of probe

cvrmap.match_timecourses(y1, y2, delay)

The goal of this function is to take two time courses and apply a time shift between the two. This is done carefully, in particular ensuring that the returned time courses are of equal length.

Args:

y1: np array of length n1 y2: np array of length n2 delay: int

Returns:

y1_matched, y2_matched: arrays of same length

cvrmap.msg_error(msg)

Custom print to shell (error)

Args:

msg: str

Returns:

None

cvrmap.msg_info(msg)

Custom print to shell (information)

Args:

msg: str

Returns:

None

cvrmap.msg_warning(msg)

Custom print to shell (warning)

Args:

msg: str

Returns:

None

cvrmap.non_agg_denoise(signal, design_matrix_df, noise_indexes)

This is the in-house implementation of non-aggressive denoising. It is doing the same thing as fsl_regfilt. This is work in progress and is not used in the main script.

cvrmap.plotly_formatted_svg_write_image(fig, output_path)

The plotly.io.write_image function write svg files without proper xml indentation (svg files are xml files, by the way). This causes an issue when using nireports run_reports function, that corrupt the svg files if indentation is not standard. To solve this bug, we must ensure the save svg files have the correct indentation, and we do this using the xmlformatter library. The original svg file is replaced in-place after being create by plotly.

Args:

fig: a plotly Figure output_path: path to where the svg must be saved

Returns:

0

cvrmap.printProgressBar(iteration, total, prefix='', suffix='Complete', decimals=4, length=100, fill='█', print_end='\r')

Call in a loop to create terminal progress bar

Args:

iteration - Required : current iteration (Int) total - Required : total iterations (Int) prefix - Optional : prefix string (Str) suffix - Optional : suffix string (Str) decimals - Optional : positive number of decimals in percent complete (Int) length - Optional : character length of bar (Int) fill - Optional : bar fill character (Str) printEnd - Optional : end character (e.g. “

“, ” “) (Str)

cvrmap.read_config_file(file=None)

All processing parameters are set here to their default values. If file is provided, then the parameters ‘fwhm’, ‘ic_threshold’ and ‘vesseldensity_threshold’ are read from the file (if unspecified, the default value will be kept).

Args:

file, path to json file

Returns:

dict, with various values/np.arrays for the parameters used in main script

cvrmap.run(command, env={})

Execute command as in a terminal Also prints any output of the command into the python shell

Args:

command: string the command (including arguments and options) to be executed env: to add stuff in the environment before running the command

Returns:

nothing

cvrmap.save_figs(results, outputs, mask)

Generate and saves cvr and delay figures.

Args:

results: dict, containing the results to save outputs: dict, with the paths where to save the figures mask: DataObj, to mask the delaymap image

Returns:

0

cvrmap.save_html_reportlets(subject_label, task, space, args, version, aroma_noise_ic_list, global_signal_shift, corrected_noise, parameters, outputs)

Save html reporlets with various data from execution of the pipeline. The reportles will be collected using nireports.

Args:

subject_label: str task: str space: str args: dict version: str aroma_noise_ic_list: list global_signal_shift: float corrected_noise: list parameters: dict outputs: dict

Returns:

0

cvrmap.set_flags(args)

Set various flags for options in the main script

Args:

args: dict, argument of the script

Returns:

dict, with values for the flags as set by the options

cvrmap.setup_output_dir(args, version, layout)

Create output dir if it does not exist, together with dataset_description.json file in it with CVRmap version. Update BIDS layout to contain this folder as BIDS derivatives.

Args:

args: dict, arguments of the script version: str, version of the software layout: BIDS layout

Returns:

layout: BIDS layout, updated with output dir

cvrmap.setup_subject_output_paths(output_dir, subject_label, space, res, args, custom_label)

Setup various paths for subject output. Also creates subject output dir.

Args:

output_dir: str, cvrmap output dir subject_label: str, subject label space: str, space entity res: int, resolution entity args: output of arguments_manager custom_label: str, custom label for outputs

Returns:

dict with various output paths (str)

cvrmap.tccorr(data_object1, data_object2)

Computes cross-correlation between two time courses, by exploring variour time shifts. The inputs are DataObj of type “timecourse”, and come with their own sampling frequency. If the sampling frequencies are different (typical in the case of BOLD signal compared to capnograph data), then the signal with higher sf is downsampled to the lower one. Delays are explored to find maximum correlation, and r-coefficient at maximum returned.

Args:

data_object1: DataObj of type “timecourse” data_object2: DataObj of type “timecourse”

Returns:

float, the maximum r-correlation over the explored delays

Indices and tables