function [D] = spm_eeg_inv_Mesh2Voxels(varargin)
% Convert a mesh representation of M/EEG power into a smoothed image
% FORMAT [D] = spm_eeg_inv_Mesh2Voxels(D,[val])
% Input:
% D        - MEEG object or filename of M/EEG mat-file (optional)
%
%     D.inv{val}.contrast.display:   display image at the end {true, [false]}
%     D.inv{val}.contrast.space:     native [0] or MNI {1} output space
%     D.inv{val}.contrast.format:    output file format {['image'], 'mesh'}
%     D.inv{val}.contrast.smoothing: # iterations for cortical smoothing
%
% Output:
% D        - MEEG object containing the new image filenames in fields:
%
%     D.inv{val}.contrast.fname
%__________________________________________________________________________
%
% Non-linear interpolation of a Mesh contrast into MNI Voxel space
% This routine is used to produce a 3D image canonical sMRI
% space (in voxel coordinates) from a cortical mesh (3D surface).
% This yields a NIfTI image of the summary statistics of the cortical
% activity for the effect of interest. This image can then enter the
% classical SPM routines for statistical testing.
% The [non-negative] mean square contrast is smoothed both on the mesh
% (using a graph Laplacian) and then in voxel-space using a conventional
% Gaussian filter.
%__________________________________________________________________________
% Copyright (C) 2007-2017 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_eeg_inv_Mesh2Voxels.m 7094 2017-06-06 11:14:10Z guillaume $


SVNrev = '$Rev: 7094 $';

%-Startup
%--------------------------------------------------------------------------
spm('FnBanner', mfilename, SVNrev);

%-Parse input arguments
%--------------------------------------------------------------------------
[D,val]      = spm_eeg_inv_check(varargin{:});

%-Get options
%--------------------------------------------------------------------------
try, space   = D.inv{val}.contrast.space;     catch, space  = 1; end
try, fmt     = D.inv{val}.contrast.format;    catch, fmt    = 'image'; end
try, smooth  = D.inv{val}.contrast.smoothing; catch, smooth = 8; end
try, Disp    = D.inv{val}.contrast.display;   catch, Disp   = 0; end

%-Time and Frequency windows of interest
%--------------------------------------------------------------------------
woi          = D.inv{val}.contrast.woi;
foi          = D.inv{val}.contrast.fboi;
Nw           = size(woi,1);

%-Get output image field of view and resolution
%--------------------------------------------------------------------------
if space
    sMRIfile = fullfile(spm('dir'),'canonical','avg152T2.nii');
else
    sMRIfile = D.inv{val}.mesh.sMRI;
end
Vin          = spm_vol(sMRIfile);

%-Get surface mesh
%--------------------------------------------------------------------------
if space
    m        = export(gifti(D.inv{val}.mesh.tess_mni),'patch');
else
    m        = export(gifti(D.inv{val}.mesh.tess_ctx),'patch');
end
nd           = D.inv{val}.inverse.Nd;


%-Accumulate mean of log-contrasts (over trials)
%==========================================================================
GL      = spm_mesh_smooth(m);

GW      = D.inv{val}.contrast.GW;

bytrial = iscell(GW{1});

if bytrial
    Ne  = cellfun(@numel,GW);
else
    Ne  = ones(1, numel(GW));
end

Nj      = numel(GW)/Nw;

k  = 1;
iw = [];
ie = [];
for c = 1:length(GW)
    if bytrial
        cGW = GW{c};
    else
        cGW = GW(c);
    end
    
    for t = 1:Ne(c)
        %-Smooth on the cortical surface
        %------------------------------------------------------------------
        ssq{k} = full(sparse(D.inv{val}.inverse.Is,1,cGW{t},nd,1));
        ssq{k} = spm_mesh_smooth(GL,ssq{k},smooth);
        
        %-Compute (truncated) moment
        %------------------------------------------------------------------
        lss        = log(ssq{k} + eps);
        i          = lss > (max(lss) - log(32));
        meanlss(k) = mean(lss(i));
        
        iw(k) = c;
        ie(k) = t;
        
        k = k + 1;
    end
end

scale = exp(mean(meanlss));

%-Save as meshes
%==========================================================================
if strcmpi(fmt,'mesh')
    [pth,name] = fileparts(D.fname);
    tag = cell(1,Nw);
    for i = 1:Nw
        tag{i} = ['t' sprintf('%g_', woi(i,:)) 'f' sprintf('%d_', foi)];
    end
    
    %-Save mesh topology
    %----------------------------------------------------------------------
    g = gifti(m);
    save(g,fullfile(D.path,[name '.surf.gii']));
    
    %-Save mesh data
    %----------------------------------------------------------------------
    spm_progress_bar('Init',numel(ssq),'Exporting as meshes','');
    fprintf('%-40s: %30s','Export as meshes','...please wait');         %-#
    for c = 1:numel(ssq)
        
        fprintf('%s%30s',repmat(sprintf('\b'),1,30),...
            sprintf('...mesh %d/%d',c,numel(ssq)));                     %-#
        
        %-Filename
        %------------------------------------------------------------------
        con       = mod(iw(c) - 1, Nj) + 1;
        str       = tag{ceil(iw(c)/Nj)};
        if bytrial, bt = sprintf('_%.0f',ie(c)); else bt = ''; end
        fname     = fullfile(D.path,...
            sprintf('%s_%.0f_%s%.0f%s.gii', name, val, str, con, bt));
        
        %-Normalise
        %------------------------------------------------------------------
        Contrast = ssq{c} / scale;
        %Contrast = Contrast.*(Contrast > exp(-8));
        
        %-Write mesh
        %------------------------------------------------------------------
        g = gifti;
        g.cdata = Contrast;
        g.private.metadata(1).name = 'SurfaceID';
        g.private.metadata(1).value = [name '.surf.gii'];
        save(g, fname, 'ExternalFileBinary');
        
        %-Store filename
        %------------------------------------------------------------------
        D.inv{val}.contrast.fname{c} = fname;
        
        spm_progress_bar('Set', c);
        
    end
    
    spm_progress_bar('Clear');
    fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done');           %-#
    
    return;
end

%-Normalise and embed in 3D-space
%==========================================================================
fprintf('%-40s: %30s','Writing images','...please wait');               %-#

[pth,name] = fileparts(D.fname);
tag = cell(1,Nw);
for i = 1:Nw
    tag{i} = ['t' sprintf('%d_', woi(i,:)) 'f' sprintf('%d_', foi)];
end

spm_progress_bar('Init',numel(ssq),'Interpolating images','');

con       = mod(iw - 1, Nj) + 1;
win       = ceil(iw/Nj);

ucon      = unique(con);
uwin      = unique(win);

n = 0;
for c = 1:length(ucon)
    for w = 1:numel(uwin)
        
        ind = find((con == ucon(c)) & (win == uwin(w)));
        str = tag{uwin(w)};
        
        fname     = fullfile(D.path,...
            sprintf('%s_%.0f_%s%.0f.nii', name, val, str, ucon(c)));
        
        %-Initialise image
        %------------------------------------------------------------------
        N      = nifti;
        N.dat  = file_array(fname, [Vin.dim, length(ind)], 'FLOAT32-LE');
        N.mat  = Vin.mat;
        N.mat0 = Vin.mat;
        create(N);
        
        
        for i = 1:length(ind)
            
            n = n+1;
            
            fprintf('%s%30s',repmat(sprintf('\b'),1,30),...
                sprintf('...image %d/%d',n,numel(ssq)));                %-#            
            
            %-Normalise
            %--------------------------------------------------------------
            Contrast = ssq{ind(i)} / scale;
            
            %-Interpolate those values into voxels
            %--------------------------------------------------------------
            RECimage = spm_mesh_to_grid(m, Vin, Contrast);
            
            %-3D smoothing and thresholding
            %--------------------------------------------------------------
            spm_smooth(RECimage, RECimage, 1);
            RECimage = RECimage.*(RECimage > exp(-8));
            
            %-Write (smoothed and scaled) image
            %--------------------------------------------------------------
            N.dat(:, :, :, i) = RECimage;
            
            %-Store filename
            %--------------------------------------------------------------
            D.inv{val}.contrast.fname{n} = fname;
            
            spm_progress_bar('Set', n);
            
        end
    end
end

spm_progress_bar('Clear');
fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done');               %-#

%-Display
%==========================================================================
if Disp && ~spm('CmdLine'), spm_eeg_inv_image_display(D); end
