Utils
Utility functions
- class linescanning.utils.VertexInfo(infofile=None, subject=None, hemi='lh')[source]
This object reads a .csv file containing relevant information about the angles, vertex position, and normal vector.
- Parameters:
infofile (str) – path to the information file containing best_vertices in the filename
subject (str) – subject ID as used in SUBJECTS_DIR
- Returns:
sets attributes in the class
- Return type:
attr
- linescanning.utils.ants_to_spm_moco(affine, deg=False, convention='SPM')[source]
SPM output = x [LR], y [AP], z [SI], rx, ry, rz. ANTs employs an LPS system, so y value should be switched
- linescanning.utils.assemble_fmriprep_wf(bold_path, wf_only=False)[source]
Parses the bold file into a workflow name for fMRIPrep into its constituents to recreate a filename. Searches for the following keys: [‘ses’, ‘task’, ‘acq’, ‘run’].
- Parameters:
bold_path (str) – Path to bold-file
wf_only (bool, optional) – If sub tag is found in bold_path, we can reconstruct the full workflow folder including preceding single_subject_<sub_id>_wf. If you do not want this, set wf_only to False.
- Returns:
filename based on constituent file parts
- Return type:
str
Example
>>> from linescanning.utils import disassemble_fmriprep_wf >>> bold_file = "sub-008_ses-2_task-SRFi_acq-3DEPI_run-1_desc-preproc_bold.nii.gz" >>> wf_name = assemble_fmriprep_wf(bold_file) >>> wf_name >>> 'single_subject_008_wf/func_preproc_ses_2_task_SRFi_run_1_acq_3DEPI_wf'
>>> # workflow name only >>> wf_name = assemble_fmriprep_wf(bold_file, wf_only=True) >>> wf_name >>> 'func_preproc_ses_2_task_SRFi_run_1_acq_3DEPI_wf'
- linescanning.utils.copy_hdr(source_img, dest_img)[source]
Similar functionality as fslcpgeom but than more rigorious using Nibabel. Copies the ENTIRE header, including affine, quaternion rotations, and dimensions.
- Parameters:
source_img (str, nibabel.Nifti1Image) – source image from which to derive the header information
dest_img (str, nibabel.Nifti1Image) – destination image to which to copy the header from <source image> to
- Returns:
source_img with updated header information
- Return type:
nibabel.Nifti1Image
Example
>>> new_img = copy_hdr(img1,img2)
- linescanning.utils.create_sinewave(amplitude=1, frequency=1, phase=0, sampling_rate=100, duration=1)[source]
- Parameters:
amplitude (int,float) – Amplitude of the wave. Default = 1
frequency (int,float) – Frequency of the wave in Hertz. Default = 1
phase (int,float) – Phase shift of the wave in radians
sampling_rate (int) – Number of samples per second
duration (int) – Duration of the wave in seconds
- Return type:
A tuple with first element the numpy array containing the sine wave. The second element is the time axis
Example
>>> from linescanning import utils >>> wave,time = utils.create_sinewave()
>>> from linescanning import utils >>> wave,time = utils.create_sinewave( >>> frequency=4, >>> amplitude=0.2 >>> )
- linescanning.utils.disassemble_fmriprep_wf(wf_path, subj_ID, prefix='sub-')[source]
Parses the workflow-folder from fMRIPrep into its constituents to recreate a filename. Searches for the following keys: [‘ses’, ‘task’, ‘acq’, ‘run’].
- Parameters:
wf_path (str) – Path to workflow-folder
subj_ID (str) – Subject ID to append to prefix
prefix (str, optional) – Forms together with subj_ID the beginning of the new filename. By default “sub-”
- Returns:
filename based on constituent file parts
- Return type:
str
Example
>>> from linescanning.utils import disassemble_fmriprep_wf >>> wf_dir = "func_preproc_ses_2_task_pRF_run_1_acq_3DEPI_wf" >>> fname = disassemble_fmriprep_wf(wf_dir, "001") >>> fname 'sub-001_ses-2_task-pRF_acq-3DEPI_run-1'
- linescanning.utils.find_intersection(xx, curve1, curve2)[source]
Find the intersection coordinates given two functions using Shapely.
- Parameters:
xx (numpy.ndarray) – array describing the x-axis values
curve1 (numpy.ndarray) – array describing the first curve
curve2 (numpy.ndarray) – array describing the first curve
- Returns:
x,y coordinates where curve1 and curve2 intersect
- Return type:
tuple
- Raises:
ValueError – if no intersection coordinates could be found
Example
See [refer to linescanning.prf.SizeResponse.find_stim_sizes]
- linescanning.utils.find_nearest(array, value, return_nr=1)[source]
Find the index and value in an array given a value. You can either choose to have 1 item (the closest) returned, or the 5 nearest items (return_nr=5), or everything you’re interested in (return_nr=”all”)
- Parameters:
array (numpy.ndarray) – array to search in
value (float) – value to search for in array
return_nr (int, str, optional) – number of elements to return after searching for elements in array that are close to value. Can either be an integer or a string all
- Returns:
int – integer representing the index of the element in array closest to value.
list – if return_nr > 1, a list of indices will be returned
numpy.ndarray – value in array at the index closest to value
- linescanning.utils.get_file_from_substring(filt, path, return_msg='error', exclude=None)[source]
This function returns the file given a path and a substring. Avoids annoying stuff with glob. Now also allows multiple filters to be applied to the list of files in the directory. The idea here is to construct a binary matrix of shape (files_in_directory, nr_of_filters), and test for each filter if it exists in the filename. If all filters are present in a file, then the entire row should be 1. This is what we’ll be looking for. If multiple files are found in this manner, a list of paths is returned. If only 1 file was found, the string representing the filepath will be returned.
- Parameters:
filt (str, list) – tag for files we need to select. Now also support a list of multiple filters.
path (str) – path to the directory from which we need to remove files
return_msg (str, optional) – whether to raise an error (return_msg=’error’) or return None (*return_msg=None). Default = ‘error’.
exclude (str, optional:) – Specify string to exclude from options. This criteria will be ensued after finding files that conform to filt as final filter.
- Returns:
str – path to the files containing string. If no files could be found, None is returned
list – list of paths if multiple files were found
- Raises:
FileNotFoundError – If no files usingn the specified filters could be found
Example
>>> get_file_from_substring("R2", "/path/to/prf") '/path/to/prf/r2.npy' >>> get_file_from_substring(['gauss', 'best_vertices'], "path/to/pycortex/sub-xxx") '/path/to/pycortex/sub-xxx/sub-xxx_model-gauss_desc-best_vertices.csv' >>> get_file_from_substring(['best_vertices'], "path/to/pycortex/sub-xxx") ['/path/to/pycortex/sub-xxx/sub-xxx_model-gauss_desc-best_vertices.csv', '/path/to/pycortex/sub-xxx/sub-xxx_model-norm_desc-best_vertices.csv']
- linescanning.utils.get_matrixfromants(mat, invert=False)[source]
This function greps the rotation and translation matrices from the matrix-file create by antsRegistration. It basically does the same as on of the ANTs functions, but still..
- Parameters:
mat (str) – string pointing to a .mat-file containing the transformation.
invert (bool) – Boolean for inverting the matrix (invert=False) or not (invert=True)
- Returns:
(4,4) array representing the transformation matrix
- Return type:
numpy.ndarray
- linescanning.utils.get_module_nr(key_word)[source]
Fetches the module number from the master script given an input string. It sends a command using sed and grep to the bash command line. Won’t work on windows! See call_bashhelper for more information (that version is actually more accurate as it allows additions to the master usage, while that’s hardcoded in this one..)
- Parameters:
key_word (str) – search string of the module your interested in. Should at least match otherwise the function will not find anything. For instance, if we want to know which module the creation of the sinus mask is, we can do:
Example
>>> get_module_nr('sinus') '12'
- linescanning.utils.make_binary_cm(color)[source]
This function creates a custom binary colormap using matplotlib based on the RGB code specified. Especially useful if you want to overlay in imshow, for instance. These RGB values will be converted to range between 0-1 so make sure you’re specifying the actual RGB-values. I like https://htmlcolorcodes.com to look up RGB-values of my desired color. The snippet of code used here comes from https://kbkb-wx-python.blogspot.com/2015/12/python-transparent-colormap.html
- Parameters:
<color> (tuple, str) –
either hex-code with (!!) ‘#’ or a tuple consisting of:
<R> int | red-channel (0-255)
<G> int | green-channel (0-255)
<B> int | blue-channel (0-255)
- Returns:
colormap to be used with plt.imshow
- Return type:
matplotlib.colors.LinearSegmentedColormap object
Example
>>> cm = make_binary_cm((232,255,0)) >>> cm <matplotlib.colors.LinearSegmentedColormap at 0x7f35f7154a30> >>> cm = make_binary_cm("#D01B47") >>> cm >>> <matplotlib.colors.LinearSegmentedColormap at 0x7f35f7154a30>
- linescanning.utils.make_chicken_csv(coord, input='ras', output_file=None, vol=0.343)[source]
This function creates a .csv-file like the chicken.csv example from ANTs to warp a coordinate using a transformation file. ANTs assumes the input coordinate to be LPS, but this function can deal with RAS-coordinates too. (see https://github.com/stnava/chicken for the reason of this function’s name)
- Parameters:
coord (np.ndarray) – numpy array containing the three coordinates in x,y,z direction
input (str) – specify whether your coordinates uses RAS or LPS convention (default is RAS, and will be converted to LPS to create the file)
output_file (str) – path-like string pointing to an output file (.csv!)
vol (float) – volume of voxels (pixdim_x*pixdim_y*pixdim_z). If you’re using the standard 0.7 MP2RAGE, the default vol will be ok
- Returns:
path pointing to the csv-file containing the coordinate
- Return type:
str
Example
>>> make_chicken_csv(np.array([-16.239,-67.23,-2.81]), output_file="sub-001_space-fs_desc-lpi.csv") "sub-001_space-fs_desc-lpi.csv"
- linescanning.utils.match_lists_on(ref_list, search_list, matcher='run')[source]
Match two list based on a BIDS-specifier such as ‘sub’, ‘run’, etc. Can be any key that is extracted using
linescanning.utils.split_bids_components().- Parameters:
ref_list (list) – List to use as reference
search_list (list) – List to search for items in ref_list
matcher (str, optional) – BIDS-identifier, by default “run”
- Returns:
new search_list filtered for items in ref_list
- Return type:
list
Example
>>> # Let's say I have functional files for 3 runs >>> func_file >>> ['sub-003_ses-3_task-SR_run-3_bold.mat', >>> 'sub-003_ses-3_task-SR_run-4_bold.mat', >>> 'sub-003_ses-3_task-SR_run-6_bold.mat']
>>> # and anatomical slices for 5 runs >>> anat_slices >>> ['sub-003_ses-3_acq-1slice_run-2_T1w.nii.gz', >>> 'sub-003_ses-3_acq-1slice_run-3_T1w.nii.gz', >>> 'sub-003_ses-3_acq-1slice_run-4_T1w.nii.gz', >>> 'sub-003_ses-3_acq-1slice_run-5_T1w.nii.gz', >>> 'sub-003_ses-3_acq-1slice_run-6_T1w.nii.gz']
>>> # I can then use `match_list_on` to find the anatomical slices corresponding to the functional files >>> from linescanning import utils >>> utils.match_lists_on(func_file, anat_slices, matcher='run') >>> ['sub-003_ses-3_acq-1slice_run-3_T1w.nii.gz', >>> 'sub-003_ses-3_acq-1slice_run-4_T1w.nii.gz', >>> 'sub-003_ses-3_acq-1slice_run-6_T1w.nii.gz']
- linescanning.utils.percent_change(ts, ax, nilearn=False, baseline=20, prf=False, dm=None)[source]
Function to convert input data to percent signal change. Two options are current supported: the nilearn method (nilearn=True), where the mean of the entire timecourse if subtracted from the timecourse, and the baseline method (nilearn=False), where the median of baseline is subtracted from the timecourse.
- Parameters:
ts (numpy.ndarray) – Array representing the data to be converted to percent signal change. Should be of shape (n_voxels, n_timepoints)
ax (int) – Axis over which to perform the conversion. If shape (n_voxels, n_timepoints), then ax=1. If shape (n_timepoints, n_voxels), then ax=0.
nilearn (bool, optional) – Use nilearn method, by default False
baseline (int, list, np.ndarray optional) – Use custom method where only the median of the baseline (instead of the full timecourse) is subtracted, by default 20. Length should be in volumes, not seconds. Can also be a list or numpy array (1d) of indices which are to be considered as baseline. The list of indices should be corrected for any deleted volumes at the beginning.
- Returns:
Array with the same size as ts (voxels,time), but with percent signal change.
- Return type:
numpy.ndarray
- Raises:
ValueError – If ax > 2
- linescanning.utils.random_timeseries(intercept, volatility, nr)[source]
Create a random timecourse by multiplying an intercept with a random Gaussian distribution.
- Parameters:
intercept (float) – starting point of timecourse
volatility (float) – this factor is multiplied with the Gaussian distribution before multiplied with the intercept
nr (int) – length of timecourse
- Returns:
array of length nr
- Return type:
numpy.ndarray
Example
>>> from linescanning import utils >>> ts = utils.random_timeseries(1.2, 0.5, 100)
Notes
- linescanning.utils.read_chicken_csv(chicken_file, return_type='lps')[source]
Function to get at least the coordinates from a csv file used with antsApplyTransformsToPoints. (see https://github.com/stnava/chicken for the reason of this function’s name)
- Parameters:
chicken_file (str) – path-like string pointing to an input file (.csv!)
return_type (str) – specify the coordinate system that the output should be in
- Returns:
(3,) array containing the coordinate in chicken_file
- Return type:
numpy.ndarray
Example
>>> read_chicken_csv("sub-001_space-fs_desc-lpi.csv") array([-16.239,-67.23,-2.81])
- linescanning.utils.read_fs_reg(dat_file)[source]
Read a .dat-formatted registration file from FreeSurfer
- Parameters:
dat_file (str) – path pointing to the registration file
- Returns:
(4,4) numpy array containing the transformation
- Return type:
nump.ndarray
- linescanning.utils.remove_files(path, string, ext=False)[source]
Remove files from a given path that containg a string as extension (ext=True), or at the start of the file (ext=False)
- Parameters:
path (str) – path to the directory from which we need to remove files
string (str) – tag for files we need to remove
ext (str, optional) – only remove files containing string that end with ext
- linescanning.utils.replace_string(fn, str1, str2, fn_sep='_')[source]
Replace a string with another string given a filename
- Parameters:
fn (str) – filename in which we need to replace something
str1 (str) – string-to-be-replaced
str2 (str) – string-to-replace-str1-with
fn_sep (str) – what type of element can we use to split the filename into chunks that we can replace
- Returns:
filename with replaced substring
- Return type:
str
- linescanning.utils.resample2d(array: ndarray, new_size: int, kind='linear')[source]
Resamples a 2D (or 3D) array with
scipy.interpolate.interp2d()to new_size. If input is 2D, we’ll loop over the final axis.- Parameters:
array (np.ndarray) – Array to be interpolated. Ideally axis have the same size.
new_size (int) – New size of array
kind (str, optional) – Interpolation method, by default ‘linear’
- Returns:
If 2D: resampled array of shape (new_size,new_size) If 3D: resampled array of shape (new_size,new_size, array.shape[-1])
- Return type:
np.ndarray
- linescanning.utils.reverse_sign(x)[source]
Inverts the sign given set of values. Can be either one value or an array of values that need to be inverted
- Parameters:
x (int,float,list,numpy.ndarray) – input that needs inverting, either one value or a list
- Return type:
the inverse of whatever the input x was
Example
>>> # input is integer >>> x = 5 >>> reverse_sign(x) -5 >>> # input is array >>> x = np.array([2, -2340, 2345,123342, 123]) >>> In [6]: reverse_sign(x) array([-2.00000e+00, 2.34000e+03, -2.34500e+03, -1.23342e+05,-1.23000e+02]) >>> # input is float >>> x = 5.0 >>> reverse_sign(x) -5.0
- linescanning.utils.round_decimals_down(number: float, decimals: int = 2)[source]
Returns a value rounded down to a specific number of decimal places. see: https://kodify.net/python/math/round-decimals/#round-decimal-places-up-and-down-round
- linescanning.utils.round_decimals_up(number: float, decimals: int = 2)[source]
Returns a value rounded up to a specific number of decimal places. see: https://kodify.net/python/math/round-decimals/#round-decimal-places-up-and-down-round
- linescanning.utils.select_from_df(df, expression=None, index=True, indices=None, match_exact=True)[source]
Select a subset of a dataframe based on an expression. Dataframe should be indexed by the variable you want to select on or have the variable specified in the expression argument as column name. If index is True, the dataframe will be indexed by the selected variable. If indices is specified, the dataframe will be indexed by the indices specified through a list (only select the elements in the list) or a range-object (select within range).
- Parameters:
df (pandas.DataFrame) – input dataframe
expression (str, optional) – what subject of the dataframe to select, by default None. The expression must consist of a variable name and an operator. The operator can be any of the following: ‘=’, ‘>’, ‘<’, ‘>=’, ‘<=’, ‘!=’, separated by spaces. You can also change 2 operations by specifying the &-operator between the two expressions. If you want to use indices, specify expression=”ribbon”.
index (bool, optional) – return output dataframe with the same indexing as df, by default True
indices (list, range, numpy.ndarray, optional) – List, range, or numpy array of indices to select from df, by default None
match_exact (bool, optional:) – When you insert a list of strings with indices to be filtered from the dataframe, you can either request that the items of indices should match exactly (match_exact=True, default) the column names of df, or whether the columns of df should contain the items of indices (match_exact=False).
- Returns:
new dataframe where expression or indices were selected from df
- Return type:
pandas.DataFrame
- Raises:
TypeError – If indices is not a tuple, list, or array
Notes
See https://linescanning.readthedocs.io/en/latest/examples/nideconv.html for an example of how to use this function (do ctrl+F and enter “select_from_df”).
- linescanning.utils.squeeze_generic(a, axes_to_keep)[source]
Numpy squeeze implementation keeping <axes_to_keep> dimensions.
- Parameters:
a (numpy.ndarray) – array to be squeezed
axes_to_keep (tuple, range) – tuple of axes to keep from original input
- Returns:
axes_to_keep from a
- Return type:
numpy.ndarray
Example
>>> a = np.random.rand(3,5,1) >>> squeeze_generic(a, axes_to_keep=range(2)).shape (3, 5)
Notes
- linescanning.utils.string2float(string_array)[source]
This function converts a array in string representation to a regular float array. This can happen, for instance, when you’ve stored a numpy array in a pandas dataframe (such is the case with the ‘normal’ vector). It starts by splitting based on empty spaces, filter these, and convert any remaining elements to floats and returns these in an array.
- Parameters:
string_array (str) – string to be converted to a valid numpy array with float values
- Returns:
array containing elements in float rather than in string representation
- Return type:
numpy.ndarray
Example
>>> string2float('[ -7.42 -92.97 -15.28]') array([ -7.42, -92.97, -15.28])
- linescanning.utils.string2list(string_array, make_float=False)[source]
This function converts a array in string representation to a list of string. This can happen, for instance, when you use bash to give a list of strings to python, where ast.literal_eval fails.
- Parameters:
string_array (str) – string to be converted to a valid numpy array with float values
- Returns:
array containing elements in float rather than in string representation
- Return type:
numpy.ndarray
Example
>>> string2list('[tc,bgfs]') ['tc', 'bgfs']
- linescanning.utils.unique_combinations(elements, l=2)[source]
Precondition: elements does not contain duplicates. Postcondition: Returns unique combinations of length 2 from elements.
>>> unique_combinations(["apple", "orange", "banana"]) [("apple", "orange"), ("apple", "banana"), ("orange", "banana")]