3
dW/                 @   sd  d Z ddlmZmZmZmZmZmZmZm	Z	m
Z
mZmZ ddlZG dd deZG dd deZG d	d
 d
eZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd  d eZG d!d" d"eZG d#d$ d$eZG d%d& d&eZG d'd( d(eZdS ))at	  The fix module provides classes for interfacing with the `FSL FIX
<http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FIX/index.html>` command line tools.

This was written to work with FSL version v5.0

The following example assumes that melodic has already been run, so
the datagrabber is configured to start from there (a list of melodic
output directories). If no hand_labels_noise.txt exists already, this
will fail and comment on that.

EXAMPLE:
subject_list = ['1', '2', '3']

fix_pipeline = pe.Workflow(name='fix_pipeline')
fix_pipeline.base_dir = os.path.abspath('./')

info = dict(mel_ica=[['subject_id']])

datasource = pe.Node(interface=nio.DataGrabber(infields=['subject_id'], outfields=['mel_ica']), name='datasource')
datasource.inputs.base_directory = os.path.abspath('<path_to_base_directory>')
datasource.inputs.template = '%s/<path_to_melodic_ica>'
datasource.inputs.template_args = info
datasource.inputs.subject_id =  subject_list
datasource.inputs.sort_filelist = True
datasource.iterables = ('subject_id', subject_list)

# create training set by looking into which mel_icas have hand_labels_noise.txt files in them
create_training_set = pe.JoinNode(interface=fix.TrainingSetCreator(), joinfield=['mel_icas_in'], joinsource='datasource', name='trainingset_creator')

# train the classifier
train_node = pe.Node(interface=fix.Training(trained_wts_filestem='foo'), name='train_node')

# test accuracy. Probably not necessary, and also failing on my setup because of fix itself (no error msg)
accuracy_tester = pe.Node(interface=fix.AccuracyTester(output_directory='more_foo'), name='accuracy_tester')

# classify components
classify_node = pe.Node(interface=fix.Classifier(), name='classify')

# apply cleanup
cleaner_node = pe.Node(interface=fix.Cleaner(), name='cleaner')

fix_pipeline.connect(datasource, 'mel_ica', create_training_set, 'mel_icas_in')
fix_pipeline.connect(create_training_set, 'mel_icas_out', train_node, 'mel_icas')
fix_pipeline.connect(train_node, 'trained_wts_file', accuracy_tester, 'trained_wts_file')
fix_pipeline.connect(datasource, 'mel_ica', accuracy_tester, 'mel_icas')
fix_pipeline.connect(train_node, 'trained_wts_file', classify_node, 'trained_wts_file')
fix_pipeline.connect(datasource, 'mel_ica', classify_node, 'mel_ica')
fix_pipeline.connect(classify_node, 'artifacts_list_file', cleaner_node, 'artifacts_list_file')

fix_pipeline.write_graph()
outgraph = fix_pipeline.run()

   )TraitedSpecCommandLineInputSpecCommandLineInputMultiPathOutputMultiPathBaseInterfaceBaseInterfaceInputSpectraits	DirectoryFile	isdefined    Nc               @   s$   e Zd Zeedddddd	dZdS )
TrainingSetCreatorInputSpecT)existsFzMelodic output directoriesz%s   )copyfiledescargstrpositionN)__name__
__module____qualname__r   r
   mel_icas_in r   r   ;/tmp/pip-build-7vycvbft/nipype/nipype/interfaces/fsl/fix.pyr   J   s   r   c               @   s$   e Zd Zeedddddd	dZdS )
TrainingSetCreatorOutputSpecT)r   FzHand labels for noise vs signalz%sr   )r   r   r   r   Nr   )r   r   r   r   r
   mel_icas_outr   r   r   r   r   T   s   r   c               @   s,   e Zd ZdZeZeZdZdd Z	dd Z
dS )TrainingSetCreatora  Goes through set of provided melodic output directories, to find all
    the ones that have a hand_labels_noise.txt file in them.

    This is outsourced as a separate class, so that the pipeline is
    rerun everytime a handlabeled file has been changed, or a new one
    created.

    Tc             C   sZ   g }x0| j jD ]$}tjjtjj|dr|j| qW t|dkrVtd| j	j
|f |S )Nzhand_labels_noise.txtr   zP%s did not find any hand_labels_noise.txt files in the following directories: %s)inputsr   ospathr   joinappendlen	Exception	__class__r   )selfZruntimemel_icasitemr   r   r   _run_interfacel   s    z!TrainingSetCreator._run_interfacec             C   sN   g }x0| j jD ]$}tjjtjj|dr|j| qW | j j }||d< |S )Nzhand_labels_noise.txtr   )	r   r   r    r!   r   r"   r#   Z_outputsget)r'   r(   r)   outputsr   r   r   _list_outputsz   s    z TrainingSetCreator._list_outputsN)r   r   r   __doc__r   
input_specr   output_specZ_always_runr*   r-   r   r   r   r   r   ^   s   r   c               @   s   e Zd ZeddddddZdS )	FeatureExtractorInputSpecTFz'Melodic output directory or directoriesz%sr   )r   r   r   r   r   Nr   )r   r   r   r
   mel_icar   r   r   r   r1      s   r1   c               @   s   e Zd ZeddddddZdS )	FeatureExtractorOutputSpecTFz'Melodic output directory or directoriesz%sr   )r   r   r   r   r   Nr   )r   r   r   r
   r2   r   r   r   r   r3      s   r3   c               @   s$   e Zd ZdZeZeZdZdd Z	dS )FeatureExtractorzB
    Extract features (for later training and/or classifying)
    zfix -fc             C   s   | j  j }| jj|d< |S )Nr2   )r0   r+   r   r2   )r'   r,   r   r   r   r-      s    zFeatureExtractor._list_outputsN)
r   r   r   r.   r1   r/   r3   r0   cmdr-   r   r   r   r   r4      s
   r4   c               @   sD   e Zd ZeedddddddZejdddd	Zej	d
dddZ
dS )TrainingInputSpecT)r   FzMelodic output directoriesz%sr   )r   r   r   r   zJtrained-weights filestem, used for trained_wts_file and output directories)r   r   r   z-lz0full leave-one-out test with classifier trainingr   )r   r   r   Nr   )r   r   r   r   r
   r(   r	   Strtrained_wts_filestemBoolZloor   r   r   r   r6      s   r6   c               @   s   e Zd ZedddZdS )TrainingOutputSpecTzTrained-weights file)r   r   N)r   r   r   r   trained_wts_filer   r   r   r   r:      s   r:   c               @   s$   e Zd ZdZeZeZdZdd Z	dS )TrainingzO
    Train the classifier based on your own FEAT/MELODIC output directory.
    zfix -tc             C   sF   | j  j }t| jjr2tjj| jjd |d< ntjjd|d< |S )Nz.RDatar;   ztrained_wts_file.RData)r0   r+   r   r   r8   r    r!   abspath)r'   r,   r   r   r   r-      s    zTraining._list_outputsN)
r   r   r   r.   r6   r/   r:   r0   r5   r-   r   r   r   r   r<      s
   r<   c               @   sF   e Zd ZeeddddddddZeddd	dd
Zeddddd
ZdS )AccuracyTesterInputSpecT)r   FzMelodic output directoriesz%s   )r   r   r   r   	mandatoryztrained-weights filer   )r   r   r   r@   zBPath to folder in which to store the results of the accuracy test.r   N)	r   r   r   r   r
   r(   r   r;   output_directoryr   r   r   r   r>      s   r>   c               @   s   e Zd ZeddddZdS )AccuracyTesterOutputSpeczBPath to folder in which to store the results of the accuracy test.z%sr   )r   r   r   N)r   r   r   r
   rA   r   r   r   r   rB      s   rB   c               @   s$   e Zd ZdZeZeZdZdd Z	dS )AccuracyTesterz
    Test the accuracy of an existing training dataset on a set of hand-labelled subjects.
    Note: This may or may not be working. Couldn't presently not confirm because fix fails on this (even outside of nipype) without leaving an error msg.
    zfix -Cc             C   sB   | j  j }t| jjr.td| jjd|d< ntddd|d< |S )NF)r   valuerA   Zaccuracy_test)r0   r+   r   r   rA   r
   )r'   r,   r   r   r   r-      s    zAccuracyTester._list_outputsN)
r   r   r   r.   r>   r/   rB   r0   r5   r-   r   r   r   r   rC      s
   rC   c               @   sN   e Zd ZeddddddZeddddddd	Zejd
ddddZ	eddZ
dS )ClassifierInputSpecTFz'Melodic output directory or directoriesz%sr   )r   r   r   r   r   ztrained-weights filer   )r   r   r   r   r@   r   z%dzThreshold for cleanup.)r   r   r   r@   zkText file listing which ICs are artifacts; can be the output from classification or can be created manually)r   Nr   )r   r   r   r
   r2   r   r;   r	   ZIntthreshartifacts_list_filer   r   r   r   rE     s"   rE   c               @   s   e Zd ZeddZdS )ClassifierOutputSpeczkText file listing which ICs are artifacts; can be the output from classification or can be created manually)r   N)r   r   r   r   rG   r   r   r   r   rH   !  s   rH   c               @   s,   e Zd ZdZeZeZdZdd Z	dd Z
dS )
Classifierzu
    Classify ICA components using a specific training dataset (<thresh> is in the range 0-100, typically 5-20).
    zfix -cc             C   sL   t jj| jj\}}|jdd }d| d }t jj||t| d }|S )N.r   Zfix4melview_Z_thrz.txt)r    r!   splitr   r;   r"   str)r'   r2   rF   _r;   r8   Zfilestemfnamer   r   r   _gen_artifacts_list_file0  s
    z#Classifier._gen_artifacts_list_filec             C   s(   | j  j }| j| jj| jj|d< |S )NrG   )r0   r+   rO   r   r2   rF   )r'   r,   r   r   r   r-   9  s    zClassifier._list_outputsN)r   r   r   r.   rE   r/   rH   r0   r5   rO   r-   r   r   r   r   rI   '  s   	rI   c               @   s|   e Zd ZeddddddZejdddd	Zejd
dddddZ	ejdddd	Z
edddd	Zedddd	Zedddd	ZdS )CleanerInputSpecTz%sr   zkText file listing which ICs are artifacts; can be the output from classification or can be created manually)r   r   r   r@   r   z-mzJcleanup motion confounds, looks for design.fsf for highpass filter cut-offr   )r   r   r   d   z-m -h %fzcleanup motion confounds)r   Z
usedefaultr   r   z-AzkApply aggressive (full variance) cleanup, instead of the default less-aggressive (unique variance) cleanup.r?   z-x %sz!Include additional confound file.         N)r   r   r   r   rG   r	   r9   Zcleanup_motionZFloatZhighpassZ
aggressiveZconfound_fileZconfound_file_1Zconfound_file_2r   r   r   r   rP   B  s4   rP   c               @   s   e Zd ZedddZdS )CleanerOutputSpecTzCleaned session data)r   r   N)r   r   r   r   cleaned_functional_filer   r   r   r   rU   l  s   rU   c               @   s,   e Zd ZdZeZeZdZdd Z	dd Z
dS )CleanerzB
    Extract features (for later training and/or classifying)
    zfix -ac             C   s>   t |d}|j jd\}}tjj|\}}tjj||d S )zEextract the proper filename from the first line of the artifacts filerrJ   z_clean.nii.gz)openreadlinerK   r    r!   r"   )r'   Zartifacts_list_filenamerG   Zfunctional_filename	extensionZartifacts_list_file_pathr   r   r    _get_cleaned_functional_filenamey  s    

z(Cleaner._get_cleaned_functional_filenamec             C   s"   | j  j }| j| jj|d< |S )NrV   )r0   r+   r\   r   rG   )r'   r,   r   r   r   r-     s    zCleaner._list_outputsN)r   r   r   r.   rP   r/   rU   r0   r5   r\   r-   r   r   r   r   rW   p  s   rW   ) r.   baser   r   r   r   r   r   r   r	   r
   r   r   r    r   r   r   r1   r3   r4   r6   r:   r<   r>   rB   rC   rE   rH   rI   rP   rU   rW   r   r   r   r   <module>8   s(   4

&

*