def adni3_image(subject_id, timepoint, visit_str, mprage_meta_subj, mayo_mri_qc_subj): from clinica.iotools.converters.adni_to_bids.adni_utils import replace_sequence_chars from clinica.utils.stream import cprint filtered_scan = mprage_meta_subj[(mprage_meta_subj['Orig/Proc'] == 'Original') & (mprage_meta_subj.Visit == visit_str) & mprage_meta_subj.Sequence.map( lambda x: (x.lower().find('accel') > -1) & ~(x.lower().endswith('_ND')))] if filtered_scan.shape[0] < 1: # TODO - LOG THIS cprint('NO MPRAGE Meta for ADNI3: ' + subject_id + ' for visit ' + timepoint + ' - ' + visit_str) return None scan = select_scan_qc_adni2(filtered_scan, mayo_mri_qc_subj, preferred_field_strength=3.0) sequence = replace_sequence_chars(scan.Sequence) return {'Subject_ID': subject_id, 'VISCODE': timepoint, 'Visit': visit_str, 'Sequence': sequence, 'Scan_Date': scan.ScanDate, 'Study_ID': str(scan.StudyID), 'Series_ID': str(scan.SeriesID), 'Image_ID': str(scan.ImageUID), 'Field_Strength': scan.MagStrength, 'Original': True}
def atlas_statistics(file_list, atlas_list): """ For each atlas name provided it ƒcalculates for the input image the mean for each region in the atlas and saves it to a TSV file. :param in_image: A Nifti image :param in_atlas_list: List of names of atlas to be applied :return: List of paths to tsv files """ from os import getcwd from os.path import abspath, join from nipype.utils.filemanip import split_filename from clinica.utils.atlas import AtlasAbstract from clinica.utils.statistics import statistics_on_atlas from clinica.utils.stream import cprint orig_dir, base, ext = split_filename(file_list) atlas_classes = AtlasAbstract.__subclasses__() atlas_statistics_list = [] for atlas in atlas_list: for atlas_class in atlas_classes: if atlas_class.get_name_atlas() == atlas: #out_atlas_statistics = abspath(join(getcwd(), base + '_space-' + atlas + '_map-graymatter_statistics.tsv')) out_atlas_statistics = abspath( join('./' + base + '_space-' + atlas + '_map-graymatter_statistics.tsv')) cprint(out_atlas_statistics) statistics_on_atlas(file_list, atlas_class(), out_atlas_statistics) atlas_statistics_list.append(out_atlas_statistics) break return atlas_statistics_list
def run_command(self, args): """ """ import os import datetime from colorama import Fore from tempfile import mkdtemp from .dwi_dti_pipeline import DwiDti from clinica.utils.stream import cprint pipeline = DwiDti( caps_directory=self.absolute_path(args.caps_directory), tsv_file=self.absolute_path(args.subjects_sessions_tsv)) if args.working_directory is None: args.working_directory = mkdtemp() pipeline.base_dir = self.absolute_path(args.working_directory) if args.n_procs: pipeline.run(plugin='MultiProc', plugin_args={'n_procs': args.n_procs}) else: pipeline.run() now = datetime.datetime.now().strftime('%H:%M:%S') cprint( '%s[%s]%s The %s pipeline has completed. You can now delete the working directory (%s).' % (Fore.GREEN, now, Fore.RESET, self._name, os.path.join(os.path.abspath(args.working_directory), pipeline.__class__.__name__)))
def check_fsl(version_requirements=None): """Check FSL software.""" import nipype.interfaces.fsl as fsl from colorama import Fore from clinica.utils.exceptions import ClinicaMissingDependencyError from clinica.utils.stream import cprint check_environment_variable("FSLDIR", "FSL") try: if fsl.Info.version().split(".") < ["5", "0", "5"]: raise ClinicaMissingDependencyError( f"{Fore.RED}FSL version must be greater than 5.0.5{Fore.RESET}" ) except Exception as e: cprint(str(e)) list_binaries = ["bet", "flirt", "fast", "first"] for binary in list_binaries: if not is_binary_present(binary): raise ClinicaMissingDependencyError( f"{Fore.RED}\n[Error] Clinica could not find FSL software: " f"the {binary} command is not present in your PATH environment.{Fore.RESET}" )
def delta_echo_time_from_bids_fmap(fmap_json): """ Extract BIDS metadata (EchoTime1, etc.) from a fmap .json file. Args: fmap_json: Path to a BIDS compliant .json file Returns: """ import json import os from clinica.utils.stream import cprint if not os.path.exists(fmap_json): raise IOError('fmap .json file (%s) does not exist.' % fmap_json) with open(fmap_json) as data_frame: data = json.load(data_frame) echo_time_1 = data['EchoTime1'] echo_time_2 = data['EchoTime2'] delta_echo_time = echo_time_2 - echo_time_1 cprint( dwi_container_from_filename(fmap_json) + " (FMap JSON): EchoTime1=" + str(echo_time_1) + ", EchoTime2=" + str(echo_time_2) + " (Delta = " + str(delta_echo_time) + ", fname=" + fmap_json + ")") return delta_echo_time
def check_qc(scan, subject_id, visit_str, mri_quality_subj): """Checks if a scan has passed check quality, if it was performed Args: scan: DataFrame row containing scan information subject_id: string containing subject ID visit_str: string of visit name mri_quality_subj: DatFrame of MR image quality of images corresponding to the subject Returns: boolean, True if image passed QC or if there is not available QC, False elsewhere """ from clinica.utils.stream import cprint # Check if QC exists for image series qc = mri_quality_subj[mri_quality_subj.LONIUID == 'S' + str(scan.SeriesID)] # If QC exists and failed we keep the other scan (in case 2 scans were performed) if not qc.empty and qc.iloc[0].PASS != 1: cprint('QC found but NOT passed') cprint('Subject ' + subject_id + ' for visit ' + visit_str + ' - Series: ' + str(scan.SeriesID) + ' - Study: ' + str(scan.StudyID)) return False return True
def build_input_node(self): """Build and connect an input node to the pipeline.""" import os from clinica.utils.filemanip import save_participants_sessions from clinica.utils.stream import cprint from clinica.utils.ux import print_images_to_process if self.parameters["longitudinal"]: self.build_input_node_longitudinal() else: self.build_input_node_cross_sectional() # Save subjects to process in <WD>/<Pipeline.name>/participants.tsv folder_participants_tsv = os.path.join(self.base_dir, self.name) save_participants_sessions( self.subjects, self.sessions, folder_participants_tsv ) if len(self.subjects): print_images_to_process(self.subjects, self.sessions) cprint( "List available in %s" % os.path.join(folder_participants_tsv, "participants.tsv") ) cprint("The pipeline will last approximately a few hours per image.")
def check_freesurfer(): """ Check FreeSurfer software. This function checks if FreeSurfer is present (FREESURFER_HOME & binaries). """ import os from clinica.utils.stream import cprint try: freesurfer_home = os.environ.get('FREESURFER_HOME', '') if not freesurfer_home: raise RuntimeError('FREESURFER_HOME variable is not set') except Exception as e: cprint(str(e)) list_binaries = ['mri_convert', 'recon-all'] for binary in list_binaries: if not is_binary_present(binary): raise RuntimeError( '%s from FreeSurfer Software is not present in your PATH ' 'environment: did you source ${FREESURFER_HOME}/' 'SetUpFreeSurfer.sh ?' % binary) cprint('FreeSurfer has been detected')
def write_tsv_files(subjects_dir, image_id): """ Generate statistics TSV files in `subjects_dir`/regional_measures folder for `image_id`. Notes: We do not need to check the line "finished without error" in scripts/recon-all.log. If an error occurs, it will be detected by Nipype and the next nodes (including write_tsv_files will not be called). """ import os from clinica.utils.freesurfer import generate_regional_measures from clinica.utils.stream import cprint if os.path.isfile( os.path.join(subjects_dir, image_id, "mri", "aparc+aseg.mgz")): generate_regional_measures(subjects_dir, image_id) else: cprint( msg= (f"{image_id.replace('_', ' | ')} does not contain " f"mri/aseg+aparc.mgz file. Creation of regional_measures/ folder will be skipped." ), lvl="warning", ) return image_id
def save_part_sess_long_ids_to_tsv(participant_ids, session_ids, long_ids, out_folder, file_name=None): """Save participant, session and longitudinal IDs to TSV file. TODO: Find a way to merge with utils/save_participants_sessions.py::read_participant_tsv into one util """ import os import pandas from clinica.utils.stream import cprint os.makedirs(out_folder, exist_ok=True) if file_name: tsv_file = os.path.join(out_folder, file_name) else: tsv_file = os.path.join(out_folder, "participants.tsv") try: data = pandas.DataFrame({ "participant_id": participant_ids, "session_id": session_ids, "long_id": long_ids, }) data.to_csv(tsv_file, sep="\t", index=False, encoding="utf-8") except Exception as e: cprint(f"Impossible to save {tsv_file} with pandas") raise e
def print_images_to_process(list_participant_id, list_session_id, list_longitudinal_id): cprint('The pipeline will be run on the following %s image(s):' % len(list_participant_id)) for (p_id, s_id, l_id) in zip(list_participant_id, list_session_id, list_longitudinal_id): cprint("\t%s | %s | %s" % (p_id, s_id, l_id))
def find_image_path(images, source_dir, modality, prefix, id_field): """ For each image, the path to an existing image file or folder is created from image metadata. Args: images: List of images metadata source_dir: path to the ADNI directory modality: Imaging modality prefix: Prefix to prepend to image identifier to create name of folder containing the image id_field: Name of the field in images metadata dataframe containing the image identifier to use Returns: Dataframe containing metadata and existing paths """ from pathlib import Path import pandas as pd from clinica.utils.stream import cprint is_dicom = [] image_folders = [] for _, image in images.iterrows(): # Base directory where to look for image files. seq_path = Path(source_dir) / str(image["Subject_ID"]) # Generator finding files containing the image ID. find_file = filter( lambda p: p.is_file(), seq_path.rglob(f"*_I{image['Image_ID']}.*"), ) try: # Grab the first file from the generator. next_file: Path = next(find_file) # Whether the image data are DICOM or not. dicom = "dcm" in next_file.suffix # Compute the image path (DICOM folder or NIfTI path). image_path = str(next_file.parent if dicom else next_file) except StopIteration: # In case no file is found. image_path = "" dicom = True is_dicom.append(dicom) image_folders.append(image_path) if image_path == "": cprint( msg= (f"No {modality} image path found for subject {image.Subject_ID} in visit {image.VISCODE} " f"with image ID {image.Image_ID}"), lvl="info", ) images.loc[:, "Is_Dicom"] = pd.Series(is_dicom, index=images.index) images.loc[:, "Path"] = pd.Series(image_folders, index=images.index) return images
def write_tsv_files(subjects_dir, subject_id): """Generate statistics TSV files in `subjects_dir`/regional_measures folder for `subject_id`. Notes: We do not need to check the line "finished without error" in scripts/recon-all.log. If an error occurs, it will be detected by Nipype and the next nodes (i.e. write_tsv_files will not be called). """ import os from clinica.utils.freesurfer import ( extract_image_id_from_longitudinal_segmentation, generate_regional_measures, ) from clinica.utils.stream import cprint image_id = extract_image_id_from_longitudinal_segmentation(subject_id) str_image_id = (image_id.participant_id + "_" + image_id.session_id + "_" + image_id.long_id) if os.path.isfile( os.path.join(subjects_dir, subject_id, "mri", "aparc+aseg.mgz")): generate_regional_measures(subjects_dir, subject_id) else: cprint( msg= (f"{str_image_id.replace('_', ' | ')} does not contain mri/aseg+aparc.mgz file. " "Creation of regional_measures/ folder will be skipped."), lvl="warning", ) return subject_id
def run_command(self, args): """ """ from tempfile import mkdtemp from clinica.utils.stream import cprint from clinica.pipelines.machine_learning_spatial_svm.spatial_svm_pipeline import SpatialSVM pipeline = SpatialSVM( caps_directory=self.absolute_path(args.caps_directory), tsv_file=self.absolute_path(args.subjects_sessions_tsv)) pipeline.parameters = { 'group_id': args.group_id, 'fwhm': args.full_width_half_maximum, 'image_type': args.image_type, 'pet_type': args.pet_tracer, 'no_pvc': args.no_pvc } if args.working_directory is None: args.working_directory = mkdtemp() pipeline.base_dir = self.absolute_path(args.working_directory) if args.n_procs: pipeline.run(plugin='MultiProc', plugin_args={'n_procs': args.n_procs}) else: pipeline.run() cprint( "The " + self._name + " pipeline has completed. You can now delete the working directory (" + args.working_directory + ").")
def run_command(self, args): """ """ from tempfile import mkdtemp from clinica.utils.stream import cprint from clinica.pipelines.t1_volume_parcellation.t1_volume_parcellation_pipeline import T1VolumeParcellation pipeline = T1VolumeParcellation( caps_directory=self.absolute_path(args.caps_directory), tsv_file=self.absolute_path(args.subjects_sessions_tsv)) assert args.modulation in ['on', 'off'] pipeline.parameters = { 'group_id': args.group_id, 'atlases': args.atlases, 'wd': self.absolute_path(args.working_directory), 'n_procs': args.n_procs, 'modulate': args.modulation } if args.working_directory is None: args.working_directory = mkdtemp() pipeline.base_dir = self.absolute_path(args.working_directory) if args.n_procs: pipeline.run(plugin='MultiProc', plugin_args={'n_procs': args.n_procs}) else: pipeline.run() cprint( "The " + self._name + " pipeline has completed. You can now delete the working directory (" + args.working_directory + ").")
def write_tsv_files(subjects_dir, subject_id): """ Generate statistics TSV files in `subjects_dir`/regional_measures folder for `subject_id`. Notes: We do not need to check the line "finished without error" in scripts/recon-all.log. If an error occurs, it will be detected by Nipype and the next nodes (i.e. write_tsv_files will not be called). """ import os import datetime from colorama import Fore from clinica.utils.stream import cprint from clinica.utils.freesurfer import generate_regional_measures, extract_image_id_from_longitudinal_segmentation image_id = extract_image_id_from_longitudinal_segmentation(subject_id) str_image_id = image_id.participant_id + '_' + image_id.session_id + '_' + image_id.long_id if os.path.isfile( os.path.join(subjects_dir, subject_id, 'mri', 'aparc+aseg.mgz')): generate_regional_measures(subjects_dir, subject_id) else: now = datetime.datetime.now().strftime('%H:%M:%S') cprint( '%s[%s] %s does not contain mri/aseg+aparc.mgz file. ' 'Creation of regional_measures/ folder will be skipped.%s' % (Fore.YELLOW, now, str_image_id.replace('_', ' | '), Fore.RESET)) return subject_id
def get_file_from_server(remote_file, cache_path=None): """Download file from server. Args: remote_file (str): RemoteFileStructure defined in clinica.utils.inputs cache_path (str): (default: ~/.cache/clinica/data) Returns: Path to downloaded file. """ import os from pathlib import Path from clinica.utils.stream import cprint home = str(Path.home()) if cache_path: cache_clinica = os.path.join(home, ".cache", cache_path) else: cache_clinica = os.path.join(home, ".cache", "clinica", "data") os.makedirs(cache_clinica, exist_ok=True) local_file = os.path.join(cache_clinica, remote_file.filename) if not (os.path.exists(local_file)): try: local_file = fetch_file(remote_file, cache_clinica) except IOError as err: cprint( f"Unable to download {remote_file.filename} from {remote_file.url}: {err}" ) return local_file
def init_input_node(pet_nii): import datetime import nibabel as nib from colorama import Fore from clinica.utils.filemanip import get_subject_id from clinica.utils.stream import cprint from clinica.utils.ux import print_begin_image # Extract image ID image_id = get_subject_id(pet_nii) # Check that the PET file is a 3D volume img = nib.load(pet_nii) if len(img.shape) == 4: now = datetime.datetime.now().strftime("%H:%M:%S") error_msg = ( f"{Fore.RED}[{now}] Error: Clinica does not handle 4D volumes " f"for {image_id.replace('_', ' | ')}{Fore.RESET}") cprint(error_msg) raise NotImplementedError(error_msg) # Print begin message print_begin_image(image_id) return pet_nii
def run_command(self, args): """ Run the DWIPreprocessingUsingT1 Pipeline from command line. """ from tempfile import mkdtemp from clinica.utils.stream import cprint from .dwi_preprocessing_using_t1_pipeline import DwiPreprocessingUsingT1 pipeline = DwiPreprocessingUsingT1( bids_directory=self.absolute_path(args.bids_directory), caps_directory=self.absolute_path(args.caps_directory), tsv_file=self.absolute_path(args.subjects_sessions_tsv), low_bval=args.low_bval) if args.working_directory is None: args.working_directory = mkdtemp() pipeline.base_dir = self.absolute_path(args.working_directory) if args.n_procs: pipeline.run(plugin='MultiProc', plugin_args={'n_procs': args.n_procs}) else: pipeline.run() cprint( "The " + self._name + " pipeline has completed. You can now delete the working directory (" + args.working_directory + ").")
def run_command(self, args): """ """ from tempfile import mkdtemp from clinica.utils.stream import cprint from clinica.pipelines.t1_volume_existing_dartel.t1_volume_existing_dartel_pipeline import T1VolumeExistingDartel pipeline = T1VolumeExistingDartel( bids_directory=self.absolute_path(args.bids_directory), caps_directory=self.absolute_path(args.caps_directory), tsv_file=self.absolute_path(args.subjects_sessions_tsv), group_id=args.group_id) pipeline.parameters.update({'tissues': args.tissues}) if args.working_directory is None: args.working_directory = mkdtemp() pipeline.base_dir = self.absolute_path(args.working_directory) if args.n_procs: pipeline.run(plugin='MultiProc', plugin_args={'n_procs': args.n_procs}) else: pipeline.run() cprint( "The " + self._name + " pipeline has completed. You can now delete the working directory (" + args.working_directory + ").")
def run(self, plugin=None, plugin_args=None, update_hash=False, bypass_check=False): """Executes the Pipeline. It overwrites the default Workflow method to check if the Pipeline is built before running it. If not, it builds it and then run it. It also checks whether there is enough space left on the disks, and if the number of threads to run in parallel is consistent with what is possible on the CPU. Args: Similar to those of Workflow.run. Returns: An execution graph (see Workflow.run). """ import shutil from colorama import Fore from networkx import Graph, NetworkXError from clinica.utils.stream import cprint from clinica.utils.ux import print_failed_images if not self.is_built: self.build() self.check_not_cross_sectional() if not bypass_check: self.check_size() plugin_args = self.update_parallelize_info(plugin_args) plugin = "MultiProc" exec_graph = [] try: exec_graph = Workflow.run(self, plugin, plugin_args, update_hash) if not self.base_dir_was_specified: shutil.rmtree(self.base_dir) except RuntimeError as e: # Check that it is a Nipype error if "Workflow did not execute cleanly. Check log for details" in str(e): input_ids = [ p_id + "_" + s_id for p_id, s_id in zip(self.subjects, self.sessions) ] output_ids = self.get_processed_images( caps_directory=self.caps_directory, subjects=self.subjects, sessions=self.sessions, ) missing_ids = list(set(input_ids) - set(output_ids)) print_failed_images(self.name, missing_ids) else: raise e except NetworkXError: cprint( f"{Fore.BLUE}Either all the images were already run by the pipeline " f"or no image was found to run the pipeline.\n{Fore.RESET}" ) exec_graph = Graph() return exec_graph
def use_spm_standalone(): """Use SPM Standalone with MATLAB Common Runtime.""" import os import platform from nipype.interfaces import spm from clinica.utils.stream import cprint # This section of code determines whether to use SPM standalone or not if all(elem in os.environ.keys() for elem in ["SPMSTANDALONE_HOME", "MCR_HOME"]): spm_standalone_home = os.getenv("SPMSTANDALONE_HOME") mcr_home = os.getenv("MCR_HOME") if os.path.exists(spm_standalone_home) and os.path.exists(mcr_home): cprint( "SPM standalone has been found and will be used in this pipeline" ) if platform.system().lower().startswith("darwin"): matlab_cmd = ( f"cd {spm_standalone_home} && ./run_spm12.sh {mcr_home} script" ) elif platform.system().lower().startswith("linux"): matlab_cmd = f"{os.path.join(spm_standalone_home, 'run_spm12.sh')} {mcr_home} script" else: raise SystemError("Clinica only support macOS and Linux") spm.SPMCommand.set_mlab_paths(matlab_cmd=matlab_cmd, use_mcr=True) cprint(f"Using SPM standalone version {spm.SPMCommand().version}") else: raise FileNotFoundError( "$SPMSTANDALONE_HOME and $MCR_HOME are defined, but linked to non existent folder " )
def parameters_from_dwi_metadata(dwi_json): """ Extract BIDS metadata (EffectiveEchoSpacing, etc.) from a DWI .json file. Args: dwi_json: Path to a BIDS compliant .json file Returns: """ import json import os from clinica.utils.stream import cprint if not os.path.exists(dwi_json): raise IOError('DWI .json file (%s) does not exist.' % dwi_json) with open(dwi_json) as data_frame: data = json.load(data_frame) effective_echo_spacing = data['EffectiveEchoSpacing'] phase_encoding_direction = data['PhaseEncodingDirection'] cprint( dwi_container_from_filename(dwi_json) + " (DWI JSON): EffectiveEchoSpacing=" + str(effective_echo_spacing) + ", PhaseEncodingDirection=" + str(phase_encoding_direction) + " (fname = " + dwi_json + ")") return [effective_echo_spacing, phase_encoding_direction]
def move_subjects_dir_to_source_dir(subjects_dir, source_dir, subject_id): """ Move content of `subjects_dir`/`subject_id` to `source_dir`. This function will move content of `subject_id` if recon-all has run in $(TMP). This happens when only one time point is used. Content of $(TMP)/`subject_id` is copied to `source_dir` before the deletion of $(TMP). Args: subjects_dir: $(TMP), if segmentation was performed on 1 time point, <base_dir>/<Pipeline.Name>/ReconAll/`subject_id` otherwise source_dir: <base_dir>/<Pipeline.Name>/ReconAll folder subject_id: Subject ID (e.g. "sub-CLNC01_ses-M00" or "sub-CLNC01_ses-M00M18") Returns: subject_id for node connection with Nipype """ import os import shutil import datetime from colorama import Fore from clinica.utils.stream import cprint if source_dir not in subjects_dir: shutil.copytree(src=os.path.join(subjects_dir, subject_id), dst=os.path.join(source_dir, subject_id, subject_id), symlinks=True) shutil.rmtree(subjects_dir) now = datetime.datetime.now().strftime('%H:%M:%S') cprint( '%s[%s] Segmentation of %s has moved to working directory and $SUBJECTS_DIR folder (%s) was deleted%s' % (Fore.YELLOW, now, subject_id.replace( '_', ' | '), subjects_dir, Fore.RESET)) return subject_id
def save_participants_sessions(participant_ids, session_ids, out_folder, out_file=None): """ Save <participant_ids> <session_ids> in <out_folder>/<out_file> TSV file. """ import os import errno import pandas from clinica.utils.stream import cprint assert (len(participant_ids) == len(session_ids)) try: os.makedirs(out_folder) except OSError as e: if e.errno != errno.EEXIST: # EEXIST: folder already exists raise e if out_file: tsv_file = os.path.join(out_folder, out_file) else: tsv_file = os.path.join(out_folder, 'participants.tsv') try: data = pandas.DataFrame({ 'participant_id': participant_ids, 'session_id': session_ids, }) data.to_csv(tsv_file, sep='\t', index=False, encoding='utf-8') except Exception as e: cprint("Impossible to save %s with pandas" % out_file) raise e
def run_command(self, args): from clinica.iotools.converters.adni_to_bids.adni_to_bids import AdniToBids from os.path import exists, join from clinica.utils.stream import cprint from colorama import Fore from time import sleep adni_to_bids = AdniToBids() # Check dcm2nii and dcm2niix dependencies adni_to_bids.check_adni_dependencies() if 'fMRI' in args.modalities and not exists(join(args.clinical_data_directory, 'IDA_MR_Metadata_Listing.csv')): cprint(Fore.RED + '[Warning] We could not detect file IDA_MR_Metadata_Listing.csv in your clinical data folder.' + ' Therefore, fMRI conversion is disabled.' + Fore.GREEN + '\nADNI conversion will start in a few seconds...' + Fore.RESET) # Enough time for the user to read the message sleep(7) args.modalities.remove('fMRI') if not args.clinical_data_only: adni_to_bids.convert_images(self.absolute_path(args.dataset_directory), self.absolute_path(args.clinical_data_directory), self.absolute_path(args.bids_directory), args.subjects_list, args.modalities) adni_to_bids.convert_clinical_data(self.absolute_path(args.clinical_data_directory), self.absolute_path(args.bids_directory))
def save_participants_sessions(participant_ids, session_ids, out_folder, out_file=None): """Save <participant_ids> <session_ids> in <out_folder>/<out_file> TSV file.""" import os import pandas from clinica.utils.stream import cprint assert len(participant_ids) == len(session_ids) os.makedirs(out_folder, exist_ok=True) if out_file: tsv_file = os.path.join(out_folder, out_file) else: tsv_file = os.path.join(out_folder, "participants.tsv") try: data = pandas.DataFrame({ "participant_id": participant_ids, "session_id": session_ids, }) data.to_csv(tsv_file, sep="\t", index=False, encoding="utf-8") except Exception as e: cprint(f"Impossible to save {out_file} with pandas") raise e
def run_command(self, args): """ Run the pipelines with defined args """ import os import datetime from colorama import Fore from clinica.utils.stream import cprint from .t1_freesurfer_cross_sectional_pipeline import T1FreeSurferCrossSectional from tempfile import mkdtemp pipeline = T1FreeSurferCrossSectional( bids_directory=self.absolute_path(args.bids_directory), caps_directory=self.absolute_path(args.caps_directory), tsv_file=self.absolute_path(args.subjects_sessions_tsv) ) pipeline.parameters = { 'recon_all_args': args.recon_all_args or '-qcache' } if args.working_directory is None: args.working_directory = mkdtemp() pipeline.base_dir = self.absolute_path(args.working_directory) if args.n_procs: pipeline.run(plugin='MultiProc', plugin_args={'n_procs': args.n_procs}) else: pipeline.run() now = datetime.datetime.now().strftime('%H:%M:%S') cprint('%s[%s]%s The %s pipeline has completed. You can now delete the working directory (%s).' % (Fore.GREEN, now, Fore.RESET, self._name, os.path.join(os.path.abspath(args.working_directory), pipeline.__class__.__name__)))
def use_spm_standalone(): """ Use SPM Standalone with MATLAB Common Runtime """ import os from colorama import Fore import platform from clinica.utils.stream import cprint from nipype.interfaces import spm # This section of code determines whether to use SPM standalone or not if all(elem in os.environ.keys() for elem in ['SPMSTANDALONE_HOME', 'MCR_HOME']): spm_standalone_home = os.getenv('SPMSTANDALONE_HOME') mcr_home = os.getenv('MCR_HOME') if os.path.exists(spm_standalone_home) and os.path.exists(mcr_home): cprint(Fore.GREEN + 'SPM standalone has been found and will be used in this pipeline' + Fore.RESET) if platform.system().lower().startswith('darwin'): matlab_cmd = ('cd %s && ./run_spm12.sh %s script' % (spm_standalone_home, mcr_home)) elif platform.system().lower().startswith('linux'): matlab_cmd = ('%s %s script' % (os.path.join(spm_standalone_home, 'run_spm12.sh'), mcr_home)) else: raise SystemError('Clinica only support macOS and Linux') spm.SPMCommand.set_mlab_paths(matlab_cmd=matlab_cmd, use_mcr=True) cprint("Using SPM standalone version %s" % spm.SPMCommand().version) else: raise FileNotFoundError('$SPMSTANDALONE_HOME and $MCR_HOME are defined, but linked to non existent folder ')
def build_input_node(self): """Build and connect an input node to the pipeline. """ from clinica.utils.stream import cprint import nipype.interfaces.utility as nutil import nipype.pipeline.engine as npe from clinica.lib.pycaps.caps_layout import CAPSLayout read_parameters_node = npe.Node(name="LoadingCLIArguments", interface=nutil.IdentityInterface( fields=self.get_input_fields(), mandatory_inputs=True)) read_parameters_node.inputs.atlas_list = self.parameters['atlases'] caps_layout = CAPSLayout(self.caps_directory) cprint('------- INPUT FILES FOR EACH SUBJECTS -------') subjects_regex = '|'.join(sub[4:] for sub in self.subjects) unique_session = set(list(self.sessions)) sessions_regex = '|'.join(sub[4:] for sub in unique_session) cprint(' * grabbing all files from CAPS folder') caps_file = caps_layout.get(return_type='file', subject=subjects_regex, session=sessions_regex, group_id=self.parameters['group_id'], modulation=self.parameters['modulate']) if len(caps_file) != len(self.subjects): raise IOError(str(len(caps_file)) + ' file(s) grabbed, but there is ' + str(len(self.subjects)) + ' sessions') read_parameters_node.inputs.file_list = caps_file self.connect([(read_parameters_node, self.input_node, [('file_list', 'file_list')]), (read_parameters_node, self.input_node, [('atlas_list', 'atlas_list')]) ])