function [ix] = spm_fieldindices(X,varargin)
% Returns the indices of fields in a structure (and vice versa)
% FORMAT [i]     = spm_fieldindices(X,field1,field2,...)
% FORMAT [field] = spm_fieldindices(X,i)
%
% X         - structure
% field1,.. - fields
%
% i         - vector of indices or fieldname{s}
%
% Note: Fields are returned in column order of X, regardless of the order
% of fields specified in the input.
%
%__________________________________________________________________________
% Copyright (C) 2010-2013 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_fieldindices.m 7031 2017-02-27 19:46:48Z karl $


% if varargin is a vector simply return fieldnames
%--------------------------------------------------------------------------
if isnumeric(varargin{1})
    if numel(varargin{1}) > 1
        for j = 1:length(varargin{1})
            ix{j} = spm_fieldindices(X,varargin{1}(j));
        end
        return
    end
end

% create structure of zeros
%--------------------------------------------------------------------------
X0    = spm_zeros(X);
ix    = spm_vec(X0);

% and add one to specified fields
%--------------------------------------------------------------------------
for i = 1:length(varargin)
    
    if ischar(varargin{i})
        
        field = varargin{i};
        x  = X0;
        try
            % field is a field name
            %--------------------------------------------------------------
            f  = x.(field);
            f  = spm_unvec(spm_vec(f) + 1,f);
            x.(field) = f;
            ix = ix + spm_vec(x);
            
        catch
            try
                % field is an expression
                %----------------------------------------------------------
                eval(['x.' field ' = x.' field ' + 1;']);
                ix = ix + spm_vec(x);
            end
        end
        
        % or return the name of the field
        %----------------------------------------------------------------------
    elseif isnumeric(varargin{i})
        
        ind    = varargin{i};
        x      = ix;
        x(ind) = 1;
        x      = spm_unvec(x,X);
        name   = fieldnames(x);
        
        for j = 1:length(name)
            if any(spm_vec(x.(name{j})))
                if iscell(x.(name{j}))
                    for k = 1:numel(x.(name{j}))
                        xv = spm_vec(x.(name{j}){k});
                        if any(xv)
                            if isstruct(x.(name{j}){k})
                                s     = spm_fieldindices(x.(name{j}){k},find(xv));
                                ix    = sprintf('%s{%i}.%s',name{j},k,s);
                            else
                                [p,q] = find(x.(name{j}){k});
                                ix    = sprintf('%s{%i}(%i,%i)',name{j},k,p,q);
                            end
                            return
                        end
                    end
                elseif isnumeric(x.(name{j}))
                    s   = size(x.(name{j}));
                    if numel(s) < 3
                        if min(s) == 1
                            p    = find(x.(name{j}));
                            ix   = sprintf('%s(%i)',name{j},p);
                            return
                        else
                            [p,q] = find(x.(name{j}));
                            ix    = sprintf('%s(%i,%i)',name{j},p,q);
                            return
                        end
                    else
                        [p,q,r] = ind2sub(s,find(x.(name{j})));
                        ix      = sprintf('%s(%i,%i,%i)',name{j},p,q,r);
                        return
                    end
                end
            end
        end
    end
end

% find indices
%--------------------------------------------------------------------------
ix = find(ix);
