Level1Design creating interaction EV

nipype
#1

Hi everyone,

I’ve been trying to do a PPI using nipype, and I’ve gotten to the point where all fsf files and ev files are prepped (i.e exist in the working directory). However, when I look at these files they seem a bit wrong based on what I expect doing a PPI analysis in fsl. Normally, I would expect:

  1. an EV_file for each condition
  2. EV_file with all conditions
  3. A 1-columnEV_file seed region,
  4. A ‘PPI’ interaction configuration in the fsf file

I am failing at #4. Is there a way to configure this in level1design using nipype? I tried what a previous post said (FSL PPI analysis with nipype), but the interaction is not shown in the fsf file.

Any way more generally to indicate an interaction EV in level1design?

thanks!

#2

Hi,
the PPI patch is not in master. I pushed a newer version of nipype with the PPI patch to
https://github.com/cni-md/nipype.git branch PPI.

For the PPI model I use:

################################################                                                                                                                                              
# PPI Model                                                                                                                                                                                   
################################################                                                                                                                                              
                                                                                                                                                                                              
class GenModelInputSpec(BaseInterfaceInputSpec):                                                                                                                                              
    bids_event_files = File(exists=True,                                                                                                                                                      
        mandatory=True,                                                                                                                                                                       
        desc='TSV event file containing common BIDS fields: `onset`,'                                                                                                                         
        '`duration`, and categorization and amplitude columns')                                                                                                                               
                                                                                                                                                                                              
    regressors     = traits.List(desc='ROI time course', mandatory=False)                                                                                                                     
    regressor_names = traits.List(desc='regressor names', mandatory=False)                                                                                                                    
                                                                                                                                                                                              
class GenModelOutputSpec(TraitedSpec):                                                                                                                                                        
    model = traits.Any(desc="Model")                                                                                                                                                          
                                                                                                                                                                                              
class GenModel(BaseInterface):                                                                                                                                                                
    input_spec  = GenModelInputSpec                                                                                                                                                           
    output_spec = GenModelOutputSpec                                                                                                                                                          
                                                                                                                                                                                              
    def _run_interface(self, runtime):                                                                                                                                                        
        from nipype.interfaces.base import Bunch                                                                                                                                              
        from nipype.algorithms.modelgen import  bids_gen_info                                                                                                                                 
        self.model = bids_gen_info([self.inputs.bids_event_files], 'trial_type')                                                                                                              
                                                                                                                                                                                              
        if self.inputs.regressors:                                                                                                                                                            
            self.model[0].update(regressors=[list(self.inputs.regressors)])                                                                                                                   
        if self.inputs.regressor_names:                                                                                                                                                       
            self.model[0].update(regressor_names=list(self.inputs.regressor_names)) # Must be list otherwise  Error Traits.list has no trait...                           
        return runtime                                                                                                                                                                        
                                                                                                                                                                                              
    def _list_outputs(self):                                                                                                                                                                  
        outputs = self._outputs().get()                                                                                                                                                       
        outputs['model'] = self.model                                                                                                                                                         
        return outputs                                                                                                                                                                        
                                                                                                                                                                                              
                                                                                                                                                                                              
rh_ppi_model = pe.Node(interface=GenModel(), name='ppi_model_rh')                                                                                                                             
rh_ppi_model.inputs.bids_event_files = os.path.abspath('./FM_r_v_train.tsv')                                                                                                                  
rh_ppi_model.inputs.regressor_names=['rh_seed']                                                                                                                                               
# seed time course form nilearn NiftiSpheresMasker                                                                                                                                                                                              
main.connect(episphere, ('ts', get_listElemt, 0), rh_ppi_model, 'regressors')                                                                                                                 
                                                                                                                                                                                              
rh_ppi_modelspec = pe.Node(interface=model.SpecifyModel(), name='RH_PPI_Modelspec')                                                                                                           
rh_ppi_modelspec.inputs.input_units = 'secs'                                                                                                                                                  
rh_ppi_modelspec.inputs.time_repetition = TR                                                                                                                                                  
rh_ppi_modelspec.inputs.high_pass_filter_cutoff = highpass                                                                                                                                    
# 0 = RH, 1 = LH                                                                                                                                                                              
main.connect(datasource, 'epi', rh_ppi_modelspec, 'functional_runs')                                                                                                                          
main.connect(datasource, 'outl', rh_ppi_modelspec, 'outlier_files')                                                                                                                           
main.connect(rh_ppi_model, 'model', rh_ppi_modelspec, 'subject_info')

rh_modelfit_ppi = create_modelfit_workflow(f_contrasts=False, name='rh_modelfit_ppi')                                                                                                         
rh_modelfit_ppi.inputs.inputspec.interscan_interval = TR                                                                                                                                      
rh_modelfit_ppi.inputs.inputspec.model_serial_correlations = True                                                                                                                             
                                                                                                                                                                                              
ppi1 = ['p1', ['rh_seed', 'bil'],['mean','centre']]                   # interaction between seed and bil condition                                                                                                                        
rh_modelfit_ppi.inputs.inputspec.ppi = [ppi1]                                                                                                                                                 
rh_modelfit_ppi.inputs.inputspec.bases = {'dgamma': {'derivs': False}}                                                                                                                        
contp2 = ['PPI > bil', 'T', [ 'bil', 'li','limr','re','remr',                                                                                                                                 
         'rh_seed', 'p1' ], [0,0,0,0,0,0,1]]                                                                                                                                                  
                                                                                                                                                                                              
rh_modelfit_ppi.inputs.inputspec.contrasts = [contp2]                                                                                                                                         
main.connect(rh_ppi_modelspec, 'session_info', rh_modelfit_ppi, 'inputspec.session_info')                                                                                                     
main.connect(datasource,  'epi', rh_modelfit_ppi, 'inputspec.functional_data') 

The last column of my .fsf contains:

# EV title
set fmri(evtitle10) "p1"

# Basic waveform shape (EV 10)
# 0 : Square
# 1 : Sinusoid
# 2 : Custom (1 entry per volume)
# 3 : Custom (3 column format)
# 4 : Interaction
# 10 : Empty (all zeros)
set fmri(shape10) 4

Joerg

1 Like
#3

Hi Joerg!

Thank you for the info. I used git checkout to fork into the ppi branch and could see the code you added to the level1design class. However once I actually tried add the ppi trait to the level1design I got an error saying that this trait did not exist. Is there anything else that i’m missing in order for this to work? Like maybe there are specific things that I need to import…?

Thank you!

modelspec = Node(SpecifyModel(high_pass_filter_cutoff= 100,
                          input_units = 'secs', time_repetition = TR), name="modelspec")

ppi_interaction1 = ['ppi_pleasant', ['seed', 'psy'], ['mean', 'centre']]


level1design = Node(Level1Design(interscan_interval = TR, bases = {'dgamma': {'derivs': False}},
                                 model_serial_correlations = False, ppi = ppi_interaction1),name = "level1design")

TraitError                                Traceback (most recent call last)
<ipython-input-21-490d09c3bb8c> in <module>()
      8 
      9 level1design = Node(Level1Design(interscan_interval = TR, bases = {'dgamma': {'derivs': False}},
---> 10                                  model_serial_correlations = False, ppi = ppi_interaction1),name = "level1design")
     11 
     12 modelgen = Node(FEATModel(),name='modelgen')

~/anaconda3/lib/python3.6/site-packages/nipype/interfaces/base/core.py in __init__(self, from_file, resource_monitor, ignore_exception, **inputs)
    177                 'No input_spec in class: %s' % self.__class__.__name__)
    178 
--> 179         self.inputs = self.input_spec(**inputs)
    180         self.ignore_exception = ignore_exception
    181 

~/anaconda3/lib/python3.6/site-packages/nipype/interfaces/base/specs.py in __init__(self, **kwargs)
     65         # therefore these args were being ignored.
     66         # super(TraitedSpec, self).__init__(*args, **kwargs)
---> 67         super(BaseTraitedSpec, self).__init__(**kwargs)
     68         traits.push_exception_handler(reraise_exceptions=True)
     69         undefined_traits = {}

TraitError: Cannot set the undefined 'ppi' attribute of a 'Level1DesignInputSpec' object.
#4

How did you install the PPI branch? Maybe your pythonpath is prefering the master nipype instead of the ppi version.
I suggest a virtualenv setup for each study / test to avoid any crosstalk between different lib versions.

Joerg

#5

Hi Jeorg,

I used git commands to switch to the ppi branch. I was worried that masters was being applied when I used Jupyter Notebook, but I checked in there too and the branch is definitely “ppi”. I’ll try doing a Jupyter Notebook in a virtual environment. However, do you think there may be anything in your local computer that makes the code work? This is a really good addition to nipype and I hope more people can use it.

Thanks again,
MZMG

#6

Hi,
I am not familiar with Jupyter but I miss a python setup.py install … or pip install -e … to install nipype.

If you run

 Level1Design??

Do you get

 <...>
          contrasts : list of lists
               Information on contrasts to be evaluated
        """
        conds = {}
        evname = []
        if basis_key == "dgamma":
            basis_key = "hrf"
        elif basis_key == "gamma":
            try:
                _ = ev_parameters['gammasigma']
            except KeyError:
                ev_parameters['gammasigma'] = 3
            try:
                _ = ev_parameters['gammadelay']
            except KeyError:
                ev_parameters['gammadelay'] = 6
        ev_template = load_template('feat_ev_' + basis_key + '.tcl')
        ev_none = load_template('feat_ev_none.tcl')
        ev_ortho = load_template('feat_ev_ortho.tcl')
        ev_ppi_header = load_template('feat_ev_ppi_header.tcl')
        ev_ppi = load_template('feat_ev_ppi.tcl')
        ev_txt = ''

and at the bottom

Init docstring: Subclasses must implement __init__
File:           ~/github/nipype/nipype/interfaces/fsl/model.py

the location of the PPI branch?

#7

Hi Jeorg,

Thanks again for the help. I actually figured it out last night! Here are the steps I took:

#terminal
git clone nipype repo
git checkout nipype/ppi

conda create -n ppi_environment python=3.6
source activate ppo_environment
pip install nipype  (THIS WAS WRONG)
ipython kernel install --name ppi_environment 

Then i used jupyter notebook to load my code and switched to the ppi_environment kernel. However, the conda environment pulls the master from the internet and not what you have from git. So my nipype in that environment was not hitting your code even though it was on the ppi branch elsewhere.

So new folks should do:

conda create -n ppi_environment python=3.6
source activate ppo_environment
git clone nipype repo
git checkout nipype/ppi
ipython kernel install --name ppi_environment 

This makes sure that your ppi branch is what is being called in the conda environment/ jupyter kernel. Alternatively you can literally just copy and paste the ppi nipype folder into the environment’s packages folder directory. Hope this helps others.

Thanks again!
MZMG