3
d                 @   s2  d Z ddlZddlmZ ddlZddlmZ ddlmZm	Z	m
Z
 ddlmZmZmZmZmZmZmZmZ d	d
lmZmZmZmZ dZejd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/d0 d0eZ,G d1d2 d2e*Z-G d3d4 d4e,Z.G d5d6 d6e*Z/G d7d8 d8e,Z0G d9d: d:e*Z1G d;d< d<e,Z2G d=d> d>e*Z3G d?d@ d@e,Z4dS )AzaThe spm module provides basic functions for interfacing with matlab
and spm to access spm tools.
    N)glob   )logging)ensure_listsimplify_listsplit_filename   )BunchtraitsTraitedSpecFile	DirectoryOutputMultiPathInputMultiPath	isdefined   )
SPMCommandSPMCommandInputSpecscans_for_fnamesImageFileSPMZrestructuredtextznipype.interfacec               @   s  e Zd ZeddddZejdddddd	Zejd
ddd	Z	ej
dddZejdddZejdddd	ZejejejdddddZejejddddddddd	Zejddd d!dZejd"d#d$d%dZedd&d'dZejejd(ej d)d(dd*Zejd+d,d"d-d.dZejd/d0Zd1S )2Level1DesignInputSpecTdirz%directory to store SPM.mat file (opt))existsfielddescZsecsscansztiming.unitsz!units for specification of onsets)r   r   	mandatoryz	timing.RTzInterscan interval in secsztiming.fmri_tz*Number of time-bins per scan in secs (opt))r   r   ztiming.fmri_t0z1The onset/time-bin in seconds for alignment (opt)sesszCSession specific information generated by ``modelgen.SpecifyModel``nameZlevelsZfactz&Factor specific information file (opt)ZhrfZfourierZfourier_hangammaZfirbasesa  Dictionary names of the basis function to parameters:

    * hrf

        * derivs -- (2-element list) Model  HRF  Derivatives. No derivatives: [0,0],
          Time derivatives : [1,0], Time and Dispersion derivatives: [1,1]

    * fourier, fourier_han, gamma, or fir:

        * length -- (int) Post-stimulus window length (in seconds)
        * order -- (int) Number of basis functions

r   r   Zvoltz Model interactions - no:1, yes:2noneZscalingglobalz0Global intensity normalization - scaling or nonemaskz,Image  for  explicitly  masking the analysisz-InfzThresholding for the mask)r   default
usedefaultzAR(1)ZFASTZcvizIModel serial correlations AR(1), FAST or none. FAST is available in SPM12zrAdditional arguments to the job, e.g., a common SPM operation is to modify the default masking threshold (mthresh))r   N)__name__
__module____qualname__r   spm_mat_dirr
   EnumZtiming_unitsFloatZinterscan_intervalIntZmicrotime_resolutionZmicrotime_onsetZAnysession_infoListDictZfactor_infor    Zvolterra_expansion_orderZglobal_intensity_normalizationr   
mask_imageEithermask_thresholdZmodel_serial_correlationsflags r4   r4   =/tmp/pip-build-7vycvbft/nipype/nipype/interfaces/spm/model.pyr   !   sf   
r   c               @   s   e Zd ZedddZdS )Level1DesignOutputSpecTzSPM mat file)r   r   N)r&   r'   r(   r   spm_mat_filer4   r4   r4   r5   r6   w   s   r6   c                   sP   e Zd ZdZeZeZdZdZ	 fddZ
 fddZ fdd	Zd
d Z  ZS )Level1Designa  Generate an SPM design matrix

    http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=59

    Examples
    --------

    >>> level1design = Level1Design()
    >>> level1design.inputs.timing_units = 'secs'
    >>> level1design.inputs.interscan_interval = 2.5
    >>> level1design.inputs.bases = {'hrf':{'derivs': [0,0]}}
    >>> level1design.inputs.session_info = 'session_info.npz'
    >>> level1design.inputs.flags = {'mthresh': 0.4}
    >>> level1design.run() # doctest: +SKIP

    statsZ	fmri_specc                sL   |dkrt jt|gtdS |dkr8t|tr4|gS |S tt| j|||S )z+Convert input to appropriate format for spmr)   r0   )dtyper-   )r)   r0   )r-   )	nparraystrobject
isinstancedictsuperr8   _format_arg)selfoptspecval)	__class__r4   r5   rB      s    
zLevel1Design._format_argc                s   t t| jdd}t| jjr>|d jdd | jjj D  x,|d d D ]}tt	|d d	d
|d< qLW t| jj
stjttj gtd|d d< |S )z2validate spm realign options if set to None ignorer2   r3   )skipr   c             S   s   i | ]\}}||qS r4   r4   ).0flagrF   r4   r4   r5   
<dictcomp>   s    z.Level1Design._parse_inputs.<locals>.<dictcomp>r   r   F)Zkeep4d)r:   r   )r2   r3   )rA   r8   _parse_inputsr   inputsr3   updateitemsr   r   r)   r;   r<   r=   osgetcwdr>   )rC   einputsZsessinfo)rG   r4   r5   rL      s    
  zLevel1Design._parse_inputsc                sn   t | jjrVd}|dt| jj 7 }|d7 }|d7 }|d| jj 7 }|d7 }|d7 }nd}tt| j||d	S )
zvalidates spm options and generates job structure
        if mfile is True uses matlab .m file
        else generates a job structure and saves in .mat
        z
load SPM;
zSPM.xM.VM = spm_vol('%s');
zSPM.xM.I = 0;
zSPM.xM.T = [];
z(SPM.xM.TH = ones(size(SPM.xM.TH))*(%s);
z8SPM.xM.xs = struct('Masking', 'explicit masking only');
zsave SPM SPM;
N)
postscript)r   rM   r0   r   r2   rA   r8   _make_matlab_command)rC   contentrS   )rG   r4   r5   rT      s    

z!Level1Design._make_matlab_commandc             C   s*   | j  j }tjjtj d}||d< |S )NzSPM.matr7   )_outputsgetrP   pathjoinrQ   )rC   outputsspmr4   r4   r5   _list_outputs   s    zLevel1Design._list_outputs)r&   r'   r(   __doc__r   
input_specr6   output_spec_jobtype_jobnamerB   rL   rT   r\   __classcell__r4   r4   )rG   r5   r8   {   s   r8   c               @   sT   e Zd ZeddddddZejejdddddd	d
Zej	dddZ
ejddZdS )EstimateModelInputSpecTspmmatzAbsolute path to SPM.mat)r   r   copyfiler   r   	Classical	Bayesian2BayesianmethodzFDictionary of either Classical: 1, Bayesian: 1, or Bayesian2: 1 (dict))r   r   r   write_residualsz Write individual residual images)r   r   zAdditional arguments)r   N)r&   r'   r(   r   r7   r
   r/   r*   estimation_methodBoolrj   r3   r4   r4   r4   r5   rc      s   
rc   c               @   s   e Zd ZedddZeeddddZedddZeeddddZedd	dZ	e
dd
dZedddZeeddddZeeddddZeeddddZeeddddZdS )EstimateModelOutputSpecTz#binary mask to constrain estimation)r   r   )r   zdesign parameter estimates)r   z#Mean-squared image of the residualsz6individual residual images (requires `write_residuals`zResels per voxel imagezUpdated SPM mat filez
label filez-Images of the standard deviation of the errorzImages of the AR coefficientz"Images of the parameter posteriorsz8Images of the standard deviation of parameter posteriorsN)r&   r'   r(   r   r0   r   beta_imagesresidual_imageresidual_imagesRPVimager   r7   labelsSDerrorARcoefCbetasSDbetasr4   r4   r4   r5   rm      s(   
rm   c                   sD   e Zd ZdZeZeZdZdZ	 fddZ
 fddZdd	 Z  ZS )
EstimateModela3  Use spm_spm to estimate the parameters of a model

    http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=69

    Examples
    --------
    >>> est = EstimateModel()
    >>> est.inputs.spm_mat_file = 'SPM.mat'
    >>> est.inputs.estimation_method = {'Classical': 1}
    >>> est.run() # doctest: +SKIP
    r9   Zfmri_estc                sX   |dkrt jt|gtdS |dkrDt|ttfr@dj|diS |S tt| j	|||S )z+Convert input to appropriate format for spmr7   )r:   rk   z{}r   )
r;   r<   r=   r>   r?   bytesformatrA   rw   rB   )rC   rD   rE   rF   )rG   r4   r5   rB     s    zEstimateModel._format_argc                sB   t t| jdd}t| jjr>|d jdd | jjj D  |S )z2validate spm realign options if set to None ignorer3   )rH   r   c             S   s   i | ]\}}||qS r4   r4   )rI   rJ   rF   r4   r4   r5   rK      s    z/EstimateModel._parse_inputs.<locals>.<dictcomp>)rA   rw   rL   r   rM   r3   rN   rO   )rC   rR   )rG   r4   r5   rL     s     zEstimateModel._parse_inputsc                s  dd l j}| j j }tjj| jj d| j	j
dd kr>dnd}|j| jjdd}dd	 |d
 d$ jd D }d| jjj ksd| jjj krtjj dj||d< ttjj d|d< ttjj d|d< |r fdd	|D |d<  fdd	|D |d< d| jjj krtjj dj||d< tjj dj||d< | jjrjttjj d|d< |r fdd	|D |d< tjj d j||d!< tjj d"|d#< |S )%Nr   12.ZniiimgF)struct_as_recordc             S   s   g | ]}|j d  qS )r   )fname)rI   Zvbetar4   r4   r5   
<listcomp>+  s    z/EstimateModel._list_outputs.<locals>.<listcomp>SPMrh   rg   z	labels.{}rr   zSess*_SDerror*rs   z
Sess*_AR_*rt   c                s    g | ]}t jj d j|qS )zC{})rP   rX   rY   ry   )rI   beta)pthr4   r5   r   5  s    ru   c                s    g | ]}t jj d j|qS )zSD{})rP   rX   rY   ry   )rI   r   )r   r4   r5   r   8  s    rv   rf   zResMS.{}ro   zRPV.{}rq   zRes_*rp   c                s   g | ]}t jj |qS r4   )rP   rX   rY   )rI   r   )r   r4   r5   r   A  s    rn   zmask.{}r0   zSPM.matr7   )r   r   )scipy.ioiorV   rW   rP   rX   dirnamerM   r7   versionsplitloadmatZVbetark   keysrY   ry   r   rj   )rC   siorZ   Zouttyper[   Zbetasr4   )r   r5   r\   #  s0    

zEstimateModel._list_outputs)r&   r'   r(   r]   rc   r^   rm   r_   r`   ra   rB   rL   r\   rb   r4   r4   )rG   r5   rw      s   rw   c               @   sB  e Zd ZeddddddZejejejej	ej
dejej	ejejejej	ej
dejej	ejejejejejej	ej
dejejejej	ej
dejej	ejejejej	ej
dejej	ejejejejdddZeedd	d
dddZedddddZejddgdZejddgdZdS )EstimateContrastInputSpecTrd   zAbsolute path to SPM.mat)r   r   r   re   r   TFaE  List of contrasts with each contrast being a list of the form:
            [('name', 'stat', [condition list], [weight list], [session list])]
            If session list is None or not provided, all sessions are used. For
            F contrasts, the condition list should contain previously defined
            T-contrasts.)r   r   )r   z(Parameter estimates of the design matrixF)r   re   r   z#Mean-squared image of the residuals)r   r   re   r   zuse derivatives for estimationgroup_contrast)r   xorzhigher level contrast
use_derivsN)r&   r'   r(   r   r7   r
   r.   r1   TupleStrr*   r+   	contrastsr   rn   ro   rl   r   r   r4   r4   r4   r5   r   H  sd   






r   c               @   s`   e Zd ZeeddddZeeddddZeeddddZeeddddZeddd	Z	d
S )EstimateContrastOutputSpecT)r   z!contrast images from a t-contrast)r   zstat images from a t-contrastz"contrast images from an F-contrastzstat images from an F-contrastzUpdated SPM mat file)r   r   N)
r&   r'   r(   r   r   
con_imagesspmT_images
ess_imagesspmF_imagesr7   r4   r4   r4   r5   r     s   r   c               @   s0   e Zd ZdZeZeZdZdZ	dd Z
dd ZdS )	EstimateContrasta  Use spm_contrasts to estimate contrasts of interest

    Examples
    --------
    >>> import nipype.interfaces.spm as spm
    >>> est = spm.EstimateContrast()
    >>> est.inputs.spm_mat_file = 'SPM.mat'
    >>> cont1 = ('Task>Baseline','T', ['Task-Odd','Task-Even'],[0.5,0.5])
    >>> cont2 = ('Task-Odd>Task-Even','T', ['Task-Odd','Task-Even'],[1,-1])
    >>> contrasts = [cont1,cont2]
    >>> est.inputs.contrasts = contrasts
    >>> est.run() # doctest: +SKIP

    r9   conc          
   C   s  g }g }xt | jjD ]r\}}|j||d  |j|t|d |d |d ddd t|dkrn|d || _t|dkr|d || _qW d	| jjt	j
 f g}t| jjr| jjr|d
g7 }nF| jjr|dg7 }n
|dg7 }|dg7 }|dg7 }|dg7 }|dg7 }xt |D ]\}}|jdkr|d|d |jf g7 }|d|d  g7 }xt |jD ]\}}	|d|	 g7 }|d|	 g7 }|jrxht |jD ]<\}
}|d|
d  g7 }|d|d ||j|  f g7 }qW n|d|d |j| f g7 }q\W qW xt |D ]v\}}|jdkr|d|d |jf g7 }xFt |jD ]8\}}|j|d }|d|d |d |d f g7 }q@W qW |dg7 }|dg7 }|dg7 }dj|S ) z0Validate spm options and generate job structure.r   r   r   N)r   stat
conditionsweightssessions   r      z%% generated by nipype.interfaces.spm
spm_defaults;
jobs{1}.stats{1}.con.spmmat  = {'%s'};
load(jobs{1}.stats{1}.con.spmmat{:});
SPM.swd = '%s';
save(jobs{1}.stats{1}.con.spmmat{:},'SPM');
names = SPM.xX.name;zcondnames=names;zpat = 'Sn\([0-9]*\) (.*)';zRpat = 'Sn\([0-9]*\) (.*)\*bf\(1\)|Sn\([0-9]*\) .*\*bf\([2-9]\)|Sn\([0-9]*\) (.*)';zt = regexp(names,pat,'tokens');zpat1 = 'Sn\(([0-9].*)\)\s.*';z!t1 = regexp(names,pat1,'tokens');zfor i0=1:numel(t)
  condnames{i0}='';
  condsess(i0)=0;
  if ~isempty(t{i0}{1})
    condnames{i0} = t{i0}{1}{1};
    condsess(i0)=str2num(t1{i0}{1}{1});
  end;
end;r   zconsess{%d}.tcon.name   = '%s';z0consess{%d}.tcon.convec = zeros(1,numel(names));z'idx = strmatch('%s',condnames,'exact');zlif isempty(idx)
  throw(MException('CondName:Chk', sprintf('Condition %%s not found in design','%s')));
end;zsidx = find(condsess(idx)==%d);z(consess{%d}.tcon.convec(idx(sidx)) = %f;z"consess{%d}.tcon.convec(idx) = %f;r   z consess{%d}.fcon.name   =  '%s';z6consess{%d}.fcon.convec{%d} = consess{%d}.tcon.convec;z'jobs{1}.stats{1}.con.consess = consess;zbif strcmp(spm('ver'),'SPM8')
  spm_jobman('initcfg');
  jobs=spm_jobman('spm5tospm8',{jobs});
end;zspm_jobman('run',jobs);
)	enumeraterM   r   insertr	   lenr   r   r7   rP   rQ   r   r   r   r   r   r   indexrY   )rC   _r   cnameiZcontscriptZcontrastZc0ZcondZsnoswZcl0ZfcontZtidxr4   r4   r5   rT     sx    
	


	
$$(

z%EstimateContrast._make_matlab_commandc             C   sj  dd l j}| j j }tjj| jj\}}|j	| jjdd}g }g }xb|d d j
d D ]L}|jttjj||jd jd  |jttjj||jd jd  qXW |r||d< ||d< d| jjdd k}	|	rttjj|d	}
nttjj|d
}
t|
dkrt|
|d< |	r.ttjj|d}nttjj|d}t|dkrZt||d< | jj|d< |S )Nr   F)r}   r   r   r   rz   r{   zess*.niizess*.imgr   z	spmF*.niiz	spmF*.imgr   r7   )r   r   )r   r   )r   r   )r   r   rV   rW   rP   rX   r   rM   r7   r   ZxConappendr=   rY   ZVconr~   ZVspmr   r   r   sorted)rC   r   rZ   r   r   r[   r   r   r   Zspm12ZessZspmfr4   r4   r5   r\     s2    
$(zEstimateContrast._list_outputsN)r&   r'   r(   r]   r   r^   r   r_   r`   ra   rT   r\   r4   r4   r4   r5   r     s   ir   c               @   s   e Zd ZedddddZedddddZejdddZej	dddd	Z
ej	ddd
d	Zejdddd	Zejddddd	Zejdddd	Zejdddd	Zej	dddd	ZdS )ThresholdInputSpecTzabsolute path to SPM.mat)r   r   re   r   z
stat imageFz$which contrast in the SPM.mat to use)r   r   zqwhether to use FWE (Bonferroni) correction for initial threshold (height_threshold_type has to be set to p-value))r%   r   z4whether to use FDR over cluster extent probabilitiesg?z2value for initial thresholding (defining clusters)zp-valuer   z9Is the cluster forming threshold a stat value or p-value?z7p threshold on FDR corrected cluster size probabilitiesr   zMinimum cluster size in voxelszIn case no clusters survive the topological inference step this will pick a culster with the highes sum of t-values. Use with care.N)r&   r'   r(   r   r7   
stat_imager
   r,   contrast_indexrl   use_fwe_correctionuse_topo_fdrr+   height_thresholdr*   height_threshold_typeextent_fdr_p_thresholdextent_thresholdforce_activationr4   r4   r4   r5   r   ;  s@   
r   c               @   s@   e Zd ZeddZej ZeddZej Z	ej
 Zej ZdS )ThresholdOutputSpecT)r   N)r&   r'   r(   r   thresholded_mapr
   r,   
n_clusterspre_topo_fdr_mappre_topo_n_clustersrl   activation_forcedr+   cluster_forming_thrr4   r4   r4   r5   r   q  s   

r   c               @   sB   e Zd ZdZeZeZdd Zdd Z	dd Z
dd	d
Zdd ZdS )	Thresholda  Topological FDR thresholding based on cluster extent/size. Smoothness is
    estimated from GLM residuals but is assumed to be the same for all of the
    voxels.

    Examples
    --------

    >>> thresh = Threshold()
    >>> thresh.inputs.spm_mat_file = 'SPM.mat'
    >>> thresh.inputs.stat_image = 'spmT_0001.img'
    >>> thresh.inputs.contrast_index = 1
    >>> thresh.inputs.extent_fdr_p_threshold = 0.05
    >>> thresh.run() # doctest: +SKIP
    c             C   s&   t | jj\}}}tjj|d | S )NZ_thr)r   rM   r   rP   rX   abspath)rC   r   r~   extr4   r4   r5   _gen_thresholded_map_filename  s    z'Threshold._gen_thresholded_map_filenamec             C   s&   t | jj\}}}tjj|d | S )NZ_pre_topo_thr)r   rM   r   rP   rX   r   )rC   r   r~   r   r4   r4   r5   _gen_pre_topo_map_filename  s    z$Threshold._gen_pre_topo_map_filenamec             C   s   d| j j }|d| j j 7 }| j jr.|d7 }n|d7 }| j jrH|d7 }n|d7 }| j jrb|d7 }n|d7 }|d	| j j 7 }|d
| j j 7 }|d| j j 7 }|d| j j	 7 }|d| j j
 7 }|d7 }|d| j  7 }|d7 }|d| j  7 }|S )Nzcon_index = %d;
zcluster_forming_thr = %f;
zthresDesc  = 'FWE';
zthresDesc  = 'none';
zuse_topo_fdr  = 1;
zuse_topo_fdr  = 0;
zforce_activation  = 1;
zforce_activation  = 0;
zcluster_extent_p_fdr_thr = %f;
zstat_filename = '%s';
zheight_threshold_type = '%s';
zextent_threshold = %d;
z	load %s;
a  
FWHM  = SPM.xVol.FWHM;
df = [SPM.xCon(con_index).eidf SPM.xX.erdf];
STAT = SPM.xCon(con_index).STAT;
R = SPM.xVol.R;
S = SPM.xVol.S;
n = 1;

switch thresDesc
    case 'FWE'
        cluster_forming_thr = spm_uc(cluster_forming_thr,df,STAT,R,n,S);

    case 'none'
        if strcmp(height_threshold_type, 'p-value')
            cluster_forming_thr = spm_u(cluster_forming_thr^(1/n),df,STAT);
        end
end

stat_map_vol = spm_vol(stat_filename);
[stat_map_data, stat_map_XYZmm] = spm_read_vols(stat_map_vol);

Z = stat_map_data(:)';
[x,y,z] = ind2sub(size(stat_map_data),(1:numel(stat_map_data))');
XYZ = cat(1, x', y', z');

XYZth = XYZ(:, Z >= cluster_forming_thr);
Zth = Z(Z >= cluster_forming_thr);

zZspm_write_filtered(Zth,XYZth,stat_map_vol.dim',stat_map_vol.mat,'thresholded map', '%s');
a  
max_size = 0;
max_size_index = 0;
th_nclusters = 0;
nclusters = 0;
if isempty(XYZth)
    thresholded_XYZ = [];
    thresholded_Z = [];
else
    if use_topo_fdr
        V2R        = 1/prod(FWHM(stat_map_vol.dim > 1));
        [uc,Pc,ue] = spm_uc_clusterFDR(cluster_extent_p_fdr_thr,df,STAT,R,n,Z,XYZ,V2R,cluster_forming_thr);
    end

    voxel_labels = spm_clusters(XYZth);
    nclusters = max(voxel_labels);

    thresholded_XYZ = [];
    thresholded_Z = [];

    for i = 1:nclusters
        cluster_size = sum(voxel_labels==i);
         if cluster_size > extent_threshold && (~use_topo_fdr || (cluster_size - uc) > -1)
            thresholded_XYZ = cat(2, thresholded_XYZ, XYZth(:,voxel_labels == i));
            thresholded_Z = cat(2, thresholded_Z, Zth(voxel_labels == i));
            th_nclusters = th_nclusters + 1;
         end
        if force_activation
            cluster_sum = sum(Zth(voxel_labels == i));
            if cluster_sum > max_size
                max_size = cluster_sum;
                max_size_index = i;
            end
        end
    end
end

activation_forced = 0;
if isempty(thresholded_XYZ)
    if force_activation && max_size ~= 0
        thresholded_XYZ = XYZth(:,voxel_labels == max_size_index);
        thresholded_Z = Zth(voxel_labels == max_size_index);
        th_nclusters = 1;
        activation_forced = 1;
    else
        thresholded_Z = [0];
        thresholded_XYZ = [1 1 1]';
        th_nclusters = 0;
    end
end

fprintf('activation_forced = %d\n',activation_forced);
fprintf('pre_topo_n_clusters = %d\n',nclusters);
fprintf('n_clusters = %d\n',th_nclusters);
fprintf('cluster_forming_thr = %f\n',cluster_forming_thr);

znspm_write_filtered(thresholded_Z,thresholded_XYZ,stat_map_vol.dim',stat_map_vol.mat,'thresholded map', '%s');
)rM   r   r   r   r   r   r   r   r   r   r7   r   r   )rC   r   r   r4   r4   r5   rT     s8    


8zThreshold._make_matlab_commandNc             C   s   | j  }t|d| j  t|d| j  x|jjdD ]}|jdrft|d|tdd  j dk q6|jdrt|dt	|tdd  j  q6|jd	rt|d
t	|td	d  j  q6|jdr6t|dt
|tdd  j  q6W |S )Nr   r   r   zactivation_forced = r   1zn_clusters = r   zpre_topo_n_clusters = r   zcluster_forming_thr = r   )rV   setattrr   r   stdoutr   
startswithr   stripintfloat)rC   runtimerZ   liner4   r4   r5   aggregate_outputs  s.    

 

zThreshold.aggregate_outputsc             C   s(   | j  j }| j |d< | j |d< |S )Nr   r   )rV   rW   r   r   )rC   rZ   r4   r4   r5   r\   -  s    zThreshold._list_outputs)N)r&   r'   r(   r]   r   r^   r   r_   r   r   rT   r   r\   r4   r4   r4   r5   r   z  s   {
r   c               @   sX   e Zd ZedddddZedddddZejdddZej	ddd	Z
ejd
dddZdS )ThresholdStatisticsInputSpecTzabsolute path to SPM.mat)r   r   re   r   z
stat imageFz$which contrast in the SPM.mat to use)r   r   z7stat value for initial thresholding (defining clusters))r   r   r   zMinimum cluster size in voxels)r%   r   N)r&   r'   r(   r   r7   r   r
   r,   r   r+   r   r   r4   r4   r4   r5   r   4  s   

r   c               @   s<   e Zd Zej Zej Zej Zej Zej Z	ej Z
dS )ThresholdStatisticsOutputSpecN)r&   r'   r(   r
   r+   voxelwise_P_Bonfvoxelwise_P_RFvoxelwise_P_uncorvoxelwise_P_FDRclusterwise_P_RFclusterwise_P_FDRr4   r4   r4   r5   r   D  s   r   c               @   s*   e Zd ZdZeZeZdd ZdddZ	dS )ThresholdStatisticsa  Given height and cluster size threshold calculate theoretical
    probabilities concerning false positives

    Examples
    --------

    >>> thresh = ThresholdStatistics()
    >>> thresh.inputs.spm_mat_file = 'SPM.mat'
    >>> thresh.inputs.stat_image = 'spmT_0001.img'
    >>> thresh.inputs.contrast_index = 1
    >>> thresh.inputs.height_threshold = 4.56
    >>> thresh.run() # doctest: +SKIP
    c             C   sX   d| j j }|d| j j 7 }|d| j j 7 }|d| j j 7 }|d| j j 7 }|d7 }|S )Nzcon_index = %d;
zcluster_forming_thr = %f;
zstat_filename = '%s';
zextent_threshold = %d;
z
load '%s'
a  
FWHM  = SPM.xVol.FWHM;
df = [SPM.xCon(con_index).eidf SPM.xX.erdf];
STAT = SPM.xCon(con_index).STAT;
R = SPM.xVol.R;
S = SPM.xVol.S;
n = 1;

voxelwise_P_Bonf = spm_P_Bonf(cluster_forming_thr,df,STAT,S,n)
voxelwise_P_RF = spm_P_RF(1,0,cluster_forming_thr,df,STAT,R,n)

stat_map_vol = spm_vol(stat_filename);
[stat_map_data, stat_map_XYZmm] = spm_read_vols(stat_map_vol);

Z = stat_map_data(:);
Zum = Z;

        switch STAT
            case 'Z'
                VPs = (1-spm_Ncdf(Zum)).^n;
                voxelwise_P_uncor = (1-spm_Ncdf(cluster_forming_thr)).^n
            case 'T'
                VPs = (1 - spm_Tcdf(Zum,df(2))).^n;
                voxelwise_P_uncor = (1 - spm_Tcdf(cluster_forming_thr,df(2))).^n
            case 'X'
                VPs = (1-spm_Xcdf(Zum,df(2))).^n;
                voxelwise_P_uncor = (1-spm_Xcdf(cluster_forming_thr,df(2))).^n
            case 'F'
                VPs = (1 - spm_Fcdf(Zum,df)).^n;
                voxelwise_P_uncor = (1 - spm_Fcdf(cluster_forming_thr,df)).^n
        end
        VPs = sort(VPs);

voxelwise_P_FDR = spm_P_FDR(cluster_forming_thr,df,STAT,n,VPs)

V2R        = 1/prod(FWHM(stat_map_vol.dim > 1));

clusterwise_P_RF = spm_P_RF(1,extent_threshold*V2R,cluster_forming_thr,df,STAT,R,n)

[x,y,z] = ind2sub(size(stat_map_data),(1:numel(stat_map_data))');
XYZ = cat(1, x', y', z');

[u, CPs, ue] = spm_uc_clusterFDR(0.05,df,STAT,R,n,Z,XYZ,V2R,cluster_forming_thr);

clusterwise_P_FDR = spm_P_clusterFDR(extent_threshold*V2R,df,STAT,R,n,cluster_forming_thr,CPs')
)rM   r   r   r   r   r7   )rC   r   r   r4   r4   r5   rT   _  s    -z(ThresholdStatistics._make_matlab_commandNc             C   s   | j  }d}xp|jjdD ]`}|dkrLt|j dkrLt||t| d}qt|j dkr|j d d
kr|j d }qqW |S )N r   r   r   r   r   r   r   r   )r   r   r   r   r   r   )rV   r   r   r   r   r   )rC   r   Zneeded_outputsrZ   Z
cur_outputr   r4   r4   r5   r     s"         z%ThresholdStatistics.aggregate_outputs)NN)
r&   r'   r(   r]   r   r^   r   r_   rT   r   r4   r4   r4   r5   r   M  s
   6r   c               @   s   e Zd ZeddddZeejejddddd	d
ddZ	ej
dddgddZejdddgddZejdddgddZej
dddZedddZej
dddgddZej
dd dgd!dZejejd"dd gddZej
d#d$dZejd%d&d'd(d)dZd*S )+FactorialDesignInputSpecTr   z%directory to store SPM.mat file (opt))r   r   r   vectorr   interaction	centering)	key_traitZcovz;covariate dictionary {vector, name, interaction, centering})r   r   zmasking.tm.tm_nonethreshold_mask_absolutethreshold_mask_relativezdo not use threshold masking)r   r   r   zmasking.tm.tma.athreshthreshold_mask_nonezuse an absolute thresholdzmasking.tm.tmr.rthreshz0threshold using a proportion of the global valuez
masking.imz,use implicit mask NaNs or zeros to thresholdz
masking.emz&use an implicit mask file to thresholdzglobalc.g_omitglobal_calc_meanglobal_calc_valueszomit global calculationzglobalc.g_meanglobal_calc_omitzuse mean for global calculationzglobalc.g_user.global_uvalzglobalm.gmsca.gmsca_noz!do not perform grand mean scalingr   r   r   zglobalm.glonormz5global normalization None-1, Proportional-2, ANCOVA-3N)r&   r'   r(   r   r)   r   r
   r/   r*   
covariatesrl   r   r+   r   r   Zuse_implicit_thresholdr   explicit_mask_filer   r   r.   r   Zno_grand_mean_scalingZglobal_normalizationr4   r4   r4   r5   r     sZ   

r   c               @   s   e Zd ZedddZdS )FactorialDesignOutputSpecTzSPM mat file)r   r   N)r&   r'   r(   r   r7   r4   r4   r4   r5   r     s   r   c                   sD   e Zd ZdZeZeZdZdZ	 fddZ
 fddZdd	 Z  ZS )
FactorialDesignzcBase class for factorial designs

    http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=77

    r9   Zfactorial_designc       
         s   |d
krt jt|gtdS |dkr|g }ddddd	}x@|D ]8}i }x$t|j D ]\}}	|	||| < qRW |j| q<W |S tt| j	|||S )z+Convert input to appropriate format for spmr)   r   )r:   r   r   cZiCFIiCC)r   r   r   r   )r)   r   )r   )
r;   r<   r=   r>   listrO   r   rA   r   rB   )
rC   rD   rE   rF   outlistmappingdictitemoutdictkeykeyval)rG   r4   r5   rB     s    
zFactorialDesign._format_argc                s>   t t| j }t| jjs:tjtt	j
 gtd|d d< |S )z2validate spm realign options if set to None ignore)r:   r   r   )rA   r   rL   r   rM   r)   r;   r<   r=   rP   rQ   r>   )rC   rR   )rG   r4   r5   rL     s     zFactorialDesign._parse_inputsc             C   s*   | j  j }tjjtj d}||d< |S )NzSPM.matr7   )rV   rW   rP   rX   rY   rQ   )rC   rZ   r[   r4   r4   r5   r\     s    zFactorialDesign._list_outputs)r&   r'   r(   r]   r   r^   r   r_   r`   ra   rB   rL   r\   rb   r4   r4   )rG   r5   r     s   r   c               @   s&   e Zd ZejedddddddZdS )OneSampleTTestDesignInputSpecT)r   zdes.t1.scansr   zinput files)r   r   minlenr   N)r&   r'   r(   r
   r.   r   in_filesr4   r4   r4   r5   r     s   r   c                   s$   e Zd ZdZeZ fddZ  ZS )OneSampleTTestDesignzCreate SPM design for one sample t-test

    Examples
    --------

    >>> ttest = OneSampleTTestDesign()
    >>> ttest.inputs.in_files = ['cont1.nii', 'cont2.nii']
    >>> ttest.run() # doctest: +SKIP
    c                s*   |dkrt j|tdS tt| j|||S )z+Convert input to appropriate format for spmr   )r:   )r   )r;   r<   r>   rA   r   rB   )rC   rD   rE   rF   )rG   r4   r5   rB   2  s    z OneSampleTTestDesign._format_arg)r&   r'   r(   r]   r   r^   rB   rb   r4   r4   )rG   r5   r   %  s   	r   c               @   s\   e Zd ZejedddddddZejedddddddZejd	d
dZ	ejdddZ
dS )TwoSampleTTestDesignInputSpecT)r   zdes.t2.scans1r   zGroup 1 input files)r   r   r   r   zdes.t2.scans2zGroup 2 input fileszdes.t2.deptz-Are the measurements dependent between levels)r   r   zdes.t2.variancez1Are the variances equal or unequal between groupsN)r&   r'   r(   r
   r.   r   group1_filesgroup2_filesrl   Z	dependentZunequal_variancer4   r4   r4   r5   r   9  s"   
r   c                   s$   e Zd ZdZeZ fddZ  ZS )TwoSampleTTestDesigna  Create SPM design for two sample t-test

    Examples
    --------

    >>> ttest = TwoSampleTTestDesign()
    >>> ttest.inputs.group1_files = ['cont1.nii', 'cont2.nii']
    >>> ttest.inputs.group2_files = ['cont1a.nii', 'cont2a.nii']
    >>> ttest.run() # doctest: +SKIP
    c                s*   |dkrt j|tdS tt| j|||S )z+Convert input to appropriate format for spmr   r   )r:   )r   r   )r;   r<   r>   rA   r   rB   )rC   rD   rE   rF   )rG   r4   r5   rB   a  s    z TwoSampleTTestDesign._format_arg)r&   r'   r(   r]   r   r^   rB   rb   r4   r4   )rG   r5   r   S  s   
r   c               @   sN   e Zd ZejejeddddddddddZejdd	d
Zejddd
Z	dS )PairedTTestDesignInputSpecT)r   r   )r   maxlenzdes.pt.pairzList of paired files)r   r   r   r   zdes.pt.gmscazPerform grand mean scaling)r   r   zdes.pt.ancovaz#Specify ancova-by-factor regressorsN)
r&   r'   r(   r
   r.   r   paired_filesrl   Zgrand_mean_scalingZancovar4   r4   r4   r5   r   h  s   
r   c                   s$   e Zd ZdZeZ fddZ  ZS )PairedTTestDesignzCreate SPM design for paired t-test

    Examples
    --------

    >>> pttest = PairedTTestDesign()
    >>> pttest.inputs.paired_files = [['cont1.nii','cont1a.nii'],['cont2.nii','cont2a.nii']]
    >>> pttest.run() # doctest: +SKIP
    c                s*   |dkrdd |D S t t| j|||S )z+Convert input to appropriate format for spmr   c             S   s    g | ]}t tj|td dqS ))r:   )r   )r@   r;   r<   r>   )rI   filesr4   r4   r5   r     s    z1PairedTTestDesign._format_arg.<locals>.<listcomp>)r   )rA   r   rB   )rC   rD   rE   rF   )rG   r4   r5   rB     s    zPairedTTestDesign._format_arg)r&   r'   r(   r]   r   r^   rB   rb   r4   r4   )rG   r5   r   x  s   	r   c               @   sX   e Zd ZejedddddddZejddddd	Ze	ej
ejd
ddddddZdS )!MultipleRegressionDesignInputSpecT)r   zdes.mreg.scansr   zList of files)r   r   r   r   zdes.mreg.incintzInclude intercept in design)r   r%   r   r   r   r   )r   zdes.mreg.mcovz.covariate dictionary {vector, name, centering})r   r   N)r&   r'   r(   r
   r.   r   r   rl   Zinclude_interceptr   r/   r*   user_covariatesr4   r4   r4   r5   r     s   r   c                   s$   e Zd ZdZeZ fddZ  ZS )MultipleRegressionDesignzCreate SPM design for multiple regression

    Examples
    --------

    >>> mreg = MultipleRegressionDesign()
    >>> mreg.inputs.in_files = ['cont1.nii','cont2.nii']
    >>> mreg.run() # doctest: +SKIP
    c       
         s   |dkrt j|tdS |d	krtg }dddd}x@|D ]8}i }x$t|j D ]\}}	|	||| < qJW |j| q4W |S tt| j|||S )
z+Convert input to appropriate format for spmr   )r:   r   r   r   r   )r   r   r   )r   )r   )	r;   r<   r>   r   rO   r   rA   r   rB   )
rC   rD   rE   rF   r   r   r   r   r   r   )rG   r4   r5   rB     s    
z$MultipleRegressionDesign._format_arg)r&   r'   r(   r]   r   r^   rB   rb   r4   r4   )rG   r5   r     s   	r   )5r]   rP   r   numpyr;   r   r   Zutils.filemanipr   r   r   baser	   r
   r   r   r   r   r   r   r   r   r   r   Z__docformat__	getLoggerZifloggerr   r6   r8   rc   rm   rw   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r4   r4   r4   r5   <module>   sJ   (

VRIF 6	 ;	^>.
