function fields = utl_timeseries_fields(signal)
% Get the time-series fields of te given signal.
% function Fields = utl_timeseries_fields(Signal)
%
% This function returns the field names in the given signal that are
% carrying time-series information (and which therefore should be filtered,
% buffered, etc.). The result is a combination of a set of hard-coded fields
% and the names listed in the field .tracking.timeseries_fields. Only fields
% that are present in the signal are returned.
%
% In:
%   Signal : a signal for which time-series field names shall be looked up
%
% Out:
%   Fields : Cell array of field names (row vector). It is assumed that the second dimension of
%            these fields is the time axis along which buffering and/or filtering should happen; any
%            number of other dimensions may be present for any field returned by this function.
%
% See also:
%   utl_register_field
%
%                                       Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                       2013-08-16

% define a database of cached queries and associated results
% (this approach is more than 10x as fast as using unique/intersect every time)
persistent keys;
persistent values;

try
    % generate the query (assuming that the signal usually has the right fields)
    try
        query = [fieldnames(signal)' {'|'} signal.tracking.timeseries_fields];
    catch
        query = fieldnames(signal)';
    end

    % turn into a string
    query = [query{:}];

    try
        % look up from the database (assuming that it is already contained)
        fields = values{strcmp(keys,query)};
    catch
        % not yet in DB: actually determine the timeseries fields
        if isfield(signal,'tracking') && isfield(signal.tracking,'timeseries_fields')
            fields = get_timeseries_fields(fieldnames(signal),signal.tracking.timeseries_fields);
        else
            fields = get_timeseries_fields(fieldnames(signal),[]);
        end
        % initialize the DB if necessary, otherwise append
        if ~iscell(keys)
            keys = {query};
            values = {fields};
        else
            keys{end+1} = query;
            values{end+1} = fields;
        end
    end
catch e
    % diagnose the error
    if ~isstruct(signal)
        error('The given argument must be a signal struct.'); end
    if ~isscalar(signal)
        error('The given argument must be a 1x1 struct.'); end
    if ~isfield(signal,'tracking')
        if ~any(isfield(signal,{'data','srate'}))
            if all(isfield(signal,{'head','parts'}))
                error('The given input is an unevaluated expression but this function expects a signal data structure. You may have to first evaluate the data using exp_eval.');
            else
                error('The given data structure does not appear to be a valid signal struct.');
            end
        else
            error('The given signal is lacking the required .tracking field.');
        end
    else
        rethrow(e);
    end
end

function fields = get_timeseries_fields(field_names,ts_fields)
% This function performs the actual computation

% generate initial list of candidates
candidates = {'data','icaact','srcpot','stamps'};

% append whatever is registered in the signal's .tracking.timeseries_fields
candidates = unique([candidates(:); ts_fields(:)]);

% restrict to those that are actually present in the signal
fields = intersect(candidates(:),field_names);
fields = fields(:)';


function out = reorderLegend(order,h)
% reorderLegend
%   Re-orders the legend entries
%   (without modifying the actual order the curves are stacked on the axes)
%
%   order  - an array specifying the order of legend entries
%   h      - axis handle (optional, defaults to current axis)
%
%   Invoking the function without an argument or with order==[]
%   causes the labels of the curves to be returned (or displayed, if
%   nargout==0).
%       e.g.
%           >> x = 0:.1:10;
%           >> plot(x,x,x,2*x,x,3*x,x,4*x); legend('x','2x','3x','4x');
%           >> reorderLegend
%           [1] 4x
%           [2] 3x
%           [3] 2x
%           [4] x
%
%   The indices of the labels (i.e., 1 to 4 in the above e.g.)
%   can be used to specify the desired order of legend entries.
%       e.g.
%           >> reorderLegend([4,2,1,3]);
%               % legend: 'x','3x','4x','2x' (from top to bottom)
%
%   Notes:
%   - By default, the legend entries are in the reverse order of the
%   indices (because the curves are in a stack).
%   - `reorderLegend' doesn't change the order of the curves
%   (i.e., the indices are not changed when it's called).
%
%   Author        : Damith Senaratne, (http://www.damiths.info)
%   Released date : 21th June 2012

    if nargin < 2
        h = gca;
    end

    hC = findobj(h,'Type','line');

    if nargin == 0 || isempty(order)
        % output/display the internal order
        lbl = get(hC,{'DisplayName'});
        if nargout == 1
            out = lbl;
        else
            for k = 1:length(lbl)
               display([sprintf('[%*d] ',fix(log10(length(lbl)))+1,k) lbl{k}]);
            end
        end

    else
       % reorder the legend entries
       legend(hC(order));
    end
end


function varargout = ldivide(varargin)
%.\   Pointwise CHEBFUN2 left array divide.
%   F.\G if G is a CHEBFUN2 and F is a double this returns (1/F)*G
%
%   F.\G if G is a double and F is a CHEBFUN2 this returns G\F, but this does
%   not work if F becomes numerically close to zero.
%
%   F.\G we do not allow F and G to both be CHEBFUN2 objects.
%
%   F.\G is the same as the command ldivide(F,G)

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

[varargout{1:nargout}] = ldivide@separableApprox(varargin{:});

end


function endPointsRoi = dtiCreateRoiFromFiberEndPoints(fg,saveFlag)
% function dtiCreateRoiFromFiberEndPoints(fiberGroup,[saveFlag])
%
% Ths fucntion creates an roi from the endpoints of a given fiber
% group passed in by the user. It borrows code from dtiFiberUI.
% You must first load the fiber group with fg = dtiReadFibers('your.mat'),
% then pass in fg to this fucntion.
%
% If saveFlag == 1 the endPointsRoi will be saved to the current directory
% with the name of the fiber group with _endPointsROI added to the name.
%
% Example:
% fg = dtiReadFibers('your.mat');
% newROI = dtiCreateRoiFromFiberEndPoints(fg);
% dtiWriteRoi(newROI,newROI.name);
%
%
% History:
%  2009.03.25 LMP Wrote it.
%

if notDefined('saveFlag'), saveFlag = 0; end

if(~exist('fg','var') || isempty(fg))
    error 'You must pass in fiber group (fg) struct!';
end

nfibers = length(fg.fibers);
fc = zeros(nfibers*2, 3);
for jj=1:nfibers
    fc((jj-1)*2+1,:) = [fg.fibers{jj}(:,1)'];
    fc((jj-1)*2+2,:) = [fg.fibers{jj}(:,end)'];
end
endPointsRoi = dtiNewRoi([fg.name '_endPointsROI'], fg.colorRgb./255, fc);

if saveFlag == 1
    dtiWriteRoi(endPointsRoi,endPointsRoi.name);
    disp([endPointsRoi.name,' saved to ' pwd]);
end
return


%% SEMINAR: INTRODUCTION TO SIMULINK
% This seminar will show some of the basic and intermediate skills for Modeling,
% Designing and working with Simulink. This script will guide you through.
%%
%
%
Created by Roni Peer, 30.4.2012
Version 2.0

%

%% PART 1: BASICS
% This part will show how to use the basic abilities of Simulink to build, model,
% design and simulate a certain algorithm. Follow the steps bellow to do
% so.

%%% 1. Starting Simulink
% Let's open a new model and look what we can do with Simulink, and how
% it's built. We will build a small example to show the main features. The
% first model would show how to open Simulink, Drag blocks and connect
% them, configuring each block, running a simulation, and use of Stop
% Simulation.
simulink;

%%
% *To build SLWS_Step_01:*
%
%%
%
%
Step 01: Begin

%

%%
% # Open Simulink and show the Blocksets, search window, dragging of blocks.
% # Write the equation on the model: $F = ma ;  a = gravity; a = \dot{V}; V =
% \dot{X};$
% # Drag blocks: Constant, Integrator, Scope. Set $X_0 = 500; V_0 = 5; g =-9.81;$
% # Show how to zoom in/out/fit.
% # Find a way to stop the simulation when Altitude = 0;
% # Label the signals, and hide block names.
% # Change Simulation time to 100sec.
% # Simulate, and save the model.
%
% *To Open a complete step-1 model:*
%%
%
%
Step 01: Complete

%

%%% 2. Subsystems and libraries
% The next model would show some use of vector operations, subsystems,
% selector block, and finally to introduce Libraries.
% You can start with this model:
%%
%
%
Step 02: Begin

%

%%
% *To build SLWS_Step_02:*
%
% # Automaticaly align and resize the blocks.
% # Vectorize the gravity and signals: $g=$ [0 0 -9.81], $V_0=$ [8 -10 5],
% $X_0=$ [0 0 500]
% # Show the port data types.
% # Change solver to ODE23, Max. Step = 1sec.
% # Select the Z-component to stop simulation.
% # Create a subsystem for the "Stop Logic", and Change the Input signal to "Altitude"
% # Open Drag_Library and connect to the input with a "sum" block.
% # Define in MATLAB: $rho=1.2; Cd=0.333; A=1.5; m=150;$
% # Create Configurable Subsystem from the Drag Library
% In the end, you get this model:
%%
%
%
Step 02: Complete

%

%%% 3. Callbacks and BUSes
% The next model would show some use of BUS Signals, Masking Subsystems.
% You can start with this model:
%%
%
%
Step 03: Begin

%

%%
% *To build SLWS_Step_03:*
%
% # Create a callback which would load the parameters values ($Cd, A$...)
% # Create a mask for the Variable Density block. Show the constant one also.
% # Create a subsystem from the entire model - Name it Rocketeer.
% # Connect a BUS creator to velocity and Altitude, output them as "State".
% # Connect a constant block to acceleration. Value: $Thrust=$[0 0 1000]
% # Move the scope block to the top layer, and connect with a BUS Selector.
% # Run and verify.
% In the end, you get this model:
%%
%
%
Step 03: Complete

%

%%% 4. Closing the loop
% The next model would show how to continue to design the controller,
% and using a model reference.
% You can start with this model:
%%
%
%
Step 04: Begin

%

%%
% *To build SLWS_Step_04:*
%
% # Change "thrust" to "Desired Velocity", $V=$[0 0 -0.5]
% # Close the loop on velocity. Name the output "Error".
% # Connect a PID controller from Error to Plant. $PI =$ [50 5]
% # Connect scopes to "Thrust" and "Error".
% # Show block execution order. Discuss this concept. Treat Controller as
% Atomic.
% # Convert the controller to a model block, and replace.
% # Show difference between Controller and Plant - Hierarchy.
% # Run. View Error scope inside Controller. Why nothing? Why so slow?
% # Switch to Normal. Don't forget to inline parameters. What now?
% # Show the "Dependancy Viewer" and the "Generate Manifest"
% - You can talk more about controls in the link specified.
% In the end, you get this model:
%%
%
%
Step 04: Complete

%

%%% 5. "Slow Down!" - Control the rates and Embedded MATLAB
% The next model would show how to adjust the real-life settings of continuous
% and discrete systems. Also, how to incorprate Embedded MATLAB code into
% the model.
% You can start with this model:
%%
%
%
Step 05: Begin

%

%%
% *To build SLWS_Step_05:*
%
% # Set the PI Controller to Discrete, Sample Time  = 0.5sec.
% # Set the sample time display to Color.
% # Set Thrust outport and Velocity inport to inherit sample time.
% # Update, and look at the error.
% # Add rate transition blocks  before and after the model reference.
% # Change the controller's Solver to Fixed-Step Discrete.
% # Change the input to the controller to be a BUS. Define the BUS with the
% editor: StateBus - Position (3) and Velocity (3).
% # Save the BUS to a mat file, and save it. Use a callback to load it.
% # Include the Embedded MATLAB code in the Model.
% # Run.
%%
%
%
Open Embedded MATLAB Code

%
Step 05: Complete

%

%%% 6. Deploying the System
% Simulink allows you to generate different types of code.
% Open the following model, and generate these types of code:
% Embedded C-Code, HDL (VHDL or Verilog), and PLC Structured
% Text:
%%
%
%
Step 06: Deploy

%

%% PART 2: Multi-Domain Modeling
% This part will show how to use the more advanced abilities of Simulink to build, model,
% design and simulate your systems.
% Open the following models, and show how Simulink can aid in desiging
% multi-domain systems:

%%
%
%
Open Multi-Domain Model

%


function obj_io_test01 ( input_file_name )

%*****************************************************************************80
%
%% TEST01 tests OBJ_SIZE.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 September 2008
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST01\n' );
  fprintf ( 1, '  OBJ_SIZE determines the size of various objects\n' );
  fprintf ( 1, '  in an OBJ file.\n' );

  [ node_num, face_num, normal_num, order_max ] = obj_size ( input_file_name );

  obj_size_print ( input_file_name, node_num, face_num, normal_num, order_max );

  return
end


function egrad = getEuclideanGradient(problem, x, storedb, key)
% Computes the Euclidean gradient of the cost function at x.
%
% function egrad = getEuclideanGradient(problem, x)
% function egrad = getEuclideanGradient(problem, x, storedb)
% function egrad = getEuclideanGradient(problem, x, storedb, key)
%
% Returns the Euclidean gradient at x of the cost function described in the
% problem structure.
%
% storedb is a StoreDB object, key is the StoreDB key to point x.
%
% Because computing the Hessian based on the Euclidean Hessian will require
% the Euclidean gradient every time, to avoid overly redundant
% computations, if the egrad function does not use the store caching
% capabilites, this implements an automatic caching functionality. Writing
% egrad to accept the optional store or storedb parameter will disable
% automatic caching, but allow user controlled caching.
%
% See also: getGradient canGetGradient canGetEuclideanGradient

% This file is part of Manopt: www.manopt.org.
% Original author: Nicolas Boumal, July 9, 2013.
% Contributors:
% Change log:
%
%   April 3, 2015 (NB):
%       Works with the new StoreDB class system.
%
%   June 28, 2016 (NB):
%       Added support for getPartialEuclideanGradient
%
%   July 26, 2018 (NB):
%       The Euclidean gradient is now automatically cached if the Euclidean
%       Hessian is also computable from the problem description. This
%       differs from previous behavior where it would only be cached if
%       problem.egrad did not accept store or storedb as input; the
%       converse was taken as a sign that the user wants to deal with
%       caching on their own, but in reality it proved more confusing than
%       helpful.
%
%   Sep.  6, 2018 (NB):
%       The Euclidean gradient is now always cached. Caching conditioned on
%       the Euclidean Hessian being provided was problematic, because if no
%       Hessian is provided at all, then the default fall-back of finite
%       differences would be slowed down significantly without cache. Since
%       the new storedb functionalities around storedb.remove() much reduce
%       the number of stored stores, this should not be an issue.

    % Allow omission of the key, and even of storedb.
    if ~exist('key', 'var')
        if ~exist('storedb', 'var')
            storedb = StoreDB();
        end
        key = storedb.getNewKey();
    end

    % Contrary to most similar functions, here, we get the store by
    % default. This is for the special caching functionality described
    % below.
    store = storedb.getWithShared(key);
    store_is_stale = false;

    % We force caching of the Euclidean gradient. Look up first.
    force_egrad_caching = true;
    if force_egrad_caching && isfield(store, 'egrad__')
        egrad = store.egrad__;
        return;
    end

    if isfield(problem, 'egrad')
    %% Compute the Euclidean gradient using egrad.

        % Check whether this function wants to deal with storedb or not.
        switch nargin(problem.egrad)
            case 1
                egrad = problem.egrad(x);
            case 2
                [egrad, store] = problem.egrad(x, store);
            case 3
                egrad = problem.egrad(x, storedb, key);
                % The store structure in storedb might have been modified
                % (since it is passed by reference), so before caching
                % we'll have to update (see below).
                store_is_stale = true;
            otherwise
                up = MException('manopt:getEuclideanGradient:badegrad', ...
                    'egrad should accept 1, 2 or 3 inputs.');
                throw(up);
        end

    elseif canGetPartialEuclideanGradient(problem)
    %% Compute the Euclidean gradient using a full partial Euclidean gradient.

        d = problem.ncostterms;
        egrad = getPartialEuclideanGradient(problem, x, 1:d, storedb, key);
        store_is_stale = true;

    else
    %% Abandon computing the Euclidean gradient

        up = MException('manopt:getEuclideanGradient:fail', ...
            ['The problem description is not explicit enough to ' ...
             'compute the Euclidean gradient of the cost.']);
        throw(up);

    end

    % If we are not sure that the store structure is up to date, update.
    if store_is_stale
        store = storedb.getWithShared(key);
    end

    % Cache here.
    if force_egrad_caching
        store.egrad__ = egrad;
    end

    storedb.setWithShared(store, key);

end


function score = SSEQ( imdist )

    feature=feature_extract(imdist,3);
    score=SSQA_by_f(feature);

end


function [T]=writeNodeFile_tetGen(inputStruct)

%%

dispStartTitleGibbonCode('Writing NODE file');

%% PARSE INPUT STRUCTURE

V=inputStruct.Nodes;
nodeFileName=inputStruct.modelName;

%Force extension to be .node
[pathstr,name,~] = fileparts(nodeFileName);
nodeFileName=fullfile(pathstr,[name,'.node']);

%%

V_id=1:1:size(V,1);
V_field=[V_id(:) V];
V_char=sprintf('%i %0.16e %0.16e %0.16e \n',V_field');
V_cell = regexp(V_char, '\n', 'split');

if numel(V_cell)>1
    V_cell=V_cell(1:end-1);
end

T={'#PART 1 - Node list';'#num nodes, num dimensions, num attributes, num boundary markers'};
numNodes=size(V,1);
numDims=3;
numAtr=0;
boundMarker=0;
doubleList=[numNodes numDims numAtr boundMarker];
charList=sprintf('%i %i %i %i',doubleList');
T(end+1)={charList};
T(end+1)={'#Node ID, x, y, z,attribute,boundary marker'};
T(end+1:end+numel(V_cell))=V_cell;

%% SAVING TXT FILE

cell2txtfile(nodeFileName,T,0,0);
dispDoneGibbonCode;

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


function matrix2html(matrix, filename, varargin)
% matrix2html Generates a HTML table for a given matrix
%
% The function generates a HTML table based on a given matrix or cell array.
%
% Input
% - matrix (matrix): A 2 dimensional numerical or cell array
% - filename (string): A valid filename or a file handle
% - varargs[RowLabels] (array): Can be used to label the rows of the table
% - varargs[ColumnLabels] (array): Can be used to label the columns of the table
% - varargs[Format] (string): Format of the numeric input data in the printf format.
% - varargs[Class] (string): CSS class of the table.
% - varargs[Title] (string): Title of the table.
% - varargs[EmbedNumers] (boolean): Embed numerical data as data attributes.
%

    rowLabels = [];
    colLabels = [];
    format = '%.4f';
    css_class = [];
    title = [];
    embed_numbers = true;
    if (rem(nargin,2) == 1 || nargin < 2)
        error('Incorrect number of arguments to %s.', mfilename);
    end

    for i = 1:2:length(varargin)
        switch lower(varargin{i})
            case 'rowlabels'
                rowLabels = varargin{i+1};
            case 'columnlabels'
                colLabels = varargin{i+1};
            case 'format'
                format = lower(varargin{i+1});
            case 'class'
                css_class = [css_class, ' ', varargin{i+1}];
            case 'title'
                title = varargin{i+1};
            case 'embednumbers'
                embed_numbers = varargin{i+1};
            otherwise
                error(['Unknown switch ', varargin{i}, '!']) ;
        end
    end

    rowLabels = matrix2cells(rowLabels, 'th', format, false);
    colLabels = matrix2cells(colLabels, 'th', format, false);
    matrix = matrix2cells(matrix, 'td', format, embed_numbers);

    if (ischar(filename))
        fid = fopen(filename, 'w');
        close_file = 1;
    else
        fid = filename;
        close_file = 0;
    end;

    if ~isempty(colLabels) && ~isempty(rowLabels)

        stub = cell(size(colLabels, 1), size(rowLabels, 2));
        stub{1, 1} = sprintf(' 	', ...
                size(rowLabels, 2), size(colLabels, 1));

        head = cat(2, stub, colLabels);

        body = cat(2, rowLabels, matrix);

    elseif ~isempty(colLabels)

        head = colLabels;

        body = matrix;

    elseif ~isempty(rowLabels)

        head = [];
        body = cat(2, rowLabels, matrix);

    end;

    if(~isempty(title))
        fprintf(fid, '
%s
\n', title);
    end

    if(~isempty(css_class))
        fprintf(fid, '
\n', css_class);
    else
        fprintf(fid, '
\n');
    end

    if ~isempty(head)

        skip = cellfun(@(x) isempty(x), head, 'UniformOutput', true);
        fprintf(fid, '
');
        for i = 1 : size(head, 1)
            fprintf(fid, '
');
            cellfun(@(x) fwrite(fid, x), head(i, ~skip(i, :)), 'UniformOutput', true);
            fprintf(fid, '
');
        end;
        fprintf(fid, '
');
    end;

    skip = cellfun(@(x) isempty(x), body, 'UniformOutput', true);

    fprintf(fid, '
');
    for i = 1 : size(body, 1)
        fprintf(fid, '
');
        cellfun(@(x) fwrite(fid, x), body(i, ~skip(i, :)), 'UniformOutput', true);
        fprintf(fid, '
');
    end;
    fprintf(fid, '
');

    fprintf(fid, '
\r\n');

    if (close_file)
        fclose(fid);
    end;

end

function [cells] = matrix2cells(matrix, element, format, embed_numbers)

    if isnumeric(matrix)
        matrix = num2cell(matrix);
    end;
    [cells, rowspan, colspan, attributes] = cellfun(@(x) cell2cell(x, format, embed_numbers), ...
        matrix, 'UniformOutput', false);
    rowspan = cell2mat(rowspan);
    colspan = cell2mat(colspan);

    width = size(matrix, 2);
    height = size(matrix, 1);

    for h=1:height
        for w=1:width
            if rowspan(h, w) == 0 || colspan(h, w) == 0
                cells{h, w} = '';
            elseif rowspan(h, w) == 1 && colspan(h, w) == 1
                cells{h, w} = sprintf('<%s %s>%s</%s>', element, ...
                    attributes{h, w}, cells{h, w}, element);
            elseif rowspan(h, w) == 1
                cells{h, w} = sprintf('<%s colspan="%d" %s>%s</%s>', ...
                    element, colspan(h, w), attributes{h, w}, cells{h, w}, element);
            elseif colspan(h, w) == 1
                cells{h, w} = sprintf('<%s rowspan="%d" %s>%s</%s>', ...
                    element, rowspan(h, w), attributes{h, w}, cells{h, w}, element);
            else
                cells{h, w} = sprintf('<%s colspan="%d" rowspan="%d" %s>%s</%s>', ...
                    element, colspan(h, w), rowspan(h, w), attributes{h, w}, cells{h, w}, element);
            end;
        end
    end

%     max_width = max(sum(colspan));
%     max_height = max(sum(rowspan));
%
%     if max_width < width
%         cells = cells(:, 1:max_width);
%     end
%
%     if max_height < height
%         cells = cells(:, 1:max_height);
%     end

end

function [str, rowspan, colspan, cell_attributes] = cell2cell(s, format, embed_numbers)

    rowspan = 1;
    colspan = 1;

    cell_attributes = '';

    if isnumeric(s)
        str = num2str(s, format);
        if embed_numbers
            cell_attributes = [cell_attributes, sprintf(' data-numeric="%f" ', s)];
        end;
        return;
    elseif ~isstruct(s)
        str = s;
        return;
    end;

    if ~isfield(s, 'text')
        rowspan = 0;
        colspan = 0;
        str = [];
        return;
    end;

    if isfield(s, 'format')
        format = s.format;
    end;

    if isfield(s, 'columns')
        colspan = s.columns;
    end

    if isfield(s, 'rows')
        rowspan = s.rows;
    end

    if isnumeric(s.text)
        if embed_numbers
            cell_attributes = [cell_attributes, sprintf(' data-numeric="%f" ', s.text)];
        end;
        str = num2str(s.text, format);
    else
        str = s.text;
    end;

    element = 'span';
    attributes = '';

    if isfield(s, 'class')
        cell_attributes = [cell_attributes, ' class="', s.class, '" '];
    end

    if isfield(s, 'tooltip')
        attributes = [attributes, ' title="', s.tooltip, '" '];
    end

    if isfield(s, 'url')
        element = 'a';
        attributes = [attributes, ' href="', s.url, '" '];
    end

    if ~isempty(attributes)
       str = sprintf('<%s %s>%s</%s>', element, attributes, str, element);
    end

end


function title = p08_title ( )

%*****************************************************************************80
%
%% P08_TITLE returns a title for problem 8.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 October 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, string TITLE, a title for the problem.
%
  title = 'The Penalty Function #1.';

  return
end


function to_extract = find_node_indices(obj, varargin)
% Identify nodes to extract from brainpathway object given an integer
% vector of which nodes to select, cell array of strings for node names,
% or combination of the two. Returns a logical vector of nodes in set
%
% obj : a brainpathway object
%
% Optional inputs:
% a cell array of strings containing node names (matched to obj.node_labels)
% an integer vector of which nodes
%
% 'flatten' (not used here - would collapse atlas regions if used in select_atlas_regions)
%
% Outputs:
% to_extract: a logical

% -------------------------------------------------------------------------
% DEFAULTS AND INPUTS
% -------------------------------------------------------------------------

strings_to_find = [];
integers_to_find = [];
doflatten = false;

% optional inputs with default values
for i = 1:length(varargin)

    if iscell(varargin{i})
        strings_to_find = varargin{i};

    elseif isnumeric(varargin{i})
        integers_to_find = varargin{i};

    elseif ischar(varargin{i})
        switch varargin{i}

            case 'flatten', doflatten = true;

                %             case 'xxx', xxx = varargin{i+1}; varargin{i+1} = [];

            otherwise
                warning(['Unknown input string option:' varargin{i} '. Assuming it might be an atlas label. Place atlas labels in a cell array']);
                strings_to_find{1} = varargin{i};
        end
    end
end

% -------------------------------------------------------------------------
% INIT
% -------------------------------------------------------------------------

k = length(obj.region_indx_for_nodes); % size(obj.node_dat, 2);
to_extract = false(1, k);

% -------------------------------------------------------------------------
% FIND BY STRING
% -------------------------------------------------------------------------

for i = 1:length(strings_to_find)

    % Find which names match
    wh = ~cellfun(@isempty, strfind(obj.node_labels, strings_to_find{i}));

    to_extract = to_extract | wh;

end

% -------------------------------------------------------------------------
% FIND BY NUMBERS
% -------------------------------------------------------------------------

to_extract(integers_to_find) = true;

if ~any(to_extract)
    error('No nodes identified to extract.');
end

end % subfunction


function H= plot_scalpEvolutionPlusChannel(erp, mnt, clab, ival, varargin)
%PLOT_SCALPEVOLUTIONPLUSCHANNEL - Display evolution of scalp topographies
%
%Synposis:
% H= plot_scalpEvolutionPlusChannel(ERP, MNT, CLAB, IVAL, <OPTS>)
%
%Description:
% Makes an ERP plot in the upper panel with given interval marked,
% and draws below scalp topographies for all marked intervals,
% separately for each Class. For each Classes topographies are plotted
% in one row and shared the same Color map scaling. (In future versions
% there might be different options for Color scaling.)
%
%Input:
% ERP: struct of epoched EEG data.
% MNT: struct defining an electrode montage
% CLAB: label of the channel(s) which are to be displayed in the
%       ERP plot.
% IVAL: [nIvals x 2]-sized array of interval, which are marked in the
%       ERP plot and for which scalp topographies are drawn.
%       When all interval are consequtive, ival can also be a
%       vector of interval borders.
% OPTS: struct or property/value list of optional fields/properties:
%  .IvalColor  - [nColors x 3]-sized array of rgb-coded Colors
%                with are used to mark intervals and corresponding
%                scalps. Colors are cycled, i.e., there need not be
%                as many Colors as interval. Two are enough,
%                default [0.4 1 1; 1 0.6 1].
%  .LegendPos  - specifies the position of the legend in the ERP plot,
%                default 0 (see help of legend for choices).
%  .PrintIvalUnits - appends the unit when writing the ival borders,
%                default 1
%
%The opts struct is passed to plot_scalpPattern
%
%Output:
% H: struct of handles to the created graphic objects.
%
%See also plot_scalpEvolution, plot_scalpPatternsPlusChannel, plot_scalp.

% Author(s): Benjamin Blankertz, Jan 2005

props= {'ChannelAtBottom', 0,                 'BOOL';
        'FigureColor',     [1 1 1],           'DOUBLE[3]';
        'GlobalCLim',      0,                 'BOOL';
        'IvalColor',       [.4 1 1; 1 .6 1],  'DOUBLE[- 3]';
        'LegendPos',       'Best',            'CHAR'
        'LineWidth',       3,                 'DOUBLE[1]';
        'PlotChannel',     1,                 'BOOL';
        'PrintIval',       0,                 'BOOL';
        'PrintIvalUnits',  1,                 'BOOL';
        'ScalePos',        'vert',            'CHAR';
        'ShrinkColorbar',  0,                 'DOUBLE';
        'Subplot',         [],                'DOUBLE|GRAPHICS';
        'SubplotChannel',  [],                'DOUBLE|GRAPHICS';
        'XUnit',           'ms',            'CHAR';
        'YUnit',           '\muV',          'CHAR';
};

props_scalpPattern= plot_scalpPattern;
props_channel= plot_channel;

if nargin==0,
  H= opt_catProps(props, props_scalpPattern, props_channel);
  return
end

% With input argument erp, we know it better
if util_getDataDimension(erp)==1
  props_channel= plotutil_channel1D;
else
  props_channel= plotutil_channel2D;
end

opt= opt_proplistToStruct(varargin{:});
[opt, isdefault]= opt_setDefaults(opt, props);
opt_checkProplist(opt, props, props_scalpPattern, props_channel);

if isfield(erp, 'xUnit'),
  [opt,isdefault]= opt_overrideIfDefault(opt, isdefault, ...
                                         'XUnit', erp.xUnit);
end
if isfield(erp, 'yUnit'),
  [opt,isdefault]= opt_overrideIfDefault(opt, isdefault, ...
                                         'YUnit', erp.yUnit);
end

if isfield(opt, 'ColorOrder'),
  if isequal(opt.ColorOrder,'rainbow'),
    nChans= size(erp.y,1);
    opt.ColorOrder= hsv2rgb([(0.5:nChans)'/nChans ones(nChans,1)*[1 0.85]]);
%  else
%    if size(opt.ColorOrder,1)<size(erp.y,1),
%      opt.ColorOrder= repmat(opt.ColorOrder, [size(erp.y,1) 1]);
%    end
  end
else
  opt.ColorOrder= get(gca, 'ColorOrder');
end

opt_scalpPattern= opt_substruct(opt, props_scalpPattern(:,1));
opt_channel= opt_substruct(opt, props_channel(:,1));

[AxesStyle, dmy]= opt_extractPlotStyles(opt);

if max(sum(erp.y,2))>1,
  erp= proc_average(erp);
end

if size(ival,1)==1,
  ival= [ival(1:end-1)', ival(2:end)'];
end
if any(ival(:)>erp.t(end)),
  warning('interval out of epoch range: truncating');
  ival= min(ival, erp.t(end));
end
if any(ival(:)<erp.t(1)),
  warning('interval out of epoch range: truncating');
  ival= max(ival, erp.t(1));
end

nIvals= size(ival,1);
nColors= size(opt.IvalColor,1);
nClasses= length(erp.className);

mapCLim= zeros(2, nClasses, nIvals);
if opt.GlobalCLim,
  % determine common color range for all scalp maps
  commonCL= visutil_getCommonRange(erp, ival, 'CLim',opt_scalpPattern.CLim);
  mapCLim(1,:,:)= commonCL(1);
  mapCLim(2,:,:)= commonCL(2);
else
  if strcmp(opt.ScalePos, 'horiz'),
    % determine common color range for each interval
    for ii= 1:nIvals,
      commonCL= visutil_getCommonRange(erp, ival(ii,:), ...
                                       'CLim',opt_scalpPattern.CLim);
      mapCLim(1,:,ii)= commonCL(1);
      mapCLim(2,:,ii)= commonCL(2);
    end
  else
    % determine common color range for each class
    for cc= 1:nClasses,
      erp_cc= proc_selectClasses(erp, cc);
      commonCL= visutil_getCommonRange(erp_cc, ival, ...
                                       'CLim',opt_scalpPattern.CLim);
      mapCLim(1,cc,:)= commonCL(1);
      mapCLim(2,cc,:)= commonCL(2);
    end
  end
end

if isempty(opt.Subplot),
  clf;
end
set(gcf, 'Color',opt.FigureColor);

subplot_Offset= 0;
if opt.PlotChannel && ~isempty(clab),
  if ~isempty(opt.SubplotChannel),
    H.ax_erp= opt.SubplotChannel;
    axis_getQuietly(H.ax_erp);
  else
    if opt.ChannelAtBottom,
      H.ax_erp= subplotxl(1+nClasses, 1, 1+nClasses, ...
                          [0.1 0.05 0.1], [0.09 0 0.05]);
    else
      H.ax_erp= subplotxl(1+nClasses, 1, 1, 0.05, [0.09 0 0.05]);
      subplot_Offset= 1;
    end
  end
  if ~isempty(AxesStyle),
    set(H.ax_erp, AxesStyle{:});
  end
  hold on;   %% otherwise axis properties like ColorOrder are lost
  H.channel= plot_channel(erp, clab, opt_channel, 'Legend',0);
  for cc= 1:min(nColors,size(ival,1)),
    grid_markInterval(ival(cc:nColors:end,:), clab, opt.IvalColor(cc,:));
  end
  axis_redrawFrame(H.ax_erp);
  if ~isequal(opt.LegendPos, 'none'),
    if iscell(H.channel),
      hhh= H.channel{1};
    else
      hhh= H.channel;
    end
    % The following part can be removed. We do not allow numeric values
    % for LegendPos anymore.
    % Check matlab version for downward compatability
    if str2double(strtok(version,'.'))<7
      H.leg= legend(hhh.plot, erp.className, opt.LegendPos);
    else
      % check if LegendPos is integer
      if isnumeric(opt.LegendPos)
        switch(opt.LegendPos)
          case -1, loc = 'NorthEastOutside';
          case 0,  loc = 'Best';
          case 1,  loc = 'NorthEast';
          case 2,  loc = 'NorthWest';
          case 3,  loc = 'SouthWest';
          case 4,  loc = 'SouthEast';
          otherwise, loc = 'Best';
        end
        warning('Location numbers are obsolete, use "%s" instead of "%d"', ...
          loc,opt.LegendPos);
      else
        loc = opt.LegendPos;
      end
      H.leg= legend(hhh.plot, erp.className, 'Location',loc);
    end
  end
end

%if ~isempty(opt.Subplot),
%  opt.Subplot= reshape(opt.Subplot, [nClasses, nIvals]);
%end
cb_per_ival= strcmp(opt.ScalePos, 'horiz');
for cc= 1:nClasses,
  if ~any(any(erp.x(:,:,cc))),
    util_warning('empty_Class', sprintf('Class %d is empty', cc));
    continue;
  end
  for ii= 1:nIvals,
    if any(isnan(ival(ii,:))),
      continue;
    end
    if ~isempty(opt.Subplot),
      axis_getQuietly(opt.Subplot(cc, ii));
    else
      subplotxl(nClasses+opt.PlotChannel, nIvals, ...
                ii+(cc-1+subplot_Offset)*nIvals, ...
                [0.01+0.08*cb_per_ival 0.03 0.05], [0.05 0.02 0.1]);
    end
    opt_scalpPattern= setfield(opt_scalpPattern, 'ScalePos','none');
    opt_scalpPattern= setfield(opt_scalpPattern, 'Class',cc);
    H.scalp(cc,ii)= plot_scalpPattern(erp, mnt, ival(ii,:), ...
                           opt_scalpPattern, 'CLim',mapCLim(:,cc,ii));
    if cc==nClasses
      if opt.PrintIval,
        yLim= get(gca, 'yLim');
        if opt.PrintIvalUnits==2,
          ival_str= sprintf('%s - %s\n%s', num2str(ival(ii,1)), num2str(ival(ii,2)), opt.XUnit);
        elseif opt.PrintIvalUnits==1,
          ival_str= sprintf('%s - %s %s', num2str(ival(ii,1)), num2str(ival(ii,2)), opt.XUnit);
        else
          ival_str= sprintf('%s - %s', num2str(ival(ii,1)), num2str(ival(ii,2)));
        end;
        H.text_ival(ii)= text(mean(xlim), yLim(1)-0.04*diff(yLim), ival_str, ...
                              'verticalAli','top', 'horizontalAli','center');
      end
      if cb_per_ival,
        H.cb(ii)= plotutil_colorbarAside('horiz');
      end
    end
  end
  if strcmp(opt.ScalePos, 'vert'),
    H.cb(cc)= plotutil_colorbarAside;
    ylabel(H.cb(cc), ['[' opt.YUnit ']']);
    if opt.ShrinkColorbar>0,
      cbpos= get(H.cb(cc), 'Position');
      cbpos(2)= cbpos(2) + cbpos(4)*opt.ShrinkColorbar/2;
      cbpos(4)= cbpos(4) - cbpos(4)*opt.ShrinkColorbar;
      set(H.cb(cc), 'Position',cbpos);
    end
  end
  pos= get(H.scalp(cc,end).ax, 'position');
  yy= pos(2)+0.5*pos(4);
  H.background= visutil_getBackgroundAxis;
  H.text(cc)= text(0.01, yy, erp.className{cc});
  set(H.text(cc), 'verticalAli','top', ...
                  'horizontalAli','center', ...
                  'rotation',90, ...
                  'Visible','on', ...
                  'FontSize',12, ...
                  'fontWeight','bold');
  if isfield(opt, 'ColorOrder'),
    ccc= 1+mod(cc-1, size(opt.ColorOrder,1));
    set(H.text(cc), 'Color',opt.ColorOrder(ccc,:));
  end
end

if nargout<1,
  clear H
end


function model = findSExRxnInd(model, nRealMet, printLevel)
% Returns a model with boolean vectors indicating internal vs external (exchange/demand/sink) reactions.
% Finds the reactions in the model which export/import from the model boundary
%
% e.g. Exchange reactions,
% Demand reactions,
% Sink reactions
%
% USAGE:
%
%    model = findSExRxnInd(model, nRealMet, printLevel)
% model.SIntRxnBool         Boolean of reactions heuristically though to be mass balanced.
%
% INPUT:
%    model:         structure with:
%
%                     * S - m x n stoichiometric matrix
%
% OPTIONAL INPUT:
%    model:         structure with:
%                     * model.biomassRxnAbbr - abbreviation of biomass reaction
%    nRealMet:      specified in case extra rows in `S` which dont correspond to metabolties
%    printLevel:    verbose level
%
% OUTPUT:
%    model:         structure with:
%
%                     * .SIntRxnBool - Boolean of reactions heuristically though to be mass balanced.
%                     * .SIntMetBool - Boolean of metabolites heuristically though to be involved in mass balanced reactions.
%                     * .SOnlyIntMetBool - Boolean of metabolites heuristically though only to be involved in mass balanced reactions.
%                     * .SExMetBool - Boolean of metabolites heuristically though to be involved in mass imbalanced reactions.
%                     * .SOnlyExMetBool - Boolean of metabolites heuristically though only to be involved in mass imbalanced reactions.
%                     * .biomassBool - Boolean of biomass reaction
%                     * .DMRxnBool - Boolean of demand reactions. Prefix `DM_` (optional field)
%                     * .SinkRxnBool - Boolean of sink reactions. Prefix `sink_` (optional field)
%                     * .ExchRxnBool - Boolean of exchange reactions. Prefix `EX_` or `Exch_` or `Ex_` (optional field)
%
% .. Author: -  Ronan Fleming

if ~exist('printLevel','var')
    printLevel=0;
end

[nMet,nRxn]=size(model.S);

if ~exist('nRealMet','var')
    nRealMet=length(model.mets);
    if nMet~=nRealMet
        if printLevel>0
            fprintf('%s\n','Detected extra rows of S without corresponding metabolite abbreviations.')
        end
    end
else
    if isempty(nRealMet)
        nRealMet=length(model.mets);
    end
end

%locate biomass reaction if there is one
biomassBool=false(nRxn,1);
if ~isfield(model,'c')
    model.c=zeros(nMet,1);
end
if ~isfield(model,'biomassRxnAbbr')
    bool=model.c~=0;
    if nnz(bool)==1
        model.biomassRxnAbbr=model.rxns{model.c~=0};
        if printLevel>0
            fprintf('%s%s\n','Assuming biomass reaction is: ', model.biomassRxnAbbr);
        end
        biomassBool(bool)=1;
    else
        if nnz(bool)==0
            if printLevel>0
                fprintf('%s\n','No model.biomassRxnAbbr? Give abbreviation of biomass reaction if there is one.');
            end
        else
            warning('More than one biomass reaction?');
        end
    end
else
    biomassBool=contains(model.rxns,model.biomassRxnAbbr);%finds a subset of the abbreviation
    if any(biomassBool)
        if nnz(biomassBool)>1
            ind = find(biomassBool);
            for p=1:length(ind)
                if printLevel>0
                    fprintf('%s%s\n','Found multiple possible biomass reactions: ', model.rxns{ind(p)});
                end
            end
        else
            fprintf('%s%s\n','Found biomass reaction: ', model.rxns{biomassBool});
        end
    else
        if printLevel>0
            fprintf('%s\n','Assuming no biomass reaction.');
        end
    end
end

%grab any possible biomass reactions
biomassBool = biomassBool | contains(model.rxns,'biomass');
biomassBool = biomassBool | contains(model.rxns,'Biomass');

model.biomassBool=biomassBool;

SExRxnBoolOneCoefficient=false(nRxn,1);
for n=1:nRxn
    %find reactions with only one coefficient
    %or no coefficient at all - Ronan May 29th 2011
    if nnz(model.S(1:nRealMet,n))<=1
        SExRxnBoolOneCoefficient(n,1)=1;
        if printLevel>2
            if nonzeros(model.S(1:nRealMet,n))>0
                fprintf('%s\t%s\n','Positive coefficient:',model.rxns{n});
            else
                fprintf('%s\t%s\n','Negative coefficient:',model.rxns{n});
                %                 fprintf('%s%s%s%s%s\n','''',model.rxns{n},''',0 ,0 ''',model.mets{find(model.S(1:nRealMet,n)~=0)},''',0 ,0 ;');
            end
        end
    end
end

% models with typical HMR subsystems - heuristic
if isfield(model,'subSystems')
    model.ExchRxnBool=cellfun(@(x) any(ismember({'Exchange reactions','Artificial reactions','Pool reactions'},x)),model.subSystems);
    if isfield(model,'rxnComps')
        model.ExchRxnBool=model.ExchRxnBool | strcmp('x',model.rxnComps);
    end
    % models with typical COBRA abbreviations - heuristic
    model.ExchRxnBool=strncmp('EX_', model.rxns, 3)==1 | strncmp('Exch_', model.rxns, 5)==1 | strncmp('Ex_', model.rxns, 5)==1 | biomassBool | model.ExchRxnBool;
else
    % models with typical COBRA abbreviations - heuristic
    model.ExchRxnBool=strncmp('EX_', model.rxns, 3)==1 | strncmp('Exch_', model.rxns, 5)==1 | strncmp('Ex_', model.rxns, 5)==1 | biomassBool;
end
%demand reactions going out of model
model.DMRxnBool=strncmp('DM_', model.rxns, 3)==1;
%sink reactions going into or out of model
model.SinkRxnBool=strncmp('sink_', model.rxns, 5) | strncmp('Sink_', model.rxns, 5)==1;

%input/output
SExRxnBoolHeuristic = model.ExchRxnBool | model.DMRxnBool | model.SinkRxnBool;

%remove ATP demand as it is usually mass balanced
bool=strcmp('ATPM',model.rxns);
if any(bool)
    if printLevel>0
        fprintf('%s\n','ATP maintenance reaction is not considered an exchange reaction by default. It should be mass balanced:')
        formulas = printRxnFormula(model,{'ATPM'});
    end
    model.DMRxnBool(bool)=0;
end
bool=strcmp('DM_atp(c)',model.rxns);
if any(bool)
    if printLevel>0
        fprintf('%s\n','ATP demand reaction is not considered an exchange reaction by default. It should be mass balanced')
        formulas = printRxnFormula(model,{'DM_atp(c)'});
    end
    model.DMRxnBool(bool)=0;
end
bool=strcmp('DM_atp_c_',model.rxns);
if any(bool)
    if printLevel>0
        fprintf('%s\n','ATP demand reaction is not considered an exchange reaction by default. It should be mass balanced:')
        formulas = printRxnFormula(model,{'DM_atp_c_'});
    end
    model.DMRxnBool(bool)=0;
end
%remove atp demand
SExRxnBoolHeuristic(bool)=0;

diffBool= ~SExRxnBoolHeuristic & SExRxnBoolOneCoefficient;
if any(diffBool)
    if printLevel>0
        fprintf('%s\n','Exchanges that would otherwise have been missed without abbreviation prefix search:')
        fprintf('%s\t%s\t%s\t\t%s\t\t%s\n','Coefficient','Metabolite','#','Reaction','#')
    end
    for n=1:nRxn
        if diffBool(n)
            objMetInd=find(model.S(:,n));
            for m=1:length(objMetInd)
                Sij=full(model.S(objMetInd(m),n));
                if length(model.mets{objMetInd(m)})<4
                    if printLevel>0
                        fprintf('%g\t\t\t%s\t\t\t%i\t%s\t\t%i\n',Sij,model.mets{objMetInd(m)},objMetInd(m),model.rxns{n},n)
                    end
                else
                    if length(model.mets{objMetInd(m)})<8
                        if printLevel>0
                            fprintf('%g\t\t\t%s\t\t%i\t%s\t\t%i\n',Sij,model.mets{objMetInd(m)},objMetInd(m),model.rxns{n},n)
                        end
                    else
                        if length(model.mets{objMetInd(m)})<12
                            if printLevel>0
                                fprintf('%g\t\t\t%s\t%i\t%s\t\t%i\n',Sij,model.mets{objMetInd(m)},objMetInd(m),model.rxns{n},n)
                            end
                        end
                    end
                end
            end
        end
    end
end

% %dont check if there are coupling constraints
% %(E. coli E matrix specific)
% if ~isfield(model,'A')
%     diffBool= SExRxnBoolHeuristic & ~SExRxnBoolOneCoefficient;
%     if any(diffBool)
%         if printLevel>0
%             fprintf('%s\n','Exchanges missed by prefix search:')
%             fprintf('%s\t%s\n','#', 'Exchange')
%         end
%         for n=1:length(diffBool)
%             if diffBool(n)
%                 equation=printRxnFormula(model,model.rxns(n),0);
%                 if printLevel>0
%                     fprintf('%i\t%s\t%s\n',n,model.rxns{n},equation{1});
%                 end
%             end
%         end
%     end
% end

%amalagamate all exchanges
SExRxnBool= SExRxnBoolHeuristic | SExRxnBoolOneCoefficient;
model.SIntRxnBool=~SExRxnBool;
%rows corresponding to internal reactions
boolMet=true(nMet,1);
%first pair
model.SIntMetBool = getCorrespondingRows(model.S,boolMet,model.SIntRxnBool,'inclusive');
model.SOnlyExMetBool = getCorrespondingRows(model.S,boolMet,~model.SIntRxnBool,'exclusive');
%second pair
model.SOnlyIntMetBool = getCorrespondingRows(model.S,boolMet,model.SIntRxnBool,'exclusive');
model.SExMetBool = getCorrespondingRows(model.S,boolMet,~model.SIntRxnBool,'inclusive');
%sanity check
if nnz(model.SIntMetBool)+nnz(model.SOnlyExMetBool) ~= nnz(model.SIntMetBool)+nnz(model.SOnlyExMetBool)
    error('Inconsistency in metabolite counts')
end


function F = conj(F)
%CONJ   Complex conjugate of a CHEBFUN3V.
%   CONJ(F) returns the complex conjugate of F. For a complex F, we have
%   CONJ(F) = REAL(F) - i*IMAG(F).
%
% See also CHEBFUN3V/REAL and CHEBFUN3V/IMAG.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% Empty check:
if ( isempty(F) )
    return
end

% Take conj part of each component:
F.components = cellfun(@conj, F.components, 'UniformOutput', false);

end


function y = istrue(x)

% ISTRUE ensures that a true/false input argument like "yes", "true"
% or "on" is converted into a boolean

% Copyright (C) 2009, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id: istrue.m 2885 2011-02-16 09:41:58Z roboos $

true_list  = {'yes' 'true' 'on' 'y' };
false_list = {'no' 'false' 'off' 'n' 'none'};

if ischar(x)
  % convert string to boolean value
  if any(strcmpi(x, true_list))
    y = true;
  elseif any(strcmpi(x, false_list))
    y = false;
  else
    error('cannot determine whether "%s" should be interpreted as true or false', x);
  end
else
  % convert numerical value to boolean
  y = logical(x);
end


% Copyright 2019 Jonas Koenemann, Moritz Diehl, University of Freiburg
% Redistribution is permitted under the 3-Clause BSD License terms. Please
% ensure the above copyright notice is visible in any derived work.
%
function stairs(x, y, varargin)
  ocl.utils.checkStartup()

  x = ocl.Variable.getValue(x);
  y = ocl.Variable.getValue(y);

  stairs(x,y,'LineWidth', 3, varargin{:})
end


%DRAWCHARUCOBOARD  Draw a ChArUco board
%
%     img = cv.drawCharucoBoard(board, outSize)
%     img = cv.drawCharucoBoard(..., 'OptionName',optionValue, ...)
%
% ## Input
% * __board__ ChArUco board that will be drawn.
% * __outSize__ size of the output image in pixels `[w,h]`.
%
% ## Output
% * __img__ output image with the board. The size of this image will be
%   `outSize` and the board will be on the center, keeping the board
%   proportions.
%
% ## Options
% * __MarginSize__ minimum margins (in pixels) of the board in the output
%   image. default 0
% * __BorderBits__ width of the marker borders. default 1
%
% This function return the image of the ChArUco board, ready to be printed.
%
% See also: cv.estimatePoseCharucoBoard, cv.drawPlanarBoard, cv.drawMarkerAruco
%


function value = p37_param ( action, name, value )

%*****************************************************************************80
%
%% P37_PARAM defaults, sets, or gets the parameters for problem 37.
%
%  Discussion:
%
%    In typical use, the user calls
%      p37_param ( 'DEFAULT' )
%    Then, once the variables have been given default values, any
%    value can be retrieved, as for example by:
%      value = p37_param ( 'GET', 'A' )
%    or set to a new value, as in:
%      p37_param ( 'SET', 'A', 2.0 )
%
%    A is the amplitude on the forcing term;
%    K is the damping coefficient.
%    W is the frequency coefficient on the forcing term;
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 March 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string ACTION:
%    'DEFAULT' sets the variables to default values.
%    'SET' sets the variable chosen by NAME to have the value VALUE.
%    'GET' gets the variable chosen by NAME.
%
%    Input, string NAME, the name of the variable, which should
%    be 'A', 'K', or 'W'.  NAME is ignored if the ACTION is 'DEFAULT'.
%
%    Input, real VALUE, the value to be assigned the variable NAME,
%    if the value of ACTION was 'SET'.  Otherwise VALUE is ignored.
%
%    Output, real VALUE, depends on the input value of ACTION:
%    'DEFAULT', returns the number of variables;
%    'SET', returns the input value of VALUE;
%    'GET', returns the value of the variable NAME.
%
  persistent a;
  persistent k;
  persistent w;

  if ( s_eqi ( action, 'DEFAULT' ) )

    a = 0.3;
    k = 0.2;
    w = 1.0;

    value = 3;

  elseif ( s_eqi ( action, 'SET' ) )

    if ( s_eqi ( name, 'A' ) )
      a = value;
    elseif ( s_eqi ( name, 'K' ) )
      k = value;
    elseif ( s_eqi ( name, 'W' ) )
      w = value;
    else
      fprintf ( 1, '\n' );
      fprintf ( 1, 'P37_PARAM - Fatal error!\n' );
      fprintf ( 1, '  Unrecognized variable name: "%s".\n', name );
      error ( 'P37_PARAM - Fatal error!' );
    end

  elseif ( s_eqi ( action, 'GET' ) )

    if ( s_eqi ( name, 'A' ) )
      value = a;
    elseif ( s_eqi ( name, 'K' ) )
      value = k;
    elseif ( s_eqi ( name, 'W' ) )
      value = w;
    else
      fprintf ( 1, '\n' );
      fprintf ( 1, 'P37_PARAM - Fatal error!\n' );
      fprintf ( 1, '  Unrecognized variable name: "%s".\n', name );
      error ( 'P37_PARAM - Fatal error!' );
    end

  else

    fprintf ( 1, '\n' );
    fprintf ( 1, 'P37_PARAM - Fatal error!\n' );
    fprintf ( 1, '  Unrecognized action: "%s".\n', action );
    error ( 'P37_PARAM - Fatal error!' );

  end

  return
end


function [params, names] = linard2KernExtractParam(kern)

% LINARD2KERNEXTRACTPARAM Extract parameters from the LINARD2 kernel structure.
% FORMAT
% DESC Extract parameters from the automatic relevance
% determination linear kernel structure into a vector of parameters
% for optimisation.
% ARG kern : the kernel structure containing the parameters to be
% extracted.
% RETURN param : vector of parameters extracted from the kernel. If
% the field 'transforms' is not empty in the kernel matrix, the
% parameters will be transformed before optimisation (for example
% positive only parameters could be logged before being returned).
%
% FORMAT
% DESC Extract parameters and parameter names from the automatic relevance
% determination linear kernel structure.
% ARG kern : the kernel structure containing the parameters to be
% extracted.
% RETURN param : vector of parameters extracted from the kernel. If
% the field 'transforms' is not empty in the kernel matrix, the
% parameters will be transformed before optimisation (for example
% positive only parameters could be logged before being returned).
% RETURN names : cell array of strings containing parameter names.
%
% SEEALSO linard2KernParamInit, linard2KernExpandParam, kernExtractParam, scg, conjgrad
%
% COPYRIGHT : Neil D. Lawrence, 2004, 2005, 2006
%
% COPYRIGHT : Michalis K. Titsias, 2009

% KERN

params = [kern.inputScales];
if nargout > 1
  %names = {'variance'};
  for i = 1:length(kern.inputScales)
    names{i} = ['input scale ' num2str(i)];
  end
end


state= acquire_bv(100, 'localhost');
while 1,
  [dmy,bn,mp,md,mt]= acquire_bv(state);
  for mm= 1:length(mt),
    %nowstr= datestr(now,31);
    %fprintf('marker %s at %s\n', md{mm}, nowstr);
    fprintf('marker %s at %d\n', md{mm}, bn+mp(mm));
  end
end
acquire_bv('close');


classdef PTKROIDividedIntoLeftAndRight < PTKPlugin
    % PTKROIDividedIntoLeftAndRight. Plugin to divide the roi region into left and right
    %
    %     This is a plugin for the Pulmonary Toolkit. Plugins can be run using
    %     the gui, or through the interfaces provided by the Pulmonary Toolkit.
    %     See PTKPlugin.m for more information on how to run plugins.
    %
    %     Plugins should not be run directly from your code.
    %
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2012.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    properties
        ButtonText = 'Left and <br>Right ROI'
        ToolTip = 'Separate and label left and right lungs'
        Category = 'Lungs'

        AllowResultsToBeCached = true
        AlwaysRunPlugin = false
        PluginType = 'ReplaceOverlay'
        HidePluginInDisplay = false
        FlattenPreviewImage = false
        PTKVersion = '1'
        ButtonWidth = 6
        ButtonHeight = 2
        GeneratePreview = true
        Visibility = 'Developer'
    end

    methods (Static)
        function results = RunPlugin(dataset, reporting)
            results = dataset.GetResult('PTKLeftAndRightLungs');
            [~, nn_index] = bwdist(results.RawImage > 0);
            results_raw = results.RawImage(nn_index);
            results.ChangeRawImage(results_raw);
        end
    end
end


function [dset] = cell2dataset(inputData)
    dset = dataset();
    if (~isfield(inputData, 'data'))
        error('[cell2dataset] input dataset structure has no ".data" field');
    end
    if (~isfield(inputData, 'columnnames'))
        error('[cell2dataset] input dataset structure has no ".columnnames" field');
    end

    for i = 1:size(inputData.columnnames,2)
        if(isnumeric(inputData.data{1,i}))
            if(isempty(dset))
                dset = dataset({cell2mat(inputData.data(:,i)),cell2mat(inputData.columnnames(i))});
            else
                dset = [dset dataset({cell2mat(inputData.data(:,i)),cell2mat(inputData.columnnames(i))})];
            end
            disp('numeric')
        else
            if(isempty(dset))
                dset = dataset({inputData.data(:,i),cell2mat(inputData.columnnames(i))});
            else
                dset = [dset dataset({inputData.data(:,i),cell2mat(inputData.columnnames(i))})];
            end
            disp('other')
        end
    end
end


function r = issparse(c)
%ISSPARSE     Returns 1 if c is sparse
%
%  r = issparse(c);
%

% written  10/16/98     S.M. Rump
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
%

  if c.complex
    r = issparse(c.mid);
  else
    r = issparse(c.inf);
  end


function A = uplus(A)
%UPLUS        Long unary plus  +A
%
%

% written  12/30/98     S.M. Rump
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
%


function nav=uniqgeph(nav)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Copyright(c) 2020-2025, by Kai Chen, All rights reserved.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
global gls;
geph0=nav.geph;
A=zeros(nav.ng,3);
geph1=repmat(gls.geph,nav.ng,1);

%sort geph
for i=1:nav.ng
    A(i,:)=[geph0(i).tof.time,geph0(i).toe.time,geph0(i).sat];
end
[~,index]=sortrows(A);
for i=1:nav.ng
    geph1(i)=geph0(index(i));
end
clear geph0;

%unique geph
j=1;
for i=2:nav.ng
    if geph1(i).sat~=geph1(j).sat||geph1(i).toe.time~=geph1(j).toe.time||geph1(i).svh~=geph1(j).svh
        j=j+1;
        geph1(j)=geph1(i);
    end
end

nav.ng=j;
geph2=repmat(gls.geph,nav.ng,1);
for i=1:nav.ng
    geph2(i)=geph1(i);
end
clear geph1;

nav=rmfield(nav,'geph');
nav.geph=geph2;

return


function [data] = convertSeperateTsToArrayTs(debug_slow)
% Author: Salih Guemues     Date: 06-06-2020
%
% Description:
%   merges the set of timeseries of scalars belonging to array dimensional
%   signal from the logs resulting from the Scope Debugging
%   mechanism of Simulink. The output is a struct including a set of timeseries.
%
% Input:
%   debug_slow:    Log data struct, with vector-signals being seperated in
%                  to scalar timeseries
% Output:
%   data:          Struct with all timeseries in there (merged vectors)

% define struct for output
data = struct();
% get signal names of logs
names = fieldnames(debug_slow);
same_signal = 0;
for i=1:1:numel(names)
    % check if last charakter of fieldname is a number (--> array signal)
    if isnan(str2double(names{i}(end)))
        % last charakter not a number, scalar signal can be copied
        % extend signal name by "slow" for the output-struct
        data.(insertAfter(names{i},"debug_","slow_")) = debug_slow.(names{i});
        same_signal = 0;
    else
        % last charakter is number --> array signal has to be merged
        % if next entry does not belong to same signal (same_signal==0) or
        % if current entry is first array-signal-entry, create new
        % struct-entry corresponding to the array-signal
        if ~same_signal
            % get signal name without increment (get "a" instead of "a_1")
            tmp_name = names{i}(1:end-2);
            len_tmp_name = numel(tmp_name);
            % extend signal name by "slow" for the output-struct
            tmp_name_slow = insertAfter(tmp_name,"debug_","slow_");
            tmp_TS = debug_slow.(names{i});
            tmp_TS.name = tmp_name_slow;    % rename timeseries to array-signal-name
            data.(tmp_name_slow) = tmp_TS;  % store timeseries in output
        else
            % concatenate signals back to array and store in output-struct
            data.(tmp_name_slow).Data = [data.(tmp_name_slow).Data, debug_slow.(names{i}).Data(:)];
        end
        if i<(numel(names)-same_signal)
            % get signal-name of next logged signal
            tmp_name_next = names{i+1}(1:end-2);
            len_tmp_name_next = numel(tmp_name_next);
            % check if next signal-name is shorter, if yes, not same signal
            if len_tmp_name > len_tmp_name_next
                same_signal = 0;
            elseif strcmp(names{i}(1:len_tmp_name), names{i+1}(1:len_tmp_name))
            % if next signal-name is equal to current -> belongs to same
            % array-signal (check necessary, since two array signals with
            % the same name-length could have been logged in succession)
            % e.g. a_1; a_2; a_3; b_1; b_2; b_3
                same_signal = 1;
            else
                same_signal = 0;
            end
        end
    end
end
end


function [lat,lon] = importPlates(filename, startRow, endRow)
%IMPORTPLATES Import numeric data from a text file as column vectors.
%   [LAT,LON] = IMPORTPLATES(FILENAME) Reads data from text file FILENAME for
%   the default selection.
%
%   [LAT,LON] = IMPORTPLATES(FILENAME, STARTROW, ENDROW) Reads data from rows
%   STARTROW through ENDROW of text file FILENAME.
%
% Example:
%   [lat,lon] = importPlates('All_boundaries.txt',2, 12377);
%
%    See also TEXTSCAN.

% Auto-generated by MATLAB on 2015/01/23 11:51:24

%% Initialize variables.
if nargin<=2
    startRow = 2;
    endRow = inf;
end

%% Read columns of data as strings:
% For more information, see the TEXTSCAN documentation.
formatSpec = '%9s%s%[^\n\r]';

%% Open the text file.
fileID = fopen(filename,'r');

%% Read columns of data according to format string.
% This call is based on the structure of the file used to generate this
% code. If an error occurs for a different file, try regenerating the code
% from the Import Tool.
dataArray = textscan(fileID, formatSpec, endRow(1)-startRow(1)+1, 'Delimiter', '', 'WhiteSpace', '', 'HeaderLines', startRow(1)-1, 'ReturnOnError', false);
for block=2:length(startRow)
    frewind(fileID);
    dataArrayBlock = textscan(fileID, formatSpec, endRow(block)-startRow(block)+1, 'Delimiter', '', 'WhiteSpace', '', 'HeaderLines', startRow(block)-1, 'ReturnOnError', false);
    for col=1:length(dataArray)
        dataArray{col} = [dataArray{col};dataArrayBlock{col}];
    end
end

%% Close the text file.
fclose(fileID);

%% Convert the contents of columns containing numeric strings to numbers.
% Replace non-numeric strings with NaN.
raw = repmat({''},length(dataArray{1}),length(dataArray)-1);
for col=1:length(dataArray)-1
    raw(1:length(dataArray{col}),col) = dataArray{col};
end
numericData = NaN(size(dataArray{1},1),size(dataArray,2));

for col=[1,2]
    % Converts strings in the input cell array to numbers. Replaced non-numeric
    % strings with NaN.
    rawData = dataArray{col};
    for row=1:size(rawData, 1);
        % Create a regular expression to detect and remove non-numeric prefixes and
        % suffixes.
        regexstr = '(?<prefix>.*?)(?<numbers>([-]*(\d+[\,]*)+[\.]{0,1}\d*[eEdD]{0,1}[-+]*\d*[i]{0,1})|([-]*(\d+[\,]*)*[\.]{1,1}\d+[eEdD]{0,1}[-+]*\d*[i]{0,1}))(?<suffix>.*)';
        try
            result = regexp(rawData{row}, regexstr, 'names');
            numbers = result.numbers;

            % Detected commas in non-thousand locations.
            invalidThousandsSeparator = false;
            if any(numbers==',');
                thousandsRegExp = '^\d+?(\,\d{3})*\.{0,1}\d*$';
                if isempty(regexp(thousandsRegExp, ',', 'once'));
                    numbers = NaN;
                    invalidThousandsSeparator = true;
                end
            end
            % Convert numeric strings to numbers.
            if ~invalidThousandsSeparator;
                numbers = textscan(strrep(numbers, ',', ''), '%f');
                numericData(row, col) = numbers{1};
                raw{row, col} = numbers{1};
            end
        catch me
        end
    end
end

%% Replace non-numeric cells with NaN
R = cellfun(@(x) ~isnumeric(x) && ~islogical(x),raw); % Find non-numeric cells
raw(R) = {NaN}; % Replace non-numeric cells

%% Allocate imported array to column variable names
lat = cell2mat(raw(:, 1));
lon = cell2mat(raw(:, 2));


function s = nnz( x )

%   Disciplined convex/geometric programming information for NNZ:
%      When used in CVX models, NNZ cannot deduce the numeric value of a
%      CVX variable, so it returns the number of "structurally" nonzero
%      elements; i.e., those that are not *identically* zero. This is
%      similar to the concept of structural nonzeros in sparse matrix
%      factorizations. To illustrate the distinction, consider:
%         variable x(3);
%         x(2) == 0;
%         y = [x(1);0;x(3)];
%      In this case, NNZ(x) returns 3, even though x(2) has been set to
%      zero in an equality constraint. (After all, the overall model may
%      be infeasible, in which case x(2) is arguably not zero.) However,
%      NNZ(y) returns 2, because y(2) is identically zero.

s = nnz( any( x.basis_, 1 ) );

% Copyright 2005-2014 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function [grad, elec] = mne2grad(hdr, dewar, coilaccuracy)

% MNE2GRAD converts a header from a fif file that was read using the MNE toolbox into
% a gradiometer structure that can be understood by the FieldTrip low-level forward
% and inverse routines.
%
% Use as
%   [grad, elec] = mne2grad(hdr, dewar, coilaccuracy)
% where
%   dewar        = boolean, whether to return it in dewar or head coordinates (default = false, i.e. head coordinates)
%   coilaccuracy = empty or a number (default = [])
%
% See also CTF2GRAD, BTI2GRAD

%%%%%%%%%%%%%%%%%% BEGIN REVISION HISTORY %%%%%%%%%%%%%%%%%%
%
% Robert Oostenveld 22/01/2016 reimplemented construction of integration
% points on basis of coil_def.dat file from MNE
%
% Laurence Hunt 03/12/2008 (with thanks to Joachim Gross's original script
% based on fiff_access). lhunt@fmrib.ox.ac.uk
%
% Teresa Cheung 09/24/2011 revision to Laurence Hunt's script. The coil
% geometry has been revised to better reflect the coil dimensions of the
% Vectorview (306) planar gradiometers and magnetometers. Coil geometry for
% the Neuromag-122 planar gradiometer is different and is not read with
% this script (coil_type should equal 2)
%
%%%%%%%%%%%%%%%%%% END REVISION HISTORY %%%%%%%%%%%%%%%%%%

% Copyrights (C) 2016, Robert Oostenveld
% Copyrights (C) 2011, Teresa Cheung
% Copyrights (C) 2008, Laurence Hunt
% Copyrights (C) 2005, Joachim Gross
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
% FieldTrip is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% FieldTrip is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

if nargin<2 || isempty(dewar)
  dewar = false;
end

if nargin<3 || isempty(coilaccuracy)
  % if empty it will use the original code
  % otherwise it will use the specified accuracy coil definition from the MNE coil_def.dat
  coilaccuracy = [];
end

% orig = fiff_read_meas_info(filename);
% orig = fiff_setup_read_raw(filename);

if isfield(hdr, 'orig')
  orig = hdr.orig; % use the original MNE header, not the FieldTrip header
else
  orig = hdr; % assume that it is the original header
end

% start with empty gradiometer definition
grad = [];

% start with empty electrode definition
elec = [];

% begin by transforming all channel locations into the desired coordinate system, if possible
if ~dewar
  if ~isempty(orig.dev_head_t)
    orig.chs = fiff_transform_meg_chs(orig.chs,orig.dev_head_t);
    orig.chs = fiff_transform_eeg_chs(orig.chs,orig.dev_head_t); % EEG channels are normally stored in head coordinates anyway, but what the heck
  else
    ft_warning('No device to head transform available in fif file');
    ft_warning('MEG channels will likely have coordinates in device frame, not head frame');
  end
else
  if ~isempty(orig.dev_head_t)
    % compute the transformation from head to device
    orig.head_dev_t.trans = inv(orig.dev_head_t.trans);
    orig.head_dev_t.from  = orig.dev_head_t.to;
    orig.head_dev_t.to    = orig.dev_head_t.from;
    orig.chs = fiff_transform_meg_chs(orig.chs,orig.head_dev_t); % MEG channels are normally stored in dewar coordinates anyway, but what the heck
    orig.chs = fiff_transform_eeg_chs(orig.chs,orig.head_dev_t);
  else
    ft_warning('No device to head transform available in fif file');
    ft_warning('EEG channels will likely have coordinates in head frame, not device frame');
  end
end

if ~isempty(coilaccuracy)
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % use the coil definitions from the MNE coil_def.dat file
  % these allow for varying accuracy which is specified by
  % coilaccuracy = 0, 1 or 2
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  ft_hastoolbox('mne', 1);
  [ftver, ftpath] = ft_version;
  def = mne_load_coil_def(fullfile(ftpath, 'external', 'mne', 'coil_def.dat'));

  k = 1;

  grad.chanpos = nan(length(orig.chs),3);
  grad.chanori = nan(length(orig.chs),3);
  grad.label = cell(length(orig.chs),1);
  grad.tra      = nan(length(orig.chs),0);
  grad.chantype = repmat({'unknown'}, size(grad.label));
  grad.chanunit = repmat({'unknown'}, size(grad.label));

  for i=1:length(orig.chs)
    thisdef = def([def.id]==orig.chs(i).coil_type & [def.accuracy]==coilaccuracy);
    if isempty(thisdef)
      continue;
    end
    weight = thisdef.coildefs(:,1);
    pos = thisdef.coildefs(:,2:4);
    ori = thisdef.coildefs(:,5:7);
    H = orig.chs(i).coil_trans;
    pos = ft_warp_apply(H, pos);
    T = H;
    R = H;
    T(1:3,1:3) = 0; % remove the rotation, keep the translation
    R(1:3,4)   = 0; % remove the translation, keep the rotation
    ori = ft_warp_apply(R, ori); % only apply the rotation
    for j=1:thisdef.num_points
      grad.coilpos(k,:) = pos(j,:);
      grad.coilori(k,:) = ori(j,:);
      grad.tra(i,k)     = weight(j);
      k = k + 1;
    end
    grad.label{i} = orig.ch_names{i};
    grad.chanpos(i,:) = T(1:3,4);
    grad.chanori(i,:) = ft_warp_apply(R, [0 0 1]);
  end

  grad.label = grad.label(:);
  grad.unit  = 'm'; % the coil_def.dat file is in meter

  % all the chs.kinds and chs.coil_types are obtained from the MNE manual, p.210-211
  for sel=find([orig.chs.kind]==1 & [orig.chs.coil_type]==2)' % planar gradiometers
    grad.chantype(sel) = {'megplanar'}; %Neuromag-122 planar gradiometer
  end
  for sel=find([orig.chs.kind]==1 & [orig.chs.coil_type]==3012)' %planar gradiometers
    grad.chantype(sel) = {'megplanar'}; %Type T1 planar grad
  end
  for sel=find([orig.chs.kind]==1 & [orig.chs.coil_type]==3013)' %planar gradiometers
    grad.chantype(sel) = {'megplanar'}; %Type T2 planar grad
  end
  for sel=find([orig.chs.kind]==1 & [orig.chs.coil_type]==3014)' %planar gradiometers
    grad.chantype(sel) = {'megplanar'}; %Type T3 planar grad
  end
  for sel=find([orig.chs.kind]==1 & [orig.chs.coil_type]==3022)' %magnetometers
    grad.chantype(sel) = {'megmag'};    %Type T1 magenetometer
  end
  for sel=find([orig.chs.kind]==1 & [orig.chs.coil_type]==3023)' %magnetometers
    grad.chantype(sel) = {'megmag'};    %Type T2 magenetometer
  end
  for sel=find([orig.chs.kind]==1 & [orig.chs.coil_type]==3024)' %magnetometers
    grad.chantype(sel) = {'megmag'};    %Type T3 magenetometer
  end
  for sel=find([orig.chs.kind]==1 & [orig.chs.coil_type]==7001)' %axial gradiometer
    grad.chantype(sel) = {'megaxial'};
  end
  for sel=find([orig.chs.kind]==301)' %MEG reference channel, located far from head
    grad.chantype(sel) = {'ref'};
  end
  for sel=find([orig.chs.kind]==2)'   %EEG channels
    grad.chantype(sel) = {'eeg'};
  end
  for sel=find([orig.chs.kind]==201)' %MCG channels
    grad.chantype(sel) = {'mcg'};
  end
  for sel=find([orig.chs.kind]==3)' %Stim channels
    if any(ismember([orig.chs(sel).logno], [101 102])) % new systems: 101 (and 102, if enabled) are digital; low numbers are 'pseudo-analog' (if enabled)
      grad.chantype(sel([orig.chs(sel).logno] == 101)) = {'digital trigger'};
      grad.chantype(sel([orig.chs(sel).logno] == 102)) = {'digital trigger'};
      grad.chantype(sel([orig.chs(sel).logno] <= 32))  = {'analog trigger'};
      others = [orig.chs(sel).logno] > 32 & [orig.chs(sel).logno] ~= 101 & ...
        [orig.chs(sel).logno] ~= 102;
      grad.chantype(sel(others)) = {'other trigger'};
    elseif any(ismember([orig.chs(sel).logno], [14 15 16])) % older systems: STI 014/015/016 are digital; lower numbers 'pseudo-analog'(if enabled)
      grad.chantype(sel([orig.chs(sel).logno] == 14)) = {'digital trigger'};
      grad.chantype(sel([orig.chs(sel).logno] == 15)) = {'digital trigger'};
      grad.chantype(sel([orig.chs(sel).logno] == 16)) = {'digital trigger'};
      grad.chantype(sel([orig.chs(sel).logno] <= 13)) = {'analog trigger'};
      others = [orig.chs(sel).logno] > 16;
      grad.chantype(sel(others)) = {'other trigger'};
    else
      ft_warning('There does not seem to be a suitable trigger channel.');
      grad.chantype(sel) = {'other trigger'};
    end
  end
  for sel=find([orig.chs.kind]==202)' %EOG
    grad.chantype(sel) = {'eog'};
  end
  for sel=find([orig.chs.kind]==302)' %EMG
    grad.chantype(sel) = {'emg'};
  end
  for sel=find([orig.chs.kind]==402)' %ECG
    grad.chantype(sel) = {'ecg'};
  end
  for sel=find([orig.chs.kind]==502)' %MISC
    grad.chantype(sel) = {'misc'};
  end
  for sel=find([orig.chs.kind]==602)' %Resp
    grad.chantype(sel) = {'respiration'};
  end

  % FIFF.FIFF_UNIT_HZ  = 101;
  % FIFF.FIFF_UNIT_N   = 102;
  % FIFF.FIFF_UNIT_PA  = 103;
  % FIFF.FIFF_UNIT_J   = 104;
  % FIFF.FIFF_UNIT_W   = 105;
  % FIFF.FIFF_UNIT_C   = 106;
  % FIFF.FIFF_UNIT_V   = 107;
  % FIFF.FIFF_UNIT_F   = 108;
  % FIFF.FIFF_UNIT_OHM = 109;
  % FIFF.FIFF_UNIT_MHO = 110;
  % FIFF.FIFF_UNIT_WB  = 111;
  % FIFF.FIFF_UNIT_T   = 112;
  % FIFF.FIFF_UNIT_H   = 113;
  % FIFF.FIFF_UNIT_CEL = 114;
  % FIFF.FIFF_UNIT_LM  = 115;
  % FIFF.FIFF_UNIT_LX  = 116;

  for sel=find([orig.chs.unit]==107)'
    grad.chanunit(sel) = {'V'};
  end
  for sel=find([orig.chs.unit]==112)'
    grad.chanunit(sel) = {'T'};
  end
  for sel=find([orig.chs.unit]==201)'
    grad.chanunit(sel) = {'T/m'};
  end

  remove = cellfun(@isempty, grad.label);
  grad.label    = grad.label(~remove);
  grad.chantype = grad.chantype(~remove);
  grad.chanunit = grad.chanunit(~remove);
  grad.tra      = grad.tra(~remove,:);
  grad.chanpos  = grad.chanpos(~remove,:);
  grad.chanori  = grad.chanori(~remove,:);

else
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % use the original implementation
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  % how many Planar gradiometers?
  nPlaGrad = 0;
  for i = 1:orig.nchan
    nPlaGrad = nPlaGrad +(orig.chs(i).coil_type==3012 | orig.chs(i).coil_type==3013 | orig.chs(i).coil_type==3014 | orig.chs(i).coil_type==2);
  end

  % how many Magnetometers?
  nMag = 0;
  for i = 1:orig.nchan
    nMag = nMag +(orig.chs(i).coil_type==3022 | orig.chs(i).coil_type==3023 | orig.chs(i).coil_type==3024);
  end

  % how many Axial gradiometers?
  nAxGrad = 0;
  for i = 1:orig.nchan
    nAxGrad = nAxGrad +(orig.chs(i).coil_type==7001); % babySQUID
  end

  % % how many IAS (internal active shielding) channels?
  % nIAS = 0;
  % for i = 1:orig.nchan;
  %   nIAS = nIAS + ~isempty(strmatch('IAS', orig.chs(i).ch_name));
  % end

  % how many magnetic field sensors in total?
  nSensors = nPlaGrad + nMag + nAxGrad;

  % how many coils in total?
  nCoils = nPlaGrad*2 + nMag + nAxGrad*2;

  % intialise grad structure
  grad.coilpos  = zeros(nCoils,3);
  grad.coilori  = zeros(nCoils,3);
  grad.tra      = zeros(nSensors,nCoils);
  grad.unit     = 'cm'; % see below for the conversion, the original fif units are in meter
  grad.label    = cell(nSensors,1);

  if dewar
    grad.coordsys = 'dewar';
  else
    grad.coordsys = 'neuromag';
  end

  % initialise elec structure, this can remain empty
  elec = [];

  % define coils
  kCoil = 1;
  kChan = 1;
  % cf. Joachim's original script - I've implemented it this way in case MEG
  % and EEG channels are not listed first in the .fif file; this shouldn't
  % ever be the case but acts as a safety net...

  for n = 1:orig.nchan
    if (orig.chs(n).coil_type==3022 || orig.chs(n).coil_type==3023 || orig.chs(n).coil_type==3024) % magnetometer
      t = orig.chs(n).coil_trans;

      % TC 2011 09 24 I have changed the coil definition, the original was
      % grad.coilpos(kCoil,:) = t(1:3,4);

      grad.coilpos(kCoil,:) = t(1:3,4)+0.0003*t(1:3,3);
      grad.coilori(kCoil,:) = t(1:3,3);
      grad.tra(kChan,kCoil) = 1;
      kCoil = kCoil+1;
      grad.label{kChan} = deblank(orig.ch_names{n});
      grad.chantype{kChan,1}='megmag';
      kChan = kChan+1;

    elseif (orig.chs(n).coil_type==3012 || orig.chs(n).coil_type==3013 || orig.chs(n).coil_type==3014 || orig.chs(n).coil_type==2) % planar gradiometer
      t = orig.chs(n).coil_trans;

      % TC 2011 09 24 I have changed the coil definition, the original was
      % grad.coilpos(kCoil,:) = 0.0000*t(1:3,3)+t(1:3,4)-0.0084*t(1:3,1)); % for the 1st coil
      % grad.coilpos(kCoil,:) = 0.0000*t(1:3,3)+t(1:3,4)+0.0084*t(1:3,1)); % for the 2nd coil

      grad.coilpos(kCoil,:) = 0.0003*t(1:3,3)+t(1:3,4)-0.0084*t(1:3,1); % for the 1st coil
      grad.coilori(kCoil,:) = t(1:3,3);
      grad.tra(kChan,kCoil) = -1;
      kCoil = kCoil+1;

      grad.coilpos(kCoil,:) = 0.0003*t(1:3,3)+t(1:3,4)+0.0084*t(1:3,1); % for the 2nd coil
      grad.coilori(kCoil,:) = t(1:3,3);
      grad.tra(kChan,kCoil) = 1;
      kCoil = kCoil+1;

      grad.label{kChan} = deblank(orig.ch_names{n});
      grad.chantype{kChan,1}='megplanar';
      kChan = kChan+1;

    elseif (orig.chs(n).coil_type==7001)  % babySQUID axial gradiometer bottom coils
      t = orig.chs(n).coil_trans;

      grad.coilpos(kCoil,:)=t(1:3,4);  % for the 1st coil
      grad.coilori(kCoil,:)=t(1:3,3);
      grad.tra(kChan,kCoil)=1;
      kCoil=kCoil+1;

      grad.coilpos(kCoil,:)=t(1:3,4)+0.050*t(1:3,3);  % for the 2nd coil
      grad.coilori(kCoil,:)=t(1:3,3);
      grad.tra(kChan,kCoil)=-1;
      kCoil=kCoil+1;

      grad.label{kChan}=deblank(orig.ch_names{n});
      grad.chantype{kChan,1}='megaxial';
      kChan=kChan+1;

    else
      % do nothing - either an EEG channel or something else such as a stim channel
    end
  end

  % check we've got all the MEG channels:
  kChan = kChan-1;
  if kChan ~= (nPlaGrad + nMag +nAxGrad)
    ft_error('Number of MEG channels identified does not match number of channels in grad structure');
  end

  % determine the type of acquisition system
  if nAxGrad>0
    grad.type = 'babysquid74';
  elseif nPlaGrad>122 && nMag~=0
    grad.type = 'neuromag306';
  elseif nPlaGrad<=122 && nMag==0
    grad.type = 'neuromag122';
  else
    % do not specify type of acquisition system
  end

  % multiply by 100 to get cm
  grad.coilpos = 100*grad.coilpos;
end

% how many EEG channels?
nEEG = 0;
for i = 1:orig.nchan
  nEEG = nEEG +(orig.chs(i).kind==2);
end

% define EEG channels
if nEEG>0
  elec.elecpos  = zeros(nEEG,3);
  elec.unit     = 'cm';
  elec.label    = cell(nEEG,1);

  % Amendments to overcome problem with fiff_read_meas_info.m when >60 channels (thanks to Rik Henson)

  dig_eeg = find([orig.dig.kind]==3); % Find EEG digitisations

  if ~isempty(dig_eeg)
    dig_eeg(1) = []; % Remove reference
  end

  chn_eeg = find([orig.chs.kind]==2); % Find EEG channels

  kChan = 0;
  for n = chn_eeg
    kChan = kChan+1;
    if nEEG<=60
      elec.elecpos(kChan,1:3) = orig.chs(n).eeg_loc(1:3);
    else
      if kChan<=numel(dig_eeg)
        elec.elecpos(kChan,1:3) = orig.dig(dig_eeg(kChan)).r;
      else
        ft_warning('not all EEG channel positions have been digitized');
        elec.elecpos(kChan,1:3) = nan;
      end
    end
    elec.label{kChan} = deblank(orig.ch_names{n});
  end

  % check we've got all the EEG channels:
  if kChan~=(nEEG)
    ft_error('Number of EEG channels identified does not match number of channels in elec structure!!!!!');
  end

  % multiply by 100 to get cm
  elec.elecpos = 100*elec.elecpos;
end

% construct SSP projectors, these can be applied later to the data and grad
% structure using FT_DENOISE_SSP
grad.balance = [];
grad.balance.current = 'none';

for i = 1:length(hdr.projs)
  hdr.projs(i).active = 'true';
  montage = [];
  montage.tra = mne_make_projector(hdr.projs(i), hdr.ch_names, []);
  montage.labelorg = hdr.ch_names;
  montage.labelnew = hdr.ch_names;
  grad.balance.(fixname(hdr.projs(i).desc)) = montage;
end

% remove grad if completely empty
if size(grad.label,1) == 0
  grad = [];
end


function [varargout] = iscolumn(varargin)

% ISCOLUMNN is a drop-in replacement for the same function that was
% introduced in MATLAB R2010b.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% see https://github.com/fieldtrip/fieldtrip/issues/899

alternatives = which(mfilename, '-all');
if ~iscell(alternatives)
  % this is needed for octave, see https://github.com/fieldtrip/fieldtrip/pull/1171
  alternatives = {alternatives};
end

keep = true(size(alternatives));
for i=1:numel(alternatives)
  keep(i) = keep(i) && ~any(alternatives{i}=='@');  % exclude methods from classes
  keep(i) = keep(i) && alternatives{i}(end)~='p';   % exclude precompiled files
end
alternatives = alternatives(keep);

if exist(mfilename, 'builtin') || any(strncmp(alternatives, matlabroot, length(matlabroot)) & cellfun(@isempty, strfind(alternatives, fullfile('private', mfilename))))
  % remove this directory from the path
  p = fileparts(mfilename('fullpath'));
  sw = warning('off','backtrace');
  warning('Removing "%s" from your path.\nSee http://www.fieldtriptoolbox.org/faq/should_i_add_fieldtrip_with_all_subdirectories_to_my_matlab_path/', p);
  warning(sw);
  rmpath(p);
  % call the original MATLAB function
  if exist(mfilename, 'builtin')
    [varargout{1:nargout}] = builtin(mfilename, varargin{:});
  else
    [varargout{1:nargout}] = feval(mfilename, varargin{:});
  end
  return
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% this is where the actual replacement code starts
% function tf = iscolumn(x)

% deal with the input arguments
if nargin==1
  [x] = deal(varargin{1:1});
else
  error('incorrect number of input arguments')
end

tf = length(size(x))==2 && size(x,2)==1;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% deal with the output arguments

varargout = {tf};


function vx = VBA_vec(X)
% // VBA toolbox //////////////////////////////////////////////////////////
%
% vx = VBA_vec (X)
% transform array X into a column vector
%
% IN:
%   - X: matrix
% OUT:
%   - vx: vector
%
% /////////////////////////////////////////////////////////////////////////

% avoid weirdly sized empty vector
if isempty(X)
    vx = [];
    return;
end

% return vectorized input
vx = full(X(:));


function timelock = fttimelock(this, chanind, timeind, trialind, freqind)
% Method for converting meeg object to Fieldtrip timelock/freq struct
% FORMAT timelock = fttimelock(this, chanind, timeind, trialind, freqind)
%
% The method support both time and TF data and outputs different variants
% of timelock or freq FT struct depending on the dataset type and requested
% data dimensions.
% _______________________________________________________________________
% Copyright (C) 2008-2012 Wellcome Trust Centre for Neuroimaging

% Vladimir Litvak
% $Id: fttimelock.m 5063 2012-11-16 12:10:41Z vladimir $

if nargin < 2 || isempty(chanind)
    chanind = 1:nchannels(this);
end

if nargin < 3 || isempty(timeind)
    timeind = 1:nsamples(this);
end

if nargin < 4 || isempty(trialind)
    trialind = 1:ntrials(this);
end

if strncmpi(transformtype(this),'TF',2) && ...
        (nargin < 5 || isempty(freqind))
     freqind = 1:nfrequencies(this);
end

timelock             = [];
timelock.label       = chanlabels(this, chanind)';

if isequal(transformtype(this), 'time')
   if isequal(type(this), 'continuous')
            error('For continuous data use ftraw method');
   end

   if isequal(type(this), 'single') || length(trialind)>1
       timelock.dimord  = 'rpt_chan_time';
       timelock.trial   =  permute(this.data.y(chanind, timeind, trialind), [3 1 2]);
   else
       timelock.dimord  = 'chan_time';
       timelock.avg     =  spm_squeeze(this.data.y(chanind, timeind, trialind), 3);
   end

   timelock.time       = time(this, timeind);

elseif strncmpi(transformtype(this),'TF',2)
    if length(timeind)>1
        if isequal(type(this), 'single') || length(trialind)>1
            timelock.dimord    = 'rpt_chan_freq_time';
            timelock.powspctrm = permute(this.data.y(chanind, freqind, timeind, trialind), [4 1 2 3]);
        else
            timelock.dimord     = 'chan_freq_time';
            timelock.powspctrm  =  spm_squeeze(this.data.y(chanind, freqind, timeind, trialind), 3);
        end

        timelock.time       = time(this, timeind);
    else
        if isequal(type(this), 'single') || length(trialind)>1
            timelock.dimord    = 'rpt_chan_freq';
            timelock.powspctrm = spm_squeeze(permute(this.data.y(chanind, freqind, timeind, trialind), [4 1 2 3]), 4);
        else
            timelock.dimord     = 'chan_freq';
            timelock.powspctrm  =  spm_squeeze(this.data.y(chanind, freqind, timeind, trialind), [3 4]);
        end
    end

    timelock.freq      = frequencies(this, freqind);
else
    error('Unknown transform type.');
end

if length(trialind)>1

    clist      =  condlist(this);
    condlabels = conditions(this, trialind);
    timelock.trialinfo = 0*trialind;

    for k = 1:numel(clist)
        fprintf('mapping condition label "%s" to condition code %d\n', clist{k}, k);
        sel = strcmp(clist{k}, condlabels);
        timelock.trialinfo(sel) = k;
    end

end

if ~isempty(sensors(this, 'MEG'))
    timelock.grad = sensors(this, 'MEG');
end

if ~isempty(sensors(this, 'EEG'))
    timelock.elec = sensors(this, 'EEG');
end