# Copyright (C) 2009-2021, Ecole Polytechnique Federale de Lausanne (EPFL) and
# Hospital Center and University of Lausanne (UNIL-CHUV), Switzerland, and CMP3 contributors
# All rights reserved.
#
# This software is distributed under the open-source license Modified BSD.
"""Connectome Mapper GUI."""
# General imports
import os
import sys
import pkg_resources
from subprocess import Popen
import subprocess
import multiprocessing
import shutil
import time
import glob
from pyface.api import ImageResource
from traitsui.qt4.extra.qt_view import QtView
from traitsui.tabular_adapter import TabularAdapter
from traitsui.api import *
from traits.api import *
from bids import BIDSLayout
import warnings
# Own imports
import cmp.bidsappmanager.project as project
from cmp.project import CMP_Project_Info
from cmp.info import __version__
from cmtklib.util import return_button_style_sheet, \
BColors, print_blue, print_warning, print_error
# Remove warnings visible whenever you import scipy (or another package)
# that was compiled against an older numpy than is installed.
warnings.filterwarnings("ignore", message="numpy.dtype size changed")
warnings.filterwarnings("ignore", message="numpy.ufunc size changed")
# global modal_width
modal_width = 400
# global style_sheet
style_sheet = '''
QLabel {
font: 12pt "Verdana";
margin-left: 5px;
background-color: transparent;
}
QPushButton {
border: 0px solid lightgray;
border-radius: 4px;
color: transparent;
background-color: transparent;
min-width: 222px;
icon-size: 222px;
font: 12pt "Verdana";
margin: 0px 0px 0px 0px;
padding:0px 0px;
}
QPushButton:pressed {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #dadbde, stop: 1 #f6f7fa);
}
QMenuBar {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #dadbde, stop: 1 #f6f7fa)
font: 14pt "Verdana";
}
QMenuBar::item {
spacing: 5px; /* spacing between menu bar items */
padding: 5px 5px;
background: transparent;
border-radius: 4px;
}
QMenuBar::item:selected { /* when selected using mouse or keyboard */
background: #a8a8a8;
}
QMenuBar::item:pressed {
background: #888888;
}
QMainWindow {
background-color: yellow;
image: url("images/cmp.png");
}
QMainWindow::separator {
background: yellow;
width: 1px; /* when vertical */
height: 1px; /* when horizontal */
}
QMainWindow::separator:hover {
background: red;
}
QListView::item:selected {
border: 1px solid #6a6ea9;
}
QListView::item:selected:!active {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #ABAFE5, stop: 1 #8588B2);
}
QListView::item:selected:active {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #6a6ea9, stop: 1 #888dd9);
}
QListView::item:hover {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #FAFBFE, stop: 1 #DCDEF1);
}
QProgressBar {
border: 2px solid grey;
border-radius: 5px;
}
QProgressBar::chunk {
background-color: #05B8CC;
width: 20px;
}
'''
[docs]def get_icon(path):
"""Return an instance of `ImageResource` or None is there is not graphical backend.
Parameters
----------
path : string
Path to an image file
Returns
-------
icon : ImageResource
Return an instance of `ImageResource` or None is there is not graphical backend.
"""
on_rtd = os.environ.get("READTHEDOCS") == "True"
if on_rtd:
print('READTHEDOCS: Return None for icon')
icon = None
else:
icon = ImageResource(path)
return icon
[docs]class CMP_Project_InfoUI(CMP_Project_Info):
"""Class that extends the :class:`CMP_Project_Info` with graphical components.
It supports graphically the setting of all processing properties / attributes
of an :class:`CMP_Project_Info` instance.
Attributes
-----------
creation_mode : traits.Enum
Mode for loading the dataset. Valid values are
'Load BIDS dataset', 'Install Datalad BIDS dataset'
install_datalad_dataset_via_ssh : traits.Bool
If set to True install the datalad dataset from a remote server
via ssh.(True by default)
ssh_user : traits.Str
Remote server username.
(Required if ``install_datalad_dataset_via_ssh`` is True)
ssh_pwd <traits.Password>
Remote server password.
(Required if ``install_datalad_dataset_via_ssh`` is True)
ssh_remote : traits.Str
Remote server IP or URL.
(Required if ``install_datalad_dataset_via_ssh`` is True)
datalad_dataset_path : traits.Directory
Path to the datalad dataset on the remote server.
(Required if ``install_datalad_dataset_via_ssh`` is True)
summary_view_button : traits.ui.Button
Button that shows the pipeline processing summary table
pipeline_processing_summary_view : traits.ui.VGroup
TraitsUI VGroup that contains ``Item('pipeline_processing_summary')``
dataset_view : traits.ui.View
TraitsUI View that shows a summary of project settings and
modality available for a given subject
traits_view : QtView
TraitsUI QtView that includes the View 'dataset_view'
create_view : traits.ui.View
Dialog view to create a BIDS Dataset
subject_view : traits.ui.View
Dialog view to select of subject
subject_session_view : traits.ui.View
Dialog view to select the subject session
dmri_bids_acq_view : traits.ui.View
Dialog view to select the diffusion acquisition model
anat_warning_view : traits.ui.View
View that displays a warning message regarding
the anatomical T1w data
anat_config_error_view : traits.ui.View
Error view that displays an error message regarding
the configuration of the anatomical pipeline
dmri_warning_view : traits.ui.View
View that displays a warning message regarding
the diffusion MRI data
dmri_config_error_view : traits.ui.View
View that displays an error message regarding
the configuration of the diffusion pipeline
fmri_warning_view : traits.ui.View
View that displays a warning message regarding
the functional MRI data
fmri_config_error_view : traits.ui.View
View that displays an error message regarding
the configuration of the fMRI pipeline
open_view : traits.ui.View
Dialog view to load a BIDS Dataset
anat_select_config_to_load : traits.ui.View
Dialog view to load the configuration file of the anatomical pipeline
diffusion_imaging_model_select_view : traits.ui.View
Dialog view to select the diffusion acquisition model
dmri_select_config_to_load : traits.ui.View
Dialog view to load the configuration file of the diffusion MRI pipeline
fmri_select_config_to_load : traits.ui.View
Dialog view to load the configuration file of the fMRI pipeline
"""
creation_mode = Enum('Load BIDS dataset', 'Install Datalad BIDS dataset')
install_datalad_dataset_via_ssh = Bool(True)
ssh_user = String('remote_username')
ssh_pwd = Password('')
ssh_remote = String('IP address/ Machine name')
datalad_dataset_path = Directory(
'/shared/path/to/existing/datalad/dataset')
anat_runs = List()
anat_run = Enum(values='anat_runs')
dmri_runs = List()
dmri_run = Enum(values='dmri_runs')
fmri_runs = List()
fmri_run = Enum(values='fmri_runs')
summary_view_button = Button('Pipeline processing summary')
pipeline_processing_summary_view = VGroup(Item('pipeline_processing_summary'))
dataset_view = VGroup(
VGroup(
HGroup(
Item('base_directory', width=-0.3,
style='readonly', label="", resizable=True),
Item('number_of_subjects',
width=-0.3,
style='readonly',
label="Number of participants",
resizable=True),
'summary_view_button'),
label='BIDS Dataset'),
spring,
HGroup(
Group(
Item('subject', style='simple',
show_label=True, resizable=True)),
Group(
Item('subject_session', style='simple',
label="Session", resizable=True),
visible_when='subject_session!=""'),
springy=True),
spring,
Group(
Item('t1_available', style='readonly', label='T1', resizable=True),
HGroup(
Item('dmri_available', style='readonly',
label='Diffusion', resizable=True),
Item('diffusion_imaging_model', label='Model',
resizable=True, enabled_when='dmri_available')),
Item('fmri_available', style='readonly',
label='BOLD', resizable=True),
label='Modalities'),
spring,
Group(
Item('anat_last_date_processed', label="Anatomical pipeline",
style='readonly', resizable=True,
enabled_when='t1_available'),
Item('dmri_last_date_processed', label="Diffusion pipeline",
style='readonly', resizable=True,
enabled_when='dmri_available'),
Item('fmri_last_date_processed', label="fMRI pipeline",
style='readonly', resizable=True,
enabled_when='fmri_available'),
label="Last date processed"),
spring,
Group(
Item('number_of_cores', resizable=True),
label='Processing configuration'),
'550',
spring,
springy=True)
traits_view = QtView(Include('dataset_view'))
create_view = View(
Item('creation_mode', style='custom'),
Group(
Group(
Item('base_directory', label='BIDS Dataset'),
visible_when='creation_mode=="Load BIDS dataset"'),
Group(
Item('install_datalad_dataset_via_ssh'),
visible_when='creation_mode=="Install Datalad/BIDS dataset"'),
Group(
Item('ssh_remote', label='Remote ssh server',
visible_when='install_datalad_dataset_via_ssh'),
Item('ssh_user', label='Remote username',
visible_when='install_datalad_dataset_via_ssh'),
Item('ssh_pwd', label='Remote password',
visible_when='install_datalad_dataset_via_ssh'),
Item('datalad_dataset_path',
label='Datalad/BIDS Dataset Path/URL to be installed'),
Item('base_directory', label='Installation directory'),
visible_when='creation_mode=="Install Datalad/BIDS dataset"'),
),
kind='livemodal',
title='Data creation: BIDS dataset selection',
# style_sheet=style_sheet,
width=modal_width,
buttons=['OK', 'Cancel'])
subject_view = View(
Group(
Item('subject', label='Selected Subject')
),
kind='modal',
title='Subject and session selection',
# style_sheet=style_sheet,
width=modal_width,
buttons=['OK', 'Cancel'])
subject_session_view = View(
Group(
Item('subject', style='readonly', label='Selected Subject'),
Item('subject_session', label='Selected Session'),
),
kind='modal',
title='Session selection',
# style_sheet=style_sheet,
width=modal_width,
buttons=['OK', 'Cancel'])
dmri_bids_acq_view = View(
Group(
Item('dmri_bids_acq', label='Selected model'),
),
kind='modal',
title='Selection of diffusion acquisition model',
# style_sheet=style_sheet,
width=modal_width,
buttons=['OK', 'Cancel'])
anat_warning_view = View(
Group(
Item('anat_warning_msg', style='readonly', show_label=False),
),
title='Warning : Anatomical T1w data',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
anat_config_error_view = View(
Group(
Item('anat_config_error_msg', style='readonly', show_label=False),
),
title='Error',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
dmri_warning_view = View(
Group(
Item('dmri_warning_msg', style='readonly', show_label=False),
),
title='Warning : Diffusion MRI data',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
dmri_config_error_view = View(
Group(
Item('dmri_config_error_msg', style='readonly', show_label=False),
),
title='Error',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
fmri_warning_view = View(
Group(
Item('fmri_warning_msg', style='readonly', show_label=False),
),
title='Warning : fMRI data',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
fmri_config_error_view = View(
Group(
Item('fmri_config_error_msg', style='readonly', show_label=False),
),
title='Error',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
open_view = View(
Item('creation_mode', label='Mode'),
Group(
Item('install_datalad_dataset_via_ssh'),
Item('ssh_remote', label='Remote ssh server',
visible_when='install_datalad_dataset_via_ssh'),
Item('ssh_user', label='Remote username',
visible_when='install_datalad_dataset_via_ssh'),
Item('ssh_pwd', label='Remote password',
visible_when='install_datalad_dataset_via_ssh'),
Item('datalad_dataset_path',
label='Datalad/BIDS Dataset Path/URL to be installed'),
Item('base_directory', label='Installation directory'),
visible_when='creation_mode=="Install Datalad BIDS dataset"'),
Group(
Item('base_directory', label='BIDS Dataset'),
visible_when='creation_mode=="Load BIDS dataset"'),
kind='livemodal',
title='BIDS Dataset Creation/Loading',
# style_sheet=style_sheet,
width=600,
height=250,
buttons=['OK', 'Cancel'])
anat_select_config_to_load = View(
Group(
Item('anat_config_to_load_msg', style='readonly', show_label=False),
Item('anat_config_to_load', style='custom', editor=EnumEditor(name='anat_available_config'),
show_label=False)
),
title='Select configuration for anatomical pipeline',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
anat_custom_map_view = View(
Group(
Item('anat_custom_last_stage', editor=EnumEditor(name='anat_stage_names'), style='custom',
show_label=False),
),
title='Select until which stage to process the anatomical pipeline.',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
diffusion_imaging_model_select_view = View(
Group(
Item('diffusion_imaging_model', label='Diffusion MRI modality'),
),
title='Please select diffusion MRI modality',
kind='modal',
width=modal_width,
buttons=['OK', 'Cancel'])
dmri_select_config_to_load = View(
Group(
Item('dmri_config_to_load_msg', style='readonly', show_label=False),
),
Item('dmri_config_to_load', style='custom', editor=EnumEditor(
name='dmri_available_config'), show_label=False),
title='Select configuration for diffusion pipeline',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
dmri_custom_map_view = View(
Group(
Item('dmri_custom_last_stage', editor=EnumEditor(name='dmri_stage_names'), style='custom',
show_label=False),
),
title='Select until which stage to process the diffusion pipeline.',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
fmri_select_config_to_load = View(
Group(
Item('fmri_config_to_load_msg', style='readonly', show_label=False),
),
Item('fmri_config_to_load', style='custom', editor=EnumEditor(
name='fmri_available_config'), show_label=False),
title='Select configuration for fMRI pipeline',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
fmri_custom_map_view = View(
Group(
Item('fmri_custom_last_stage', editor=EnumEditor(name='fmri_stage_names'), style='custom',
show_label=False),
),
title='Select until which stage to process the fMRI pipeline.',
kind='modal',
width=modal_width,
# style_sheet=style_sheet,
buttons=['OK', 'Cancel'])
def _summary_view_button_fired(self):
self.configure_traits(view='pipeline_processing_summary_view')
[docs]class MultiSelectAdapter(TabularAdapter):
"""This adapter is used by left and right tables for selection of subject to be processed."""
# Titles and column names for each column of a table.
# In this example, each table has only one column.
columns = [('', 'myvalue')]
width = 100
# Magically named trait which gives the display text of the column named
# 'myvalue'. This is done using a Traits Property and its getter:
myvalue_text = Property
def _get_myvalue_text(self):
"""The getter for Property 'myvalue_text'.
It simply takes the value of the corresponding item in the list
being displayed in this table. A more complicated example could
format the item before displaying it.
"""
return 'sub-%s' % self.item
[docs]class CMP_BIDSAppWindow(HasTraits):
"""Class that defines the Window of the BIDS App Interface.
Attributes
----------
project_info : CMP_Project_Info
Instance of :class:`CMP_Project_Info` that represents the processing project
bids_root : traits.Directory
BIDS root dataset directory
output_dir : traits.Directory
Output directory
subjects : traits.List
List of subjects (in the form ``sub-XX``) present in the dataset
number_of_participants_processed_in_parallel : traits.Range
Number of participants / subjects to be processed in parallel that
takes values in the [1, # of CPUs - 1] range
number_threads_max : traits.Int
Maximal number of threads to be used by OpenMP programs
(4 by default)
number_of_threads : traits.Range
Number of threads to be used by OpenMP programs that takes values
in the [1, ``number_threads_max``] range
fs_file : traits.File
Path to Freesurfer license file
list_of_subjects_to_be_processed : List(Str)
Selection of subjects to be processed from the ``subjects`` list
dmri_inputs_checked : traits.Bool
True if dMRI data is available in the dataset
fmri_inputs_checked : traits.Bool
rue if fMRI data is available in the dataset
anat_config : traits.File
Configuration file for the anatomical MRI pipeline
dmri_config : traits.File
Configuration file for the diffusion MRI pipeline
fmri_config : traits.File
Configuration file for the functional MRI pipeline
run_anat_pipeline : traits.Bool
If True, run the anatomical pipeline
run_dmri_pipeline : traits.Bool
If True, run the diffusion pipeline
run_fmri_pipeline : traits.Bool
If True, run the functional pipeline
bidsapp_tag : traits.Enum
Selection of BIDS App version to use
data_provenance_tracking : traits.Bool
If set and if ``datalad_is_available`` is True run the BIDS App
using datalad (False by default)
datalad_update_environment : traits.Bool
If True and ``data_provenance_tracking`` is True, tell to datalad
to update the BIDS App container image if there was a previous
execution (True by default)
datalad_is_available : traits.Bool
Boolean used to store if datalad is available in the computing
environment (False by default)
check : traits.ui.Button
Button to check if all parameters are properly set for execution
of the BIDS App
start_bidsapp : traits.ui.Button
Button to run the BIDS App
traits_view : QtView
TraitsUI QtView that describes the content of the window
"""
project_info = Instance(CMP_Project_Info)
bids_root = Directory()
output_dir = Directory()
subjects = List(Str)
# multiproc_number_of_cores = Int(1)
number_of_participants_processed_in_parallel = Range(low=1,
high=multiprocessing.cpu_count()-1,
desc='Number of participants to be processed in parallel')
number_of_threads_max = Int(multiprocessing.cpu_count()-1)
number_of_threads = Range(low=1,
high='number_of_threads_max',
mode='spinner',
desc='Number of OpenMP threads used by Dipy, FSL, MRtrix, '
'and Freesurfer recon-all')
fix_ants_random_seed = Bool(False, desc='Fix MRtrix3 random generator seed for tractography')
ants_random_seed = Int(1234, desc='MRtrix random generator seed value')
fix_mrtrix_random_seed = Bool(False, desc='Fix ANTs random generator seed for registration')
mrtrix_random_seed = Int(1234, desc='ANTs random generator seed value')
fix_ants_number_of_threads = Bool(False, desc='Fix independently number of threads used by ANTs registration')
ants_number_of_threads = Range(low=1,
high='number_of_threads_max',
mode='spinner',
desc='Number of ITK threads used by ANTs registration')
fs_license = File(desc='Path to your FREESURFER license.txt')
# fs_average = Directory(os.path.join(os.environ['FREESURFER_HOME'],'subjects','fsaverage'))
list_of_subjects_to_be_processed = List(Str)
list_of_processing_logfiles = List(File)
anat_config = File(desc='Path to the configuration file of the anatomical pipeline')
dmri_config = File(desc='Path to the configuration file of the diffusion pipeline')
fmri_config = File(desc='Path to the configuration file of the fMRI pipeline')
run_anat_pipeline = Bool(True, desc='Run the anatomical pipeline')
run_dmri_pipeline = Bool(False, desc='Run the diffusion pipeline')
run_fmri_pipeline = Bool(False, desc='Run the fMRI pipeline')
dmri_inputs_checked = Bool(False)
fmri_inputs_checked = Bool(False)
settings_checked = Bool(False)
docker_running = Bool(False)
bidsapp_tag = Enum('{}'.format(__version__), [
'latest', '{}'.format(__version__)])
data_provenance_tracking = Bool(False,
desc='Use datalad to execute CMP3 and record dataset changes')
datalad_update_environment = Bool(True,
desc='Update the container if datalad run-container has been run already once')
datalad_is_available = Bool(False,
desc='True if datalad is available')
# check = Action(name='Check settings!',
# action='check_settings',
# image=get_icon(
# pkg_resources.resource_filename('resources',
# os.path.join('buttons', 'bidsapp-check-settings.png'))))
# start_bidsapp = Action(name='Start BIDS App!',
# action='start_bids_app',
# enabled_when='settings_checked==True and docker_running==False',
# image=get_icon(
# pkg_resources.resource_filename('resources',
# os.path.join('buttons', 'bidsapp-run.png'))))
update_selection = Button()
check = Button()
start_bidsapp = Button()
# stop_bidsapp = Action(name='Stop BIDS App!',action='stop_bids_app',enabled_when='handler.settings_checked and handler.docker_running')
traits_view = QtView(Group(
VGroup(
VGroup(
Item('bidsapp_tag', style='readonly', label='Tag'),
label='BIDS App Version'),
VGroup(
Item('bids_root', style='readonly', label='Input directory'),
Item('output_dir', style='simple', label='Output directory',
enabled_when='not(data_provenance_tracking)'),
label='BIDS dataset'),
VGroup(
HGroup(
UItem('subjects',
editor=TabularEditor(
show_titles=True,
selected='list_of_subjects_to_be_processed',
editable=False,
multi_select=True,
adapter=MultiSelectAdapter(columns=[('Available labels', 'myvalue')]))
),
UItem('list_of_subjects_to_be_processed',
editor=TabularEditor(
show_titles=True,
editable=False,
adapter=MultiSelectAdapter(columns=[('Labels to be processed', 'myvalue')]))
),
),
label='Participant labels to be processed'),
HGroup(
Item('number_of_participants_processed_in_parallel',
label='Number of participants processed in parallel'),
label='Parallel processing'
),
VGroup(
HGroup(
VGroup(Item('number_of_threads',
label='Number of OpenMP threads'),
Item('fix_ants_number_of_threads',
label='Set number of threads used by ANTs'),
Item('ants_number_of_threads',
label='Number of ITK threads used by ANTs registration',
enabled_when='fix_ants_number_of_threads'),
label='Multithreading'),
VGroup(Item('fix_ants_random_seed',
label='Set seed of ANTS random number generator'),
Item('ants_random_seed',
label='Seed',
enabled_when='fix_ants_random_seed'),
Item('fix_mrtrix_random_seed',
label='Set seed of MRtrix random number generator'),
Item('mrtrix_random_seed',
label='Seed',
enabled_when='fix_mrtrix_random_seed'),
label='Random number generators'),
),
label='Advanced execution settings for each participant process'
),
VGroup(
Group(Item('anat_config',
editor=FileEditor(dialog_style='open'),
label='Configuration file', visible_when='run_anat_pipeline'),
label='Anatomical pipeline'),
Group(Item('run_dmri_pipeline', label='Run processing stages'),
Item('dmri_config',
editor=FileEditor(dialog_style='open'),
label='Configuration file',
visible_when='run_dmri_pipeline'),
label='Diffusion pipeline',
visible_when='dmri_inputs_checked==True'),
Group(Item('run_fmri_pipeline', label='Run processing stages'),
Item('fmri_config',
editor=FileEditor(dialog_style='open'),
label='Configuration file',
visible_when='run_fmri_pipeline'),
label='fMRI pipeline',
visible_when='fmri_inputs_checked==True'),
label='Configuration of processing pipelines'),
VGroup(
Item('fs_license',
editor=FileEditor(dialog_style='open'),
label='LICENSE'),
# Item('fs_average', label='FSaverage directory'),
label='Freesurfer configuration'),
VGroup(
Item('data_provenance_tracking', label='Use Datalad'),
Item('datalad_update_environment', visible_when='data_provenance_tracking',
label='Update the computing environment (if existing)'),
label='Data Provenance Tracking / Data Lineage',
enabled_when='datalad_is_available'),
orientation='vertical', springy=True),
spring,
HGroup(spring, Item('check', style='custom',
width=152, height=35, resizable=False,
label='', show_label=False,
style_sheet=return_button_style_sheet(
ImageResource(
pkg_resources.resource_filename(
'resources',
os.path.join('buttons', 'bidsapp-check-settings.png'))).absolute_path)
),
spring,
Item('start_bidsapp', style='custom',
width=152, height=35, resizable=False,
label='', show_label=False,
style_sheet=return_button_style_sheet(
ImageResource(
pkg_resources.resource_filename(
'resources',
os.path.join('buttons', 'bidsapp-run.png'))).absolute_path,
ImageResource(
pkg_resources.resource_filename(
'resources',
os.path.join('buttons', 'bidsapp-run-disabled.png'))).absolute_path
),
enabled_when='settings_checked==True and docker_running==False'),
spring,
show_labels=False, label=""),
orientation='vertical',
springy=True),
title='Connectome Mapper 3 BIDS App GUI',
# kind='modal',
handler=project.CMP_BIDSAppWindowHandler(),
# style_sheet=style_sheet,
buttons=[],
# buttons = [check,start_bidsapp],
# buttons = [process_anatomical,map_dmri_connectome,map_fmri_connectome],
# buttons = [preprocessing, map_connectome, map_custom],
width=0.6, height=0.8, scrollable=True, # , resizable=True
icon=get_icon('bidsapp.png')
)
log_view = QtView(Group(
Item('list_of_processing_logfiles'),
orientation='vertical', springy=True),
title='Connectome Mapper 3 BIDS App Progress',
# kind='modal',
# handler=project.CMP_BIDSAppWindowHandler(),
# style_sheet=style_sheet,
buttons=[],
# buttons = [check,start_bidsapp],
# buttons = [process_anatomical,map_dmri_connectome,map_fmri_connectome],
# buttons = [preprocessing, map_connectome, map_custom],
width=0.5, height=0.8, resizable=True, # , scrollable=True, resizable=True
icon=get_icon('bidsapp.png')
)
def __init__(self, project_info=None, bids_root='', subjects=None, list_of_subjects_to_be_processed=None,
anat_config='', dmri_config='', fmri_config=''):
"""Constructor of an :class:``CMP_BIDSAppWindow`` instance.
Parameters
----------
project_info : cmp.project.CMP_Project_Info
:class:`CMP_Project_Info` object (Default: None)
bids_root : traits.Directory
BIDS dataset root directory (Default: \'\')
subjects : List of string
List of subjects in the dataset (Default: None)
list_of_subjects_to_be_processed : List of string
List of subjects to be processed (Default: None)
anat_config : string
Path to anatomical pipeline configuration file (Default: \'\')
dmri_config : string
Path to diffusion pipeline configuration file (Default: \'\')
fmri_config : string
Path to functional pipeline configuration file (Default: \'\')
"""
print('> Initialize window...')
if multiprocessing.cpu_count() < 4:
self.number_of_threads_max = multiprocessing.cpu_count()
self.project_info = project_info
self.bids_root = bids_root
# Create a BIDSLayout for checking availability of dMRI and fMRI data
try:
bids_layout = BIDSLayout(self.bids_root)
except Exception:
print_error(" .. Exception : Raised at BIDSLayout")
sys.exit(1)
# Check if sMRI data is available in the dataset
smri_files = bids_layout.get(datatype='anat',
suffix='T1w',
extensions='nii.gz',
return_type='file')
if not smri_files:
anat_inputs_checked = False
else:
anat_inputs_checked = True
print(f' .. T1w available: {anat_inputs_checked}')
# Check if dMRI data is available in the dataset
dmri_files = bids_layout.get(datatype='dwi',
suffix='dwi',
extensions='nii.gz',
return_type='file')
if not dmri_files:
self.dmri_inputs_checked = False
self.run_dmri_pipeline = False
else:
self.dmri_inputs_checked = True
self.run_dmri_pipeline = True
print(f' .. DWI available: {self.dmri_inputs_checked}')
# Check if fMRI data is available in the dataset
fmri_files = bids_layout.get(task='rest',
datatype='func',
suffix='bold',
extensions='nii.gz',
return_type='file')
if not fmri_files:
self.fmri_inputs_checked = False
self.run_fmri_pipeline = False
else:
self.fmri_inputs_checked = True
self.run_fmri_pipeline = True
print(f' .. rsfMRI available: {self.fmri_inputs_checked}')
# Initialize output directory to be /bids_dir/derivatives
self.output_dir = os.path.join(bids_root, 'derivatives')
self.subjects = subjects
# self.list_of_subjects_to_be_processed = list_of_subjects_to_be_processed
self.anat_config = anat_config
self.dmri_config = dmri_config
self.fmri_config = fmri_config
if 'FREESURFER_HOME' in os.environ:
self.fs_license = os.path.join(
os.environ['FREESURFER_HOME'], 'license.txt')
else:
print_error(' .. ERROR: Environment variable $FREESURFER_HOME not found')
self.fs_license = ''
print_warning('Freesurfer license unset ({})'.format(self.fs_license))
self.datalad_is_available = project.is_tool('datalad')
self.on_trait_change(
self.update_run_dmri_pipeline, 'run_dmri_pipeline')
self.on_trait_change(
self.update_run_fmri_pipeline, 'run_fmri_pipeline')
self.on_trait_change(self.number_of_parallel_procs_updated,
'number_of_participants_processed_in_parallel')
self.on_trait_change(self.update_checksettings,
'list_of_subjects_to_be_processed')
self.on_trait_change(self.update_checksettings, 'anat_config')
self.on_trait_change(self.update_checksettings, 'run_dmri_pipeline')
self.on_trait_change(self.update_checksettings, 'dmri_config')
self.on_trait_change(self.update_checksettings, 'run_fmri_pipeline')
self.on_trait_change(self.update_checksettings, 'fmri_config')
self.on_trait_change(self.update_checksettings, 'fs_license')
# self.on_trait_change(self.update_checksettings, 'fs_average')
[docs] def number_of_parallel_procs_updated(self, new):
"""Callback function when ``number_of_parallel_procs`` is updated."""
number_of_threads_max = int((multiprocessing.cpu_count() - 1) / new)
if number_of_threads_max > 4:
self.number_of_threads_max = 4
else:
self.number_of_threads_max = number_of_threads_max
print(' .. INFO : Update number of threads max to : {}'.format(self.number_of_threads_max))
[docs] def update_run_anat_pipeline(self, new):
"""Callback function when ``run_anat_pipeline`` is updated."""
if new is False:
print_warning(' .. WARNING: At least anatomical pipeline should be run!')
self.run_anat_pipeline = True
[docs] def update_run_dmri_pipeline(self, new):
"""Callback function when ``run_dmri_pipeline`` is updated."""
self.run_anat_pipeline = True
[docs] def update_run_fmri_pipeline(self, new):
"""Callback function when ``run_fmri_pipeline`` is updated."""
self.run_anat_pipeline = True
[docs] def update_checksettings(self, new):
"""Function that reset ``settings_checked`` attribute to False."""
self.settings_checked = False
def _data_provenance_tracking_changed(self, new):
"""Callback function `data_provenance_tracking` attribute is updated."""
if new is True:
self.output_dir = os.path.join(self.bids_root, 'derivatives')
self.data_provenance_tracking = new
def _update_selection_fired(self):
"""Callback function when the list of selected subjects is updated."""
self.configure_traits(view='select_subjects_to_be_processed_view')
def _check_fired(self):
"""Callback function when the Check Setting button is clicked."""
self.check_settings()
def _start_bidsapp_fired(self):
"""Callback function when the Run BIDS App button is clicked."""
self.start_bids_app()
[docs] def check_settings(self):
"""Checks if all the parameters of the BIDS App run are properly set before execution."""
print_warning('\n-----------------------------------------')
print_warning('BIDS App execution settings check summary')
print_warning('-----------------------------------------')
self.settings_checked = True
if os.path.isdir(self.bids_root):
print(f'* BIDS root directory : {self.bids_root}')
else:
print_error("Error: BIDS root invalid!")
self.settings_checked = False
if os.path.exists(os.path.join(self.output_dir, 'cmp')):
print(f'* Output directory (existing) : {self.output_dir}')
else:
os.makedirs(os.path.join(self.output_dir, 'cmp'))
print_warning(f'Output directory (created) : {self.output_dir}')
if len(self.list_of_subjects_to_be_processed) > 0:
print(f'* Participant labels to be processed : {self.list_of_subjects_to_be_processed}')
else:
print_error("Error: At least one participant label to be processed should selected!")
self.settings_checked = False
# if not self.list_of_subjects_to_be_processed.empty():
# print("List of subjects to be processed : {}".format(self.list_of_subjects_to_be_processed))
# else:
# print("Warning: List of subjects empty!")
if os.path.isfile(self.anat_config):
print(f'* Anatomical configuration file : {self.anat_config}')
else:
print_error("Error: Configuration file for anatomical pipeline not existing!")
self.settings_checked = False
if os.path.isfile(self.dmri_config):
print(f'* Diffusion configuration file : {self.dmri_config}')
else:
print_warning("Warning: Configuration file for diffusion pipeline not existing!")
if os.path.isfile(self.fmri_config):
print(f'* fMRI configuration file : {self.fmri_config}')
else:
print_warning("Warning: Configuration file for fMRI pipeline not existing!")
if os.path.isfile(self.fs_license):
print(f'* Freesurfer license : {self.fs_license}')
else:
print_error(f'Error: Invalid Freesurfer license ({self.fs_license})!')
self.settings_checked = False
# if os.path.isdir(self.fs_average):
# print("fsaverage directory : {}".format(self.fs_average))
# else:
# print("Error: fsaverage directory ({}) not existing!".format(self.fs_average))
# self.settings_checked = False
print(f'Valid inputs for BIDS App : {self.settings_checked}')
print(f'BIDS App Version Tag: {self.bidsapp_tag}')
print(f'Data provenance tracking (datalad) : {self.data_provenance_tracking}')
print(f'Update computing environment (datalad) : {self.datalad_update_environment}')
print(f'Number of participant processed in parallel : {self.number_of_participants_processed_in_parallel}')
print(f'Number of OpenMP threads / participant : {self.number_of_threads}')
print(f'Fix number of ITK threads : {self.fix_ants_number_of_threads}')
if self.fix_ants_number_of_threads:
print(f'Number of ITK threads (ANTs) / participant : {self.ants_number_of_threads}')
print(f'Fix seed in ANTS random number generator : {self.fix_ants_random_seed}')
if self.fix_ants_random_seed:
print(f'Seed value : {self.ants_random_seed}')
print(f'Fix seed in MRtrix random number generator : {self.fix_mrtrix_random_seed}')
if self.fix_ants_random_seed:
print(f'Seed value : {self.mrtrix_random_seed}')
print('-----------------------------------------\n')
return True
[docs] def start_bidsapp_participant_level_process(self, bidsapp_tag, participant_labels):
"""Create and run the BIDS App command.
Parameters
----------
bidsapp_tag : traits.Str
Version tag of the CMP 3 BIDS App
participant_labels : traits.List
List of participants labels in the form ["01", "03", "04", ...]
"""
cmd = ['docker', 'run', '-it', '--rm',
'-v', '{}:/bids_dir'.format(self.bids_root),
'-v', '{}:/output_dir'.format(self.output_dir),
'-v', '{}:/bids_dir/code/license.txt'.format(self.fs_license),
'-v', '{}:/code/ref_anatomical_config.json'.format(self.anat_config),
]
if self.run_dmri_pipeline:
cmd.append('-v')
cmd.append('{}:/code/ref_diffusion_config.json'.format(self.dmri_config))
if self.run_fmri_pipeline:
cmd.append('-v')
cmd.append('{}:/code/ref_fMRI_config.json'.format(self.fmri_config))
cmd.append('-u')
cmd.append('{}:{}'.format(os.geteuid(), os.getegid()))
cmd.append(
'sebastientourbier/connectomemapper-bidsapp:{}'.format(bidsapp_tag))
cmd.append('/bids_dir')
cmd.append('/output_dir')
cmd.append('participant')
cmd.append('--participant_label')
for label in participant_labels:
cmd.append('{}'.format(label))
cmd.append('--anat_pipeline_config')
cmd.append('/code/ref_anatomical_config.json')
if self.run_dmri_pipeline:
cmd.append('--dwi_pipeline_config')
cmd.append('/code/ref_diffusion_config.json')
if self.run_fmri_pipeline:
cmd.append('--func_pipeline_config')
cmd.append('/code/ref_fMRI_config.json')
cmd.append('--fs_license')
cmd.append('{}'.format('/bids_dir/code/license.txt'))
cmd.append('--number_of_participants_processed_in_parallel')
cmd.append('{}'.format(self.number_of_participants_processed_in_parallel))
cmd.append('--number_of_threads')
cmd.append('{}'.format(self.number_of_threads))
if self.fix_ants_number_of_threads:
cmd.append('--ants_number_of_threads')
cmd.append('{}'.format(self.ants_number_of_threads))
if self.fix_ants_random_seed:
cmd.append('--ants_random_seed')
cmd.append('{}'.format(self.ants_random_seed))
if self.fix_mrtrix_random_seed:
cmd.append('--mrtrix_random_seed')
cmd.append('{}'.format(self.mrtrix_random_seed))
print_blue('... BIDS App execution command: {}'.format(' '.join(cmd)))
proc = Popen(cmd)
# proc = Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
return proc
[docs] def start_bidsapp_participant_level_process_with_datalad(self, bidsapp_tag, participant_labels):
"""Create and run the BIDS App command with Datalad.
Parameters
----------
bidsapp_tag : traits.Str
Version tag of the CMP 3 BIDS App
participant_labels : traits.List
List of participants labels in the form ["01", "03", "04", ...]
"""
cmd = ['datalad',
'containers-run',
'--container-name',
'connectomemapper-bidsapp-{}'.format("-".join(bidsapp_tag.split("."))),
'-m',
'Processing with connectomemapper-bidsapp {}'.format(bidsapp_tag),
'--input',
f'{self.anat_config}']
# for label in participant_labels:
# cmd.append('--input')
# cmd.append('sub-{}/ses-*/anat/sub-*_T1w.*'.format(label))
#
# cmd.append('--input')
# cmd.append('derivatives/freesurfer/sub-{}*/*'.format(label))
#
# if self.run_dmri_pipeline:
# cmd.append('--input')
# cmd.append('sub-{}/ses-*/dwi/sub-*_dwi.*'.format(label))
#
# if self.run_fmri_pipeline:
# cmd.append('--input')
# cmd.append('sub-{}/ses-*/func/sub-*_bold.*'.format(label))
if self.run_dmri_pipeline:
cmd.append('--input')
cmd.append(f'{self.dmri_config}')
if self.run_fmri_pipeline:
cmd.append('--input')
cmd.append(f'{self.fmri_config}')
cmd.append('--output')
cmd.append(f'{self.output_dir}')
# for label in participant_labels:
# cmd.append('--input')
# cmd.append('{}'.format(label))
cmd.append('/bids_dir')
cmd.append('/output_dir')
cmd.append('participant')
cmd.append('--participant_label')
for label in participant_labels:
cmd.append('{}'.format(label))
# Counter to track position of config file as --input
i = 0
cmd.append('--anat_pipeline_config')
cmd.append('/{{inputs[{}]}}'.format(i))
i += 1
if self.run_dmri_pipeline:
cmd.append('--dwi_pipeline_config')
cmd.append('/{{inputs[{}]}}'.format(i))
i += 1
if self.run_fmri_pipeline:
cmd.append('--func_pipeline_config')
cmd.append('/{{inputs[{}]}}'.format(i))
print_blue('... Datalad cmd : {}'.format(' '.join(cmd)))
proc = Popen(cmd, cwd=os.path.join(self.bids_root))
# proc = Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=os.path.join(self.bids_root,'derivatives'))
return proc
[docs] @classmethod
def manage_bidsapp_procs(self, proclist):
"""Manage parallelized process at the participant level
Parameters
----------
proclist : List of subprocess.Popen
List of Popen processes
"""
for proc in proclist:
if proc.poll() is not None:
proclist.remove(proc)
[docs] @classmethod
def run(self, command, env=None, cwd=os.getcwd()):
"""Function to run datalad commands.
It runs the command specified as input via ``subprocess.run()``.
Parameters
----------
command : string
String containing the command to be executed (required)
env : os.environ
Specify a custom os.environ
cwd : os.path
Specify a custom current working directory
Examples
--------
>>> cmd = 'datalad save -m my dataset change message'
>>> run(cmd) # doctest: +SKIP
"""
merged_env = os.environ
if env is not None:
merged_env.update(env)
process = Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=True,
env=merged_env,
cwd=cwd)
while True:
line = process.stdout.readline()
# Remove the "b'" prefix and the "'" at the end return by datalad
line = str(line)[2:-1]
print(line)
if line == '' and process.poll() is not None:
break
if process.returncode != 0:
raise Exception(
BColors.FAIL +
f'Non zero return code: {process.returncode}' +
BColors.ENDC)
[docs] def start_bids_app(self):
"""Function executed when the Run BIDS App button is clicked.
It implements all steps in the creation and execution of the BIDS App
with or without datalad.
"""
print_blue("[Run BIDS App]")
# Copy freesurfer license into dataset/code directory at the location
# the BIDS app expects to find it.
license_dst = os.path.join(self.bids_root, 'code', 'license.txt')
if not os.access(license_dst, os.F_OK):
dst = os.path.join(
self.bids_root, 'code', 'license.txt')
print('> Copy FreeSurfer license (BIDS App Manager) ')
print('... src : {}'.format(self.fs_license))
print('... dst : {}'.format(dst))
shutil.copy2(src=self.fs_license, dst=dst)
else:
print_warning(
'> FreeSurfer license copy skipped as it already exists(BIDS App Manager) ')
print("> Datalad available: {}".format(self.datalad_is_available))
# self.datalad_is_available = False
if self.datalad_is_available and self.data_provenance_tracking:
# Detect structure subject/session
session_structure = False
res = glob.glob(os.path.join(self.bids_root, 'sub-*/*/anat'))
# print(res)
if len(res) > 0:
session_structure = True
print(' INFO : Subject/Session structure detected!')
else:
print(' INFO : Subject structure detected!')
# Equivalent to:
# >> datalad create derivatives
# >> cd derivatives
# >> datalad containers-add connectomemapper-bidsapp-{} --url dhub://sebastientourbier/connectomemapper-bidsapp:{}
if not os.path.isdir(os.path.join(self.bids_root, '.datalad')):
cmd = ['datalad',
'create',
'--force',
'-D',
f'"Creation of datalad dataset to be processed by the connectome mapper bidsapp (tag:{self.bidsapp_tag})"',
'-c',
'text2git',
'-d',
f'{self.bids_root}']
cmd = " ".join(cmd)
try:
print_blue(f'... cmd: {cmd}')
self.run(cmd, env={}, cwd=os.path.abspath(self.bids_root))
print(" INFO: A datalad dataset has been created with success at the root directory!")
msg = 'Add all files to datalad. ' \
'Dataset ready to be linked with the BIDS App.'
except Exception:
msg = 'Save state after error at datalad dataset creation'
print_error(" DATALAD ERROR: Failed to create the datalad dataset")
else:
msg = 'Datalad dataset up-to-date and ready to be linked with the BIDS App.'
print(" INFO: A datalad dataset already exists!")
# log_filename = os.path.join(self.bids_root,'derivatives','cmp','main-datalad_log-cmpbidsapp.txt')
#
# if not os.path.exists(os.path.join(self.bids_root,'derivatives','cmp')):
# os.makedirs(os.path.join(self.bids_root,'derivatives','cmp'))
# create an empty log file to be tracked by datalad
# f = open(log_filename,"w+")
# f.close()
cmd = f'datalad save -d . -m "{msg}"'
try:
print_blue(f'... cmd: {cmd}')
self.run(cmd, env={}, cwd=os.path.abspath(self.bids_root))
except Exception:
print_error(" DATALAD ERROR: Failed to add changes to dataset")
datalad_container = os.path.join(self.bids_root,
'.datalad',
'environments',
'connectomemapper-bidsapp-{}'.format(
"-".join(self.bidsapp_tag.split("."))),
'image')
add_container = True
update_container = False
if os.path.isdir(datalad_container):
if self.datalad_update_environment:
print(
" INFO: Container already listed in the datalad dataset and will be updated!")
shutil.rmtree(datalad_container)
add_container = True
else:
add_container = False
print(
" INFO: Container already listed in the datalad dataset and will NOT be updated!")
else:
add_container = True
print(
" INFO: Add a new computing environment (container image) to the datalad dataset!")
if add_container:
# Define the docker run command executed by Datalad.
# It makes the assumption that the license.txt and the configuration files
# are located in the code/ directory.
docker_cmd = ['docker', 'run', '--rm', '-t',
'-v',
'"$(pwd)":/bids_dir',
'-v',
'"$(pwd)"/derivatives:/output_dir',
'-v',
'"$(pwd)"/code/license.txt:/bids_dir/code/license.txt',
'-v',
f'"$(pwd)"/code/{os.path.basename(self.anat_config)}:/code/ref_anatomical_config.json',
]
if self.run_dmri_pipeline:
docker_cmd.append('-v')
docker_cmd.append(f'"$(pwd)"/code/{os.path.basename(self.dmri_config)}:/code/ref_diffusion_config.json')
if self.run_fmri_pipeline:
docker_cmd.append('-v')
docker_cmd.append(f'"$(pwd)"/code/{os.path.basename(self.fmri_config)}:/code/ref_fMRI_config.json')
docker_cmd.append('-u')
docker_cmd.append('{}:{}'.format(os.geteuid(), os.getegid()))
docker_cmd.append(f'sebastientourbier/connectomemapper-bidsapp:{self.bidsapp_tag}')
docker_cmd.append('{cmd}')
# Define and run the command to add the container image to datalad
version_tag = "-".join(self.bidsapp_tag.split("."))
cmd = ['datalad',
'containers-add',
f'connectomemapper-bidsapp-{version_tag}',
'--url',
f'dhub://sebastientourbier/connectomemapper-bidsapp:{self.bidsapp_tag}',
'-d',
'.',
'--call-fmt']
cmd = " ".join(cmd)
docker_cmd = " ".join(docker_cmd)
cmd = f'{cmd} "{docker_cmd}"'
if self.datalad_update_environment:
cmd = f'{cmd} --update'
try:
print_blue(f'... cmd: {cmd}')
self.run(cmd, env={}, cwd=os.path.join(self.bids_root))
print(" INFO: Container image has been linked to dataset with success!")
except Exception:
print_error(" DATALAD ERROR: Failed to link the container image to the dataset")
# Create a list of files to be retrieved by datalad get
datalad_get_list = [self.anat_config]
if self.run_dmri_pipeline:
datalad_get_list.append(self.dmri_config)
if self.run_dmri_pipeline:
datalad_get_list.append(self.fmri_config)
if session_structure:
for label in self.list_of_subjects_to_be_processed:
datalad_get_list.append(
'sub-{}/ses-*/anat/sub-{}*_T1w.*'.format(label, label))
datalad_get_list.append(
'derivatives/freesurfer/sub-{}*/*'.format(label))
if self.run_dmri_pipeline:
datalad_get_list.append(
'sub-{}/ses-*/dwi/sub-{}*_dwi.*'.format(label, label))
if self.run_fmri_pipeline:
datalad_get_list.append(
'sub-{}/ses-*/func/sub-{}*_bold.*'.format(label, label))
else:
for label in self.list_of_subjects_to_be_processed:
datalad_get_list.append(
'sub-{}/anat/sub-{}*_T1w.*'.format(label, label))
datalad_get_list.append(
'derivatives/freesurfer/sub-{}/*'.format(label))
if self.run_dmri_pipeline:
datalad_get_list.append(
'sub-{}/dwi/sub-{}*_dwi.*'.format(label, label))
if self.run_fmri_pipeline:
datalad_get_list.append(
'sub-{}/func/sub-{}*_bold.*'.format(label, label))
cmd = 'datalad save -d . -m "Dataset state after adding the container image. '\
'Datasets ready to get files via datalad run."'
try:
print_blue(f'... cmd: {cmd}')
self.run(cmd, env={}, cwd=os.path.abspath(self.bids_root))
except Exception:
print_error(" DATALAD ERROR: Failed to add existing files to dataset")
cmd = 'datalad run -d . -m "Get files for sub-{}" bash -c "datalad get {}"'.format(
self.list_of_subjects_to_be_processed, " ".join(datalad_get_list))
try:
print_blue(f'... cmd: {cmd}')
self.run(cmd, env={}, cwd=os.path.abspath(self.bids_root))
except Exception:
print_error(" DATALAD ERROR: Failed to get files (cmd: datalad get {})".format(
" ".join(datalad_get_list)))
cmd = 'datalad save -d . -m "Dataset state after getting the files. Dataset ready for connectome mapping." '\
'--version-tag ready4analysis-{}'.format(time.strftime("%Y%m%d-%H%M%S"))
try:
print_blue(f'... cmd: {cmd}')
self.run(cmd, env={}, cwd=os.path.abspath(self.bids_root))
except Exception:
print_error(" DATALAD ERROR: Failed to commit changes to dataset")
cmd = 'datalad status -d .'
try:
print_blue(f'... cmd: {cmd}')
self.run(cmd, env={}, cwd=os.path.abspath(self.bids_root))
except Exception:
print_error(" DATALAD ERROR: Failed to run datalad rev-status")
# maxprocs = multiprocessing.cpu_count()
processes = []
self.docker_running = True
if self.datalad_is_available and self.data_provenance_tracking:
proc = self.start_bidsapp_participant_level_process_with_datalad(self.bidsapp_tag,
self.list_of_subjects_to_be_processed)
else:
proc = self.start_bidsapp_participant_level_process(self.bidsapp_tag,
self.list_of_subjects_to_be_processed)
processes.append(proc)
while len(processes) > 0:
self.manage_bidsapp_procs(processes)
if self.datalad_is_available and self.data_provenance_tracking:
# Clean remaining cache files generated in tmp/ of the docker image
# project.clean_cache(self.bids_root)
cmd = 'datalad save -d . -m "Dataset processed by the connectomemapper-bidsapp:{}" --version-tag processed-{}'.format(
self.bidsapp_tag, time.strftime("%Y%m%d-%H%M%S"))
try:
print_blue(f'... cmd: {cmd}')
self.run(cmd, env={}, cwd=os.path.abspath(self.bids_root))
except Exception:
print_error(" DATALAD ERROR: Failed to commit derivatives to datalad dataset")
cmd = 'datalad diff -t HEAD~1'
try:
print_blue(f'... cmd: {cmd}')
self.run(cmd, env={}, cwd=os.path.abspath(self.bids_root))
except Exception:
print_error(" DATALAD ERROR: Failed to run datalad diff -t HEAD~1")
print('Processing with BIDS App Finished')
self.docker_running = False
return True
# def stop_bids_app(self, ui_info):
# print("Stop BIDS App")
# #self.docker_process.kill()
# self.docker_running = False
# return True
[docs]class CMP_ConfiguratorWindow(HasTraits):
"""Class that defines the Configurator Window.
Attributes
----------
project_info : CMP_Project_Info
Instance of :class:`CMP_Project_Info` that represents the processing project
anat_pipeline : Instance(HasTraits)
Instance of anatomical MRI pipeline UI
dmri_pipeline : Instance(HasTraits)
Instance of diffusion MRI pipeline UI
fmri_pipeline : Instance(HasTraits)
Instance of functional MRI pipeline UI
anat_inputs_checked : traits.Bool
Boolean that indicates if anatomical pipeline inputs are available
(Default: False)
dmri_inputs_checked = : traits.Bool
Boolean that indicates if diffusion pipeline inputs are available
(Default: False)
fmri_inputs_checked : traits.Bool
Boolean that indicates if functional pipeline inputs are available
(Default: False)
anat_save_config : traits.ui.Action
TraitsUI Action to save the anatomical pipeline configuration
dmri_save_config : traits.ui.Action
TraitsUI Action to save the diffusion pipeline configuration
fmri_save_config : traits.ui.Action
TraitsUI Action to save the functional pipeline configuration
save_all_config : traits.ui.Button
Button to save all configuration files at once
traits_view : QtView
TraitsUI QtView that describes the content of the window
"""
project_info = Instance(CMP_Project_Info)
anat_pipeline = Instance(HasTraits)
dmri_pipeline = Instance(HasTraits)
fmri_pipeline = Instance(HasTraits)
anat_inputs_checked = Bool(False)
dmri_inputs_checked = Bool(False)
fmri_inputs_checked = Bool(False)
anat_save_config = Action(
name='Save anatomical pipeline configuration as...', action='save_anat_config_file')
dmri_save_config = Action(
name='Save diffusion pipeline configuration as...', action='save_dmri_config_file')
fmri_save_config = Action(
name='Save fMRI pipeline configuration as...', action='save_fmri_config_file')
# anat_load_config = Action(name='Load anatomical pipeline configuration...',action='anat_load_config_file')
# dmri_load_config = Action(name='Load diffusion pipeline configuration...',action='load_dmri_config_file')
# fmri_load_config = Action(name='Load fMRI pipeline configuration...',action='load_fmri_config_file')
save_all_config = Button('')
traits_view = QtView(
Group(
Group(
Item('anat_pipeline', style='custom', show_label=False),
label='Anatomical pipeline', dock='tab'),
Group(
Item('dmri_pipeline', style='custom', show_label=False,
enabled_when='dmri_inputs_checked', visible_when='dmri_inputs_checked'),
label='Diffusion pipeline', dock='tab'),
Group(
Item('fmri_pipeline', style='custom', show_label=False,
enabled_when='fmri_inputs_checked', visible_when='fmri_inputs_checked'),
label='fMRI pipeline', dock='tab'),
orientation='horizontal', layout='tabbed',
springy=True, enabled_when='anat_inputs_checked'),
spring,
HGroup(spring, Item('save_all_config',
style='custom',
width=315, height=35,
resizable=False,
label='',
show_label=False,
style_sheet=return_button_style_sheet(
ImageResource(
pkg_resources.resource_filename(
'resources',
os.path.join('buttons', 'configurator-saveall.png'))).absolute_path),
enabled_when='anat_inputs_checked==True'),
spring,
show_labels=False, label=""),
title='Connectome Mapper 3 Configurator',
menubar=MenuBar(
Menu(
ActionGroup(
anat_save_config,
dmri_save_config,
fmri_save_config),
ActionGroup(
Action(name='Quit', action='_on_close')),
name='File')),
handler=project.CMP_ConfigQualityWindowHandler(),
style_sheet=style_sheet,
buttons=[],
width=0.5, height=0.8, resizable=True, # scrollable=True,
icon=get_icon('configurator.png')
)
def __init__(self, project_info=None, anat_pipeline=None, dmri_pipeline=None, fmri_pipeline=None,
anat_inputs_checked=False, dmri_inputs_checked=False, fmri_inputs_checked=False):
"""Constructor of an :class:``CMP_ConfiguratorWindow`` instance.
Parameters
----------
project_info : cmp.project.CMP_Project_Info
:class:`CMP_Project_Info` object (Default: None)
anat_pipeline <cmp.bidsappmanager.pipelines.anatomical.AnatomicalPipelineUI>
Instance of :class:`cmp.bidsappmanager.pipelines.anatomical.AnatomicalPipelineUI`
(Default: None)
dmri_pipeline <cmp.bidsappmanager.pipelines.diffusion.DiffusionPipelineUI>
Instance of :class:`cmp.bidsappmanager.pipelines.diffusion.DiffusionPipelineUI`
(Default: None)
fmri_pipeline <cmp.bidsappmanager.pipelines.functional.fMRIPipelineUI>
Instance of :class:`cmp.bidsappmanager.pipelines.functional.fMRIPipelineUI`
(Default: None)
anat_inputs_checked : traits.Bool
Boolean that indicates if anatomical pipeline inputs are available
(Default: False)
dmri_inputs_checked = : traits.Bool
Boolean that indicates if diffusion pipeline inputs are available
(Default: False)
fmri_inputs_checked : traits.Bool
Boolean that indicates if functional pipeline inputs are available
(Default: False)
"""
print('> Initialize window...')
self.project_info = project_info
self.anat_pipeline = anat_pipeline
self.dmri_pipeline = dmri_pipeline
self.fmri_pipeline = fmri_pipeline
if self.anat_pipeline is not None:
self.anat_pipeline.view_mode = 'config_view'
if self.dmri_pipeline is not None:
self.dmri_pipeline.view_mode = 'config_view'
if self.fmri_pipeline is not None:
self.fmri_pipeline.view_mode = 'config_view'
self.anat_inputs_checked = anat_inputs_checked
self.dmri_inputs_checked = dmri_inputs_checked
self.fmri_inputs_checked = fmri_inputs_checked
[docs] def update_diffusion_imaging_model(self, new):
self.dmri_pipeline.diffusion_imaging_model = new
def _save_all_config_fired(self):
print_blue('[Save all pipeline configuration files]')
if self.anat_inputs_checked:
anat_config_file = os.path.join(
self.project_info.base_directory, 'code', 'ref_anatomical_config.json')
project.anat_save_config(self.anat_pipeline, anat_config_file)
print(' * Anatomical config saved as {}'.format(anat_config_file))
if self.dmri_inputs_checked:
dmri_config_file = os.path.join(
self.project_info.base_directory, 'code', 'ref_diffusion_config.json')
project.dmri_save_config(self.dmri_pipeline, dmri_config_file)
print(' * Diffusion config saved as {}'.format(dmri_config_file))
if self.fmri_inputs_checked:
fmri_config_file = os.path.join(
self.project_info.base_directory, 'code', 'ref_fMRI_config.json')
project.fmri_save_config(self.fmri_pipeline, fmri_config_file)
print(' * fMRI config saved as {}'.format(fmri_config_file))
# Window class of the ConnectomeMapper_Pipeline Quality Inspector
#
[docs]class CMP_InspectorWindow(HasTraits):
"""Class that defines the Configurator Window.
Attributes
----------
project_info : CMP_Project_Info
Instance of :class:`CMP_Project_Info` that represents the processing project
anat_pipeline : Instance(HasTraits)
Instance of anatomical MRI pipeline
dmri_pipeline : Instance(HasTraits)
Instance of diffusion MRI pipeline
fmri_pipeline : Instance(HasTraits)
Instance of functional MRI pipeline
anat_inputs_checked : traits.Bool
Indicates if inputs of anatomical pipeline are available
(Default: False)
dmri_inputs_checked : traits.Bool
Indicates if inputs of diffusion pipeline are available
(Default: False)
fmri_inputs_checked : traits.Bool
Indicates if inputs of functional pipeline are available
(Default: False)
output_anat_available : traits.Bool
Indicates if outputs of anatomical pipeline are available
(Default: False)
output_dmri_available : traits.Bool
Indicates if outputs of diffusion pipeline are available
(Default: False)
output_fmri_available : traits.Bool
Indicates if outputs of functional pipeline are available
(Default: False)
traits_view : QtView
TraitsUI QtView that describes the content of the window
"""
project_info = Instance(CMP_Project_Info)
anat_pipeline = Instance(HasTraits)
dmri_pipeline = Instance(HasTraits)
fmri_pipeline = Instance(HasTraits)
anat_inputs_checked = Bool(False)
dmri_inputs_checked = Bool(False)
fmri_inputs_checked = Bool(False)
output_anat_available = Bool(False)
output_dmri_available = Bool(False)
output_fmri_available = Bool(False)
traits_view = QtView(Group(
# Group(
# # Include('dataset_view'),label='Data manager',springy=True
# Item('project_info',style='custom',show_label=False),label='Data manager',springy=True, dock='tab'
# ),
Group(
Item('anat_pipeline', style='custom', show_label=False), visible_when='output_anat_available',
label='Anatomical pipeline', dock='tab'
),
Group(
Item('dmri_pipeline', style='custom', show_label=False,
visible_when='output_dmri_available'),
label='Diffusion pipeline', dock='tab'
),
Group(
Item('fmri_pipeline', style='custom', show_label=False,
visible_when='output_fmri_available'),
label='fMRI pipeline', dock='tab'
),
orientation='horizontal', layout='tabbed', springy=True, enabled_when='output_anat_available'),
title='Connectome Mapper 3 Inspector',
menubar=MenuBar(
Menu(
ActionGroup(
Action(name='Quit', action='_on_close'),
),
name='File'),
),
handler=project.CMP_ConfigQualityWindowHandler(),
style_sheet=style_sheet,
width=0.5, height=0.8, resizable=True, # scrollable=True,
icon=get_icon('qualitycontrol.png')
)
error_msg = Str('')
error_view = View(
Group(
Item('error_msg', style='readonly', show_label=False),
),
title='Error',
kind='modal',
# style_sheet=style_sheet,
buttons=['OK'])
def __init__(self, project_info=None, anat_inputs_checked=False, dmri_inputs_checked=False,
fmri_inputs_checked=False):
"""Constructor of an :class:``CMP_ConfiguratorWindow`` instance.
Parameters
----------
project_info : cmp.project.CMP_Project_Info
:class:`CMP_Project_Info` object (Default: None)
anat_inputs_checked : traits.Bool
Boolean that indicates if anatomical pipeline inputs are available
(Default: False)
dmri_inputs_checked = : traits.Bool
Boolean that indicates if diffusion pipeline inputs are available
(Default: False)
fmri_inputs_checked : traits.Bool
Boolean that indicates if functional pipeline inputs are available
(Default: False)
"""
print('> Initialize window...')
self.project_info = project_info
self.anat_inputs_checked = anat_inputs_checked
self.dmri_inputs_checked = dmri_inputs_checked
self.fmri_inputs_checked = fmri_inputs_checked
aborded = self.select_subject()
if aborded:
raise Exception(
BColors.FAIL +
' .. ABORDED: The quality control window will not be displayed.' +
'Selection of subject/session was cancelled at initialization.' +
BColors.ENDC)
[docs] def select_subject(self):
"""Function to select the subject and session for which to inspect outputs."""
print('> Selection of subject (and session) for which to inspect outputs')
valid_selected_subject = False
select = True
aborded = False
while not valid_selected_subject and not aborded:
# Select subject from BIDS dataset
np_res = self.project_info.configure_traits(view='subject_view')
if not np_res:
aborded = True
break
print(" .. INFO: Selected subject: {}".format(self.project_info.subject))
# Select session if any
bids_layout = BIDSLayout(self.project_info.base_directory)
subject = self.project_info.subject.split('-')[1]
sessions = bids_layout.get(
target='session', return_type='id', subject=subject)
if len(sessions) > 0:
print(" .. INFO: Input dataset has sessions")
print(sessions)
self.project_info.subject_sessions = []
for ses in sessions:
self.project_info.subject_sessions.append(
'ses-' + str(ses))
np_res = self.project_info.configure_traits(
view='subject_session_view')
if not np_res:
aborded = True
break
self.project_info.anat_config_file = os.path.join(self.project_info.base_directory, 'derivatives',
'cmp', '{}'.format(
self.project_info.subject),
'{}'.format(
self.project_info.subject_session),
'{}_{}_anatomical_config.json'.format(
self.project_info.subject,
self.project_info.subject_session))
if os.access(self.project_info.anat_config_file, os.F_OK):
print("> Initialize anatomical pipeline")
self.anat_pipeline = project.init_anat_project(
self.project_info, False)
else:
self.anat_pipeline = None
if self.dmri_inputs_checked:
self.project_info.dmri_config_file = os.path.join(self.project_info.base_directory, 'derivatives',
'cmp', '{}'.format(
self.project_info.subject),
'{}'.format(
self.project_info.subject_session),
'{}_{}_diffusion_config.json'.format(
self.project_info.subject,
self.project_info.subject_session))
if os.access(self.project_info.dmri_config_file, os.F_OK):
print("> Initialize diffusion pipeline")
dmri_valid_inputs, self.dmri_pipeline = project.init_dmri_project(self.project_info,
bids_layout, False)
else:
self.dmri_pipeline = None
# self.dmri_pipeline.subject = self.project_info.subject
# self.dmri_pipeline.global_conf.subject = self.project_info.subject
if self.fmri_inputs_checked:
self.project_info.fmri_config_file = os.path.join(self.project_info.base_directory, 'derivatives',
'cmp', '{}'.format(
self.project_info.subject),
'{}'.format(
self.project_info.subject_session),
'{}_{}_fMRI_config.json'.format(
self.project_info.subject,
self.project_info.subject_session))
if os.access(self.project_info.fmri_config_file, os.F_OK):
print("> Initialize fMRI pipeline")
fmri_valid_inputs, self.fmri_pipeline = project.init_fmri_project(self.project_info,
bids_layout, False)
else:
self.fmri_pipeline = None
# self.fmri_pipeline.subject = self.project_info.subject
# self.fmri_pipeline.global_conf.subject = self.project_info.subject
# self.anat_pipeline.global_conf.subject_session = self.project_info.subject_session
# if self.dmri_pipeline is not None:
# self.dmri_pipeline.global_conf.subject_session = self.project_info.subject_session
#
# if self.fmri_pipeline is not None:
# self.fmri_pipeline.global_conf.subject_session = self.project_info.subject_session
print(" .. INFO: Selected session %s" %
self.project_info.subject_session)
if self.anat_pipeline is not None:
self.anat_pipeline.stages['Segmentation'].config.freesurfer_subject_id = os.path.join(
self.project_info.base_directory, 'derivatives', 'freesurfer',
'{}_{}'.format(self.project_info.subject, self.project_info.subject_session))
else:
print(" .. INFO: No session detected")
self.project_info.anat_config_file = os.path.join(self.project_info.base_directory, 'derivatives',
'cmp', '{}'.format(
self.project_info.subject),
'{}_anatomical_config.json'.format(
self.project_info.subject))
if os.access(self.project_info.anat_config_file, os.F_OK):
self.anat_pipeline = project.init_anat_project(
self.project_info, False)
else:
self.anat_pipeline = None
if self.dmri_inputs_checked:
self.project_info.dmri_config_file = os.path.join(self.project_info.base_directory, 'derivatives',
'cmp', '{}'.format(
self.project_info.subject),
'{}_diffusion_config.json'.format(
self.project_info.subject))
if os.access(self.project_info.dmri_config_file, os.F_OK):
dmri_valid_inputs, self.dmri_pipeline = project.init_dmri_project(self.project_info,
bids_layout, False)
else:
self.dmri_pipeline = None
# self.dmri_pipeline.subject = self.project_info.subject
# self.dmri_pipeline.global_conf.subject = self.project_info.subject
if self.fmri_inputs_checked:
self.project_info.fmri_config_file = os.path.join(self.project_info.base_directory, 'derivatives',
'cmp', '{}'.format(
self.project_info.subject),
'{}_fMRI_config.json'.format(
self.project_info.subject))
if os.access(self.project_info.fmri_config_file, os.F_OK):
fmri_valid_inputs, self.fmri_pipeline = project.init_fmri_project(self.project_info,
bids_layout, False)
else:
self.fmri_pipeline = None
# self.fmri_pipeline.subject = self.project_info.subject
# self.fmri_pipeline.global_conf.subject = self.project_info.subject
# self.anat_pipeline.global_conf.subject_session = ''
if self.anat_pipeline is not None:
self.anat_pipeline.stages['Segmentation'].config.freesurfer_subjects_dir = os.path.join(
self.project_info.base_directory, 'derivatives', 'freesurfer',
'{}'.format(self.project_info.subject))
if self.anat_pipeline is not None:
print("> Anatomical pipeline output inspection")
self.anat_pipeline.view_mode = 'inspect_outputs_view'
for stage in list(self.anat_pipeline.stages.values()):
print(" ... Inspect stage {}".format(stage))
stage.define_inspect_outputs()
# print('Stage {}: {}'.format(stage.stage_dir, stage.inspect_outputs))
if (len(stage.inspect_outputs) > 0) and (stage.inspect_outputs[0] != 'Outputs not available'):
self.output_anat_available = True
if self.dmri_pipeline is not None:
print("> Diffusion pipeline output inspection")
self.dmri_pipeline.view_mode = 'inspect_outputs_view'
for stage in list(self.dmri_pipeline.stages.values()):
print(" ... Inspect stage {}".format(stage))
stage.define_inspect_outputs()
# print('Stage {}: {}'.format(stage.stage_dir, stage.inspect_outputs))
if (len(stage.inspect_outputs) > 0) and (stage.inspect_outputs[0] != 'Outputs not available'):
self.output_dmri_available = True
if self.fmri_pipeline is not None:
print("> fMRI pipeline output inspection")
self.fmri_pipeline.view_mode = 'inspect_outputs_view'
for stage in list(self.fmri_pipeline.stages.values()):
print(" ... Inspect stage {}".format(stage))
stage.define_inspect_outputs()
# print('Stage {}: {}'.format(stage.stage_dir, stage.inspect_outputs))
if (len(stage.inspect_outputs) > 0) and (stage.inspect_outputs[0] != 'Outputs not available'):
self.output_fmri_available = True
print_blue(" .. Anatomical output(s) available : %s" %
self.output_anat_available)
print_blue(" .. Diffusion output(s) available : %s" %
self.output_dmri_available)
print_blue(" .. fMRI output(s) available : %s" % self.output_fmri_available)
if self.output_anat_available or self.output_dmri_available or self.output_fmri_available:
valid_selected_subject = True
else:
self.error_msg = " .. ERROR: No output available! " +\
"Please select another subject (and session if any)!"
print_error(self.error_msg)
select = error(message=self.error_msg,
title='Error', buttons=['OK', 'Cancel'])
aborded = not select
return aborded
[docs] def update_diffusion_imaging_model(self, new):
"""Function called when ``diffusion_imaging_model`` is updated."""
self.dmri_pipeline.diffusion_imaging_model = new
[docs]class CMP_MainWindow(HasTraits):
"""Class that defines the Main window of the Connectome Mapper 3 GUI.
Attributes
----------
project_info : CMP_Project_InfoUI
Instance of :class:`CMP_Project_InfoUI` that represents the processing project
anat_pipeline : Instance(HasTraits)
Instance of anatomical MRI pipeline UI
dmri_pipeline : Instance(HasTraits)
Instance of diffusion MRI pipeline UI
fmri_pipeline : Instance(HasTraits)
Instance of functional MRI pipeline UI
bidsapp_ui : CMP_Project_Info
Instance of :class:`CMP_BIDSAppWindow`
load_dataset : traits.ui.Action
TraitsUI Action to load a BIDS dataset
bidsapp : traits.ui.Button
Button that displays the BIDS App Interface window
configurator : traits.ui.Button
Button thats displays the pipeline Configurator window
quality_control : traits.ui.Button
Button that displays the pipeline Quality Control / Inspector window
manager_group : traits.ui.View
TraitsUI View that describes the content of the main window
traits_view : QtView
TraitsUI QtView that includes ``manager_group`` and parameterize
the window with menu
"""
project_info = Instance(CMP_Project_Info)
anat_pipeline = Instance(HasTraits)
dmri_pipeline = Instance(HasTraits)
fmri_pipeline = Instance(HasTraits)
# configurator_ui = Instance(CMP_PipelineConfigurationWindow)
bidsapp_ui = Instance(CMP_BIDSAppWindow)
# quality_control_ui = Instance(CMP_QualityControlWindow)
load_dataset = Action(name='Load BIDS Dataset...', action='load_dataset')
project_info.style_sheet = style_sheet
configurator = Button('')
bidsapp = Button('')
quality_control = Button('')
view_mode = 1
manager_group = VGroup(
spring,
HGroup(
spring,
HGroup(
Item('configurator', style='custom', width=200, height=200, resizable=False, label='', show_label=False,
style_sheet=return_button_style_sheet(
ImageResource(
pkg_resources.resource_filename('cmp',
os.path.join('bidsappmanager/images',
'configurator_200x200.png'))).absolute_path)
),
show_labels=False, label=""),
spring,
HGroup(Item('bidsapp', style='custom', width=200, height=200, resizable=False,
style_sheet=return_button_style_sheet(
ImageResource(
pkg_resources.resource_filename('cmp',
os.path.join('bidsappmanager/images',
'bidsapp_200x200.png'))).absolute_path)
),
show_labels=False, label=""),
spring,
HGroup(Item('quality_control', style='custom', width=200, height=200, resizable=False,
style_sheet=return_button_style_sheet(
ImageResource(
pkg_resources.resource_filename('cmp',
os.path.join('bidsappmanager/images',
'qualitycontrol_200x200.png'))).absolute_path)
),
show_labels=False, label=""),
spring,
springy=True, visible_when='handler.project_loaded==True'),
spring,
springy=True)
traits_view = QtView(
HGroup(
Include('manager_group'),
),
title='Connectome Mapper {} - BIDS App Manager'.format(__version__),
menubar=MenuBar(
Menu(
ActionGroup(
load_dataset,
),
ActionGroup(
Action(name='Quit', action='_on_close'),
),
name='File'),
),
handler=project.CMP_MainWindowHandler(),
style_sheet=style_sheet,
width=0.5, height=0.8, resizable=True, # , scrollable=True , resizable=True
icon=get_icon('cmp.png')
)
def _bidsapp_fired(self):
""" Callback of the "bidsapp" button. This displays the BIDS App Interface window."""
print_blue("[Open BIDS App Window]")
bids_layout = BIDSLayout(self.project_info.base_directory)
subjects = bids_layout.get_subjects()
anat_config = os.path.join(
self.project_info.base_directory, 'code/', 'ref_anatomical_config.json')
dmri_config = os.path.join(
self.project_info.base_directory, 'code/', 'ref_diffusion_config.json')
fmri_config = os.path.join(
self.project_info.base_directory, 'code/', 'ref_fMRI_config.json')
self.bidsapp_ui = CMP_BIDSAppWindow(project_info=self.project_info,
bids_root=self.project_info.base_directory,
subjects=subjects,
list_of_subjects_to_be_processed=subjects,
# anat_config=self.project_info.anat_config_file,
# dmri_config=self.project_info.dmri_config_file,
# fmri_config=self.project_info.fmri_config_file
anat_config=anat_config,
dmri_config=dmri_config,
fmri_config=fmri_config
)
self.bidsapp_ui.configure_traits()
def _configurator_fired(self):
"""Callback of the "configurator" button. This displays the Configurator Window."""
print_blue("[Open Pipeline Configurator Window]")
if self.project_info.t1_available:
if os.path.isfile(self.project_info.anat_config_file):
print(" .. Anatomical config file : %s" %
self.project_info.anat_config_file)
if self.project_info.dmri_available:
if os.path.isfile(self.project_info.dmri_config_file):
print(" .. Diffusion config file : %s" %
self.project_info.dmri_config_file)
if self.project_info.fmri_available:
if os.path.isfile(self.project_info.fmri_config_file):
print(" .. fMRI config file : %s" %
self.project_info.fmri_config_file)
self.configurator_ui = CMP_ConfiguratorWindow(project_info=self.project_info,
anat_pipeline=self.anat_pipeline,
dmri_pipeline=self.dmri_pipeline,
fmri_pipeline=self.fmri_pipeline,
anat_inputs_checked=self.project_info.t1_available,
dmri_inputs_checked=self.project_info.dmri_available,
fmri_inputs_checked=self.project_info.fmri_available
)
self.configurator_ui.configure_traits()
def _quality_control_fired(self):
"""Callback of the "Inspector" button. This displays the Quality Control (Inspector) Window."""
print_blue("[Open Quality Inspector Window]")
if self.project_info.t1_available:
if os.path.isfile(self.project_info.anat_config_file):
print(" .. Anatomical config file : %s" %
self.project_info.anat_config_file)
if self.project_info.dmri_available:
if os.path.isfile(self.project_info.dmri_config_file):
print(" .. Diffusion config file : %s" %
self.project_info.dmri_config_file)
if self.project_info.fmri_available:
if os.path.isfile(self.project_info.fmri_config_file):
print(" .. fMRI config file : %s" %
self.project_info.fmri_config_file)
try:
self.quality_control_ui = CMP_InspectorWindow(project_info=self.project_info,
anat_inputs_checked=self.project_info.t1_available,
dmri_inputs_checked=self.project_info.dmri_available,
fmri_inputs_checked=self.project_info.fmri_available
)
self.quality_control_ui.configure_traits()
except Exception as e:
print(e)