classdef MaxFixedStepsReachedValidator < AbstractLaunchVehicleDataValidator
    %MaxSimTimeReachedValidator Summary of this class goes here
    %   Detailed explanation goes here

    properties
        lvdData LvdData
    end

    methods
        function obj = MaxFixedStepsReachedValidator(lvdData)
            obj.lvdData = lvdData;
        end

        function [errors, warnings] = validate(obj)
            errors = LaunchVehicleDataValidationError.empty(0,1);
            warnings = LaunchVehicleDataValidationWarning.empty(0,1);

            warnEvtNums = [];
            evts = obj.lvdData.script.evts;
            for(i=1:length(evts)) %#ok<*NO4LP>
                evt = evts(i);

                integratorOptions = evt.integratorObj.getOptions();
                integrationStep = integratorOptions.getIntegratorStepSize();
                integrationMaxFixedSteps = integratorOptions.getIntegratorMaxNumFixedSteps();

                if(integrationStep > 0) %fixed step requested
                    stateLogEntries = obj.lvdData.stateLog.getAllStateLogEntriesForEvent(evt);
                    numEntries = numel(stateLogEntries);

                    if(numEntries >= integrationMaxFixedSteps)
                        warnEvtNums(end+1) = evt.getEventNum(); %#ok<AGROW>
                    end
                end

                if(not(isempty(warnEvtNums)))
                    eventStr = makeEventsStr(unique(warnEvtNums));
                    str = sprintf('Maximum number of fixed step sizes reached on some events. (Events: %s)\n%s', eventStr);
                    warnings(end+1) = LaunchVehicleDataValidationWarning(str); %#ok<AGROW>
                end
            end
        end
    end
end


% Copyright (C) 2017-2018 Titus Cieslewski, RPG, University of Zurich,
%   Switzerland
%   You can contact the author at <titus at ifi dot uzh dot ch>
% Copyright (C) 2017-2018 Siddharth Choudhary, College of Computing,
%   Georgia Institute of Technology, Atlanta, GA, USA
% Copyright (C) 2017-2018 Davide Scaramuzza, RPG, University of Zurich,
%   Switzerland
%
% This file is part of dslam_open.
%
% dslam_open 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.
%
% dslam_open 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 dslam_open. If not, see <http://www.gnu.org/licenses/>.

function opt_handle = initOptHandle(num_robots)

for i = 1:num_robots
    opt_handle.optimized_groups(i).members = [i];
end

opt_handle.running = false;

end


function [outC,ptListC] = stackDLMaskFiles(outPath,outFmt,passedScanDim)
% stackDLMaskFiles.m Reads output mask files and returns 3D stack.
%--------------------------------------------------------------------------
%INPUTS:
% outPath       : Path to generated files
%                 Note: Assumes output filenames are of the form:
%                 prefix_slice# if  passedScanDim = '2D' and
%                 prefix_3D if passedScanDim = '3D'.
% outFmt        : Output format ('H5' or 'NRRD').
% passedScanDim : '2D' or '3D'.
%------------------------------------------------------------------------
% AI 6/29/21

switch outFmt

    case 'H5'
        [outC,ptListC] = stackHDF5Files(outPath,passedScanDim);

    case 'NRRD'

        dirS = dir(fullfile(outPath,'outputNRRD','*.nrrd'));
        fileNameC = {dirS.name};
        ptListC = unique(strtok(fileNameC,'_'));
        outC = cell(length(ptListC),1);

        for p = 1:length(ptListC)

            %Assumes 3D mask file
            fileName = fullfile(outPath,'outputNRRD',fileNameC{1});
            mask3M = nrrdread_opensrc(fileName);
            outC{p} = mask3M;
        end

    otherwise

        error('invalid output format %s',outFmt);

end


function model = svargplvmExpandParam(model, params)

% SVARGPLVMEXPANDPARAM Expand a parameter vector into a shared variational GP-LVM model.
% FORMAT
% DESC takes a SVARGPLVM structure and a vector of parameters, and
% fills the structure with the given parameters. Also performs any
% necessary precomputation for likelihood and gradient
% computations, so can be computationally intensive to call.
% Parallelism can be applied w.r.t the models, so that some speed-up is achieved on
% multi-core machines.

% Parameters must be passed as a vector in the following order (left to right)
% - parameter{size} -
% vardistParams{model.vardist.nParams} % mu, S
%       OR
% [dynamicsVardistParams{dynamics.vardist.nParams} dynamics.kernParams{dynamics.kern.nParams}] % mu_bar, lambda
%    % Followed by:
% private params of 1st model {model.comp{1}.nPrivateParams}
% private params of 2nd model {model.comp{2}.nPrivateParams}
%           ...
% private params of i-th model {model.comp{i}.nPrivateParams}
%
% ARG model : the svargplvm model to update with parameters
% ARG params : parameter vector
% RETURN model : model with updated parameters
%
% SEEALSO : svargplvmCreate, svargplvmExtractParam, modelExpandParam
%
% COPYRIGHT : Andreas C. Damianou, 2011

% VARGPLVM

try
    pool_open = matlabpool('size')>0;
catch e
    pool_open = 0;
end

if pool_open && (isfield(model,'parallel') && model.parallel)
    model = svargplvmExpandParamPar(model, params);
else
    model = svargplvmExpandParamOrig(model, params);
end
%!!! Since all dynamical models have the same "dynamics" structure, we can
%avoid the expandParam for ALL the dynamics structures. In fact, we should
%not store all these dynamics structures at all.

function model = svargplvmExpandParamPar(model, params)
%startVal = 1;
%endVal = model.N*model.q;
%paramsX = params(startVal:endVal);
% model.barmu = reshape(params(startVal:endVal), model.N, model.q);
startValS=1;

if isfield(model, 'dynamics') & ~isempty(model.dynamics)
    endValS = model.dynamics.nParams;
else
    endValS = model.vardist.nParams;
end
sharedParams = params(startValS:endValS);

startVal{1} = endValS+1;
endVal{1} = startVal{1} + model.comp{1}.nPrivateParams-1;
for i = 2:model.numModels
    % model.comp{i}.X = model.X;
    startVal{i} = endVal{i-1}+1;
    endVal{i} = startVal{i} + model.comp{i}.nPrivateParams-1;
end

modelTempComp = model.comp;
parfor i = 1:model.numModels
    % model.comp{i}.X = model.X;
   % startVal = endVal+1;
   % endVal = startVal + model.comp{i}.nPrivateParams-1;
    params_i = [sharedParams params(startVal{i}:endVal{i})];
    modelTempComp{i} = vargplvmExpandParam(modelTempComp{i}, params_i);
    if strcmp(modelTempComp{i}.kern.type, 'rbfardjit') || ~iscell(modelTempComp{i}.kern)
        modelTempComp{i}.kern.comp{1}.inputScales = modelTempComp{i}.kern.inputScales;
    end
    %[par, names] = vargplvmExtractParam(model.comp{i}); %%%%5
    %for j=5:-1:1 %%
    %params_i(end-j) %%%
    %end%%
    %model.comp{i}.kern.comp{1}.inputScales
end
model.comp = modelTempComp;

% with vargplvmExpandParam for the submodels, and given that the dynamics
% parameters (if there are dynamics) are shared, barmu has been turned into
% mu and this is the same for all submodels. The same holds for the
% variational distribution.
model.X = model.comp{1}.X;

if isfield(model, 'dynamics') & ~isempty(model.dynamics)
    model.dynamics = model.comp{1}.dynamics; % = model.comp{i}.dynamics for all submodels m
end

model.vardist = model.comp{1}.vardist;

function model = svargplvmExpandParamOrig(model, params)

%startVal = 1;
%endVal = model.N*model.q;
%paramsX = params(startVal:endVal);
% model.barmu = reshape(params(startVal:endVal), model.N, model.q);

startVal=1;

if isfield(model, 'dynamics') & ~isempty(model.dynamics)
    endVal = model.dynamics.nParams;
else
    endVal = model.vardist.nParams;
end
sharedParams = params(startVal:endVal);

for i = 1:model.numModels
    % model.comp{i}.X = model.X;
    startVal = endVal+1;
    endVal = startVal + model.comp{i}.nPrivateParams-1;
    params_i = [sharedParams params(startVal:endVal)];
    model.comp{i} = vargplvmExpandParam(model.comp{i}, params_i);
    % For compatibility ...
    if strcmp(model.comp{i}.kern.type, 'rbfardjit')
        model.comp{i}.kern.comp{1}.inputScales = model.comp{i}.kern.inputScales;
    end
    %[par, names] = vargplvmExtractParam(model.comp{i}); %%%%5
    %for j=5:-1:1 %%
    %params_i(end-j) %%%
    %end%%
    %model.comp{i}.kern.comp{1}.inputScales
end

% with vargplvmExpandParam for the submodels, and given that the dynamics
% parameters (if there are dynamics) are shared, barmu has been turned into
% mu and this is the same for all submodels. The same holds for the
% variational distribution.
model.X = model.comp{1}.X;

if isfield(model, 'dynamics') & ~isempty(model.dynamics)
    model.dynamics = model.comp{1}.dynamics; % = model.comp{i}.dynamics for all submodels m
end

model.vardist = model.comp{1}.vardist;


% [base,ext] = splitext(name)
function [base,ext] = splitext(name)

k = strfind(name,'.');
if isempty(k),
  base = name;
  ext = '';
  return;
end

k = k(end);
j = strfind(name,'/');
if ~isempty(j) && j(end) > k,
  base = name;
  ext = '';
  return;
end

base = name(1:k-1);
ext = name(k:end);


function writeLogData(fid,data,format)

% WRITELOGDATA  Write log data in file.
%   WRITELOGDATA(FID,DATA) writes the line of data DATA in hte log file
%   identified by FID. FID is created by the function OPENLOGFILE.
%
%   See also OPENLOGFILE, WRITELOGHEADER, CLOSELOGFILE, FPRINTF.

if nargin == 2
    n = length(data);
    format = '%d';
    for i = 1:n-1
        format = [format ' %f'];
    end
    format = [format '\n'];
end

fprintf(fid,format,data);

end
% return

%%
% fid = fopen('lala.log','w');
% writeLogHeader(fid,'f x');
% writeLogData(fid,3);
% fclose(fid);

%%

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

%---------------------------------------------------------------------
%
%   This file is part of SLAMTB, a SLAM toolbox for Matlab.
%
%   SLAMTB 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.
%
%   SLAMTB 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 SLAMTB.  If not, see <http://www.gnu.org/licenses/>.
%
%---------------------------------------------------------------------

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


function f = mat2cell(f, varargin)
%MAT2CELL   Wrap a DELTAFUN in a cell.
%   DELTAFUN objects are not array-valued, so G = MAT2CELL(F) simply wraps F
%   in a cell array and is equivalent to G = {F}.

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

if ( any(cellfun(@(v) v ~= 1, varargin)) )
    error('CHEBFUN:DELTAFUN:mat2cell:inputs', ...
        'DELTAFUN objects are not array-valued, so M and n must equal 1.');
end

f = {f};

end


function q_current = coppelia_get_joint_positions(coppelia)
    joint_handles = coppelia.robot.j_handles;

    q_current = [];
    for i=1:length(joint_handles)
        [error, value]=coppelia.sim.simxGetJointPosition(coppelia.clientID, joint_handles(i), coppelia.sim.simx_opmode_buffer);
        q_current = [q_current value];
    end
    q_current = q_current(:);
end


% batch_export_dvh_to_excel.m
%
% This script exports DVHs for the specified structure names to Excel.
%
% The binwidth to use for DVH calculation is defined in CERROptions.json.
%
% APA, 1/28/2019

% Directory containing CERR files
dirPath = 'path:\to\cerr\files';

% Output Excel file
xlSaveFile = 'path:\to\expoty\excel\dvh.xlsx';

% Names of structures to calculate and export DVHs
strC = {'Lungs_combined', 'Lung_L_combined', 'Lung_R_combined',...
    'Heart_combined', 'Outer_combined', 'Stomach_combined', 'PTV_combined'};

%Find all CERR files
fileC = {};
if strcmpi(dirPath,'\') || strcmpi(dirPath,'/')
    filesTmp = getCERRfiles(dirPath(1:end-1));
else
    filesTmp = getCERRfiles(dirPath);
end
fileC = [fileC filesTmp];

filesNotConvertedC = {};

pathStr = getCERRPath;
optName = [pathStr 'CERROptions.json'];
optS = opts4Exe(optName);

dvhC = {};

%Loop over CERR plans
for iFile = 1:length(fileC)

    planC = loadPlanC(fileC{iFile},tempdir);
    planC = quality_assure_planC(fileC{iFile},planC);
    planC = updatePlanFields(planC);
    indexS = planC{end};

    strNameC = {planC{indexS.structures}.structureName};

    for indStr = 1:length(strC)
                %DVH
                strNum = find(strcmpi(strC{indStr},strNameC));
                doseNum = length(planC{indexS.dose});
                if ~isempty(strNum)
                    [dosesV, volsV] = getDVH(strNum, doseNum, planC);
                    [doseBinsV, volsHistV] = doseHist(dosesV, volsV, optS.DVHBinWidth);
                    doseBinsV = doseBinsV * 100; % Gy to cGy
                    fVol = volsHistV;
                    dvhC{iFile,indStr} = [doseBinsV; fVol];
                else
                    dvhC{iFile,indStr} = [];
                end
    end

end

for iDvh = 1:size(dvhC,2)
    dvhM = [dvhC{:,iDvh}];
    doseHistV = unique(dvhM(1,:));
    dvhM = zeros(length(fileC),length(doseHistV));
    doseHistC{iDvh} = doseHistV;
    for iFile = 1:size(dvhC,1)
        if ~isempty(dvhC{iFile,iDvh})
            indMin = findnearest(doseHistV,min(dvhC{iFile,iDvh}(1,:)));
            indMax = findnearest(doseHistV,max(dvhC{iFile,iDvh}(1,:)));
            dvhM(iFile,indMin:indMax) = dvhC{iFile,iDvh}(2,:);
        end
    end
    dvhToWriteC{iDvh} = dvhM;
end

[~,namC] = cellfun(@fileparts,fileC,'UniformOutput',false);
for indStr = 1:length(strC)
    xlswrite(xlSaveFile,namC',strC{indStr},['A2:A',num2str(length(fileC)+1)])
    colEnd = xlsColNum2Str(length(doseHistC{indStr})+1);
    xlswrite(xlSaveFile,doseHistC{indStr},strC{indStr},...
        ['B1:',colEnd{1},'1'])
    colEnd = xlsColNum2Str(size(dvhToWriteC{indStr},2)+1);
    xlswrite(xlSaveFile,dvhToWriteC{indStr},strC{indStr},...
        ['B2:',colEnd{1},num2str(size(dvhToWriteC{indStr},1)+1)])
end


function st_to_mm_test01 ( )

%*****************************************************************************80
%
%% ST_TO_MM_TEST01 tests ST_TO_MM.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 November 2008
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'ST_TO_MM_TEST01\n' );
  fprintf ( 1, '  Use ST_TO_MM to read an ST file,\n' );
  fprintf ( 1, '  and write an equivalent MM file.\n' );

  input_file = 'st_to_mm_test01.st';
  output_file = 'st_to_mm_test01.mm';

  st_to_mm ( input_file, output_file );

  return
end


MATLAB_PATH = '/usr/local/matlab/';

global Start_path;
Start_path = '/home.dokt/martid1/export/svoboda/Matlab';
setpaths;

screen = get(0, 'ScreenSize');
xwidth = screen(4)/2;
ywidth = screen(4)/2;
set(0, 'defaultfigureposition', [screen(3)-xwidth*1.1 5 xwidth*1.1-4 ywidth*0.9]);
clear screen xwidth ywidth

set(0,'FormatSpacing',         'compact',...
      'DefaultFigureColormap' , (0:1/63:1)'*[1 1 1],...
      'DefaultFigureMenu', 'none' );
close

flops(0);


function varargout = mars_struct(action, varargin)
% Multifunction function for manipulating structures
%
% To help the exposition a bit:
% 'fill' in a name, means that values empty or missing
% in one structure are fetched from another
%
% 'merge' means simply that missing fields are added, with
% values, from a second structure (but not filled if empty)
%
% Each function needs to deal with the case of empty arguments
%
% FORMAT c = mars_struct('fillafromb', a, b, fieldns, flags)
% fills structure fields empty or missing in a from those present in b
% a, b are structures
% fieldns (optional) is cell array of field names to fill from in b
% c is returned structure
% Is recursive, will fill struct fields from struct fields
% flags may contain 'f', which Force fills a from b (all non empty
% fields in b overwrite those in a)
% flags may also contain 'r', which Restricts fields to write from b, to
% those that are already present in a
%
% FORMAT [c, d] = mars_struct('split', a, b)
% split structure a into two, according to fields in b
% so that c becomes a structure which contains the fields
% in a, that are also present in b, and d contains the fields
% in a that are not present in b.  b can be a structure
% or a cell array of fieldnames
%
% FORMAT [d] = mars_struct('strip', a, b)
% strips all fields present in b from those in a,
% returning denuded structure as d. b can be a structure
% or a cell array of fieldnames.  'strip' is just 'split'
% but returning only the second argument
%
% FORMAT c = mars_struct('merge', a, b)
% merges structure a and b (fields present in b added to a)
%
% FORMAT [c,d] = mars_struct('ffillsplit', a, b)
% force fill, followed by split
% All fields from a, that are also present in b, and not empty in b,
% are replaced with the values in b; the result is returned as c
% Any fields present in a, but not present in b, are returned in d
%
% FORMAT c = mars_struct('ffillmerge', a, b)
% force fill followed by merge
% performs 'ffillsplit' on a and b, then merges a and b
% All fields present in a or b are returned in c, but
% any fields present in both, now have the value from b
%
% FORMAT [c d] = mars_struct('splitmerge', a, b)
% performs 'split' on a and b, creating c and d
% then merges c with b.
% d contains fields in a that were not present in b
% c contains fields present in both, or just in b
%
% FORMAT z = mars_struct('isthere', a, b [, c [, d ...])
% returns 1 if field named in b is present in a
% and field value is not empty.
% The call is recursive if more than two arguments are passed
% Thus with structure s = struct('one', struct('two', 3))
% mars_struct('isthere', s, 'one', 'two') returns 1
%
% FORMAT z = mars_struct('getifthere', a, b [, c [, d ...])
% returns value of field named in b from a or [] if absent
% Call is recursive, like 'isthere' above.
%
% FORMAT strs = mars_struct('celldisp', a)
% returns output like disp(a) as a cell array
% Useful for printing text description of structure
%__________________________________________________________________________

% Matthew Brett
% $Id: mars_struct.m 6623 2015-12-03 18:38:08Z guillaume $

if nargin < 1
    error('Action needed');
end
if nargin < 2
    error('Must specify structure')
end
if nargin < 3
    varargin = {varargin{:} []};
end
[a,b] = deal(varargin{1:2});

switch lower(action)
    case 'fillafromb'
        % Return for empty passed args
        if isempty(a), varargout = {b}; return, end
        if isempty(b), varargout = {a}; return, end
        if nargin < 4, fieldns = []; else fieldns = varargin{3}; end
        if isempty(fieldns)
            if ~isstruct(b), error('Need struct as 2nd argument'); end
            fieldns = fieldnames(b);
        end
        if nargin < 5, flags = ''; else flags = varargin{4}; end
        if isempty(flags), flags = ' ';end

        if ischar(fieldns), fieldns=cellstr(fieldns);end

        af = fieldnames(a)';
        bf = fieldns';

        % classify fields 0 = a~b, 1 = a&b, 2=b~a
        cf = af;
        ftype = ismember(af, bf);
        if ~any(flags == 'r')
            b_not_a = find(~ismember(bf, af));
            cf =  {cf{:} bf{b_not_a}};
            ftype = [ftype ones(1, length(b_not_a))*2];
        end

        % cope with arrays of structures
        alen = prod(size(a));
        blen = prod(size(b));
        maxlen = max(alen, blen);

        for si=1:maxlen
            ctmp = [];
            for i=1:length(cf)
                fn = cf{i};
                switch ftype(i)
                    case 0 % a~b
                        fval = getfield(a(si), fn);
                    case 1 % shared field
                        bfc = getfield(b(si), fn);
                        if isempty(getfield(a(si), fn)) || ... % a field is empty
                                (any(flags == 'f' & ~isempty(bfc)))% or force fill
                            fval = bfc;
                        else % field not empty, could be struct -> recurse
                            fval = getfield(a(si),fn);
                            if isstruct(fval) && isstruct(bfc)
                                fval = mars_struct('fillafromb',fval,bfc);
                            end
                        end
                    case 2 % b~a
                        fval = getfield(b(si), fn);
                    case 3 % no field information, see below
                        fval = [];
                end
                if isempty(ctmp)
                    ctmp = struct(fn, fval);
                else
                    ctmp = setfield(ctmp, fn, fval);
                end
            end
            c(si) = ctmp;

            if si == blen % reached end of bs, rest of b~a fields are empty
                ftype = (ftype == 2) * 3;
            elseif si == alen % end of a's rest of a~b fields are empty
                ftype = (ftype == 0) * 2 + 1;
            end

        end
        varargout = {c};

    case 'split'
        if isempty(a), varargout = {a,a}; return, end
        if isempty(b), varargout = {b,a}; return, end
        d = a;
        c = [];

        if ischar(b), b = {b};end
        if isstruct(b), b = fieldnames(b);end

        for bf = b(:)'
            if isfield(a, bf{1})
                c = setfield(c, bf{1}, getfield(a, bf{1}));
                d = rmfield(d, bf{1});
            end
        end
        varargout = {c, d};

    case 'strip'
        [c,d] = mars_struct('split', a, b);
        varargout = {d};

    case 'merge'
        if isempty(a), varargout = {b}; return, end
        if isempty(b), varargout = {a}; return, end
        c = a;

        for bf = fieldnames(b)';
            if ~isfield(a, bf{1})
                c = setfield(c, bf{1}, getfield(b, bf{1}));
            end
        end
        varargout = {c};

    case 'ffillsplit'
        if isempty(a) || isempty(b)
            % Nothing in common, return unchanged
            varargout = {a, b}; return
        end
        c = a; d = b;

        cf = fieldnames(c);
        for i=1:length(cf)
            if isfield(d, cf{i})
                dfc = getfield(d,cf{i});
                if ~isempty(dfc)
                    c = setfield(c, cf{i}, dfc);
                end
                d = rmfield(d, cf{i});
            end
        end
        varargout = {c,d};

    case 'ffillmerge'
        [a,b] = mars_struct('ffillsplit', a, b);
        varargout = {mars_struct('merge', a, b)};

    case 'splitmerge'
        [a,c] = mars_struct('split', a, b);
        varargout = {mars_struct('merge', a, b) c};

    case 'isthere'
        if isempty(a), varargout = {0}; return, end
        c = mars_struct('getifthere', varargin{:});
        varargout = {~isempty(c)};

    case 'getifthere'
        if isempty(a), varargout = {[]}; return, end
        if isempty(b), varargout = {[]}; return, end
        for v = 2:nargin-1
            b = varargin{v};
            if ~isfield(a, b)
                varargout = {[]};
                return
            end
            a = getfield(a, b);
        end
        varargout = {a};

    case 'celldisp'
        if isempty(a), varargout = {{}}; return, end
        af = fieldnames(a);
        c  = {};
        pad_len = size(char(af), 2) + 4;
        pad_str = ['%' num2str(pad_len) 's: %s'];
        for f = 1:length(af)
            d     = getfield(a, af{f});
            cls   = class(d);
            sz    = size(d);
            szstr = sprintf('%dx', size(d));
            szstr(end) = [];
            switch cls
                case 'char'
                case {'double', 'float'}
                    d = ['['  num2str(d) ']'];
                otherwise
                    d = sprintf('[%s %s]', szstr, cls);
            end
            c{f} = sprintf(pad_str, af{f}, d);
        end
        varargout = {c};

    otherwise
        error(['Suspicious action was ' action]);
end % switch


function reversed_sequence = sequence_reverse(sequence)
% sequence_reverse Returns reverse sequence
%
% This sequence converter returns a sequence with all its frames reversed.
%
% Input:
% - sequence (structure): A valid sequence structure.
%
% Output:
% - reversed_sequence (structure): A sequence descriptor of a converted sequence.

reversed_sequence = sequence;
reversed_sequence.groundtruth = sequence.groundtruth(end:-1:1);
reversed_sequence.indices = sequence.indices(end:-1:1);
reversed_sequence.images = sequence.images(end:-1:1);
reversed_sequence.tags.data = sequence.tags.data(end:-1:1, :);
reversed_sequence.values.data = sequence.values.data(end:-1:1, :);


function nlammap()
    %  NLAMMAP displays a map view of the seismicity in Lambert projection and ask for two input
    % points select with the cursor. These input points are
    % the endpoints of the crossection.
    %
    % Stefan Wiemer 2/95
    % updated: 12.10.2004, jochen.woessner@sed.ethz.ch
    % turned into function by Celso G Reyes 2017

    %global a
    %global main mainfault faults coastline vo s1_east s2_west s3_north s4_south
    %global mapl fipo
    %global h2 newa lat1 leng lon1 lon2 lat2

    %{
%% This is how you do it with the mapping toolbox -CGR
fig = figure;
axm=axesm('lambert','MapLatLimit',bounds2(ZG.primeCatalog.Latitude),...
  'MapLonLimit',bounds2(ZG.primeCatalog.Longitude));
plm=plotm(coastlat,coastlon,'k');
plm=plotm(ZG.primeCatalog.Latitude,ZG.primeCatalog.Longitude,'.');
disp('Select one end of cross-section')
p1=ginput(1); %TODO offer chance to redo/abort

disp('Select other end of cross-section')
p2=ginput(1);

    %}

    [c2, gcDist, zans] = plot_cross_section_from_mainmap; %was select_xsection();
    disp(c2)
    return

    ZG=ZmapGlobal.Data;
    report_this_filefun();
    %
    % Find out if figure already exists
    %
    mapl=findobj('Type','Figure','-and','Name','Seismicity Map (Lambert)');

    ZG.xsec_rotation_deg = 0;
    % Set up the Seismicity Map window Enviroment
    %
    if isempty(mapl)
        mapl = figure_w_normalized_uicontrolunits( ...
            'Name','Seismicity Map (Lambert)',...
            'NumberTitle','off', ...
            'backingstore','on',...
            'Visible','off', ...
            'Position',position_in_current_monitor(ZG.map_len(1), ZG.map_len(2)));

        drawnow
        info2=@(s,ev)web(['file:' ZG.hodi '/zmapwww/chap4.htm#997433']);
        info1=@(s,ev)web(['file:' ZG.hodi '/zmapwww/chp11.htm#996756']) ;
        uicontrol('Units','normal',...
            'Position',[.0 .93 .08 .06],'String','Info ',...
            'callback',@info1_callback);

        uicontrol('Units','normal',...
            'Position',[.0 .93 .08 .06],'String','Info ',...
            'callback',@info2_callback);

    end % if figure exist
    %figure(mapl);
    %delete(findobj(mapl,'Type','axes'));
    plotmap(mapl);
    %{
    if isempty(coastline)
        coastline = [ZG.primeCatalog.Longitude(1) ZG.primeCatalog.Latitude(1)];
    end
    %}
    set(gca,'NextPlot','add')
    % Added try-catch to prevent failure if no coastline is inside
    % cross-section box, JW
    %try
    %{
    if length(coastline) > 1 %TODO what is coastline?
        lc_map(coastline(:,2),coastline(:,1),s3_north,s4_south,s1_east,s2_west)
        g = allchild(gca);
        set(g,'Color','k')

        %catch
    end
    set(gca,'NextPlot','add')
    try
        if length(faults) > 10
            lc_map(faults(:,2),faults(:,1),s3_north,s4_south,s1_east,s2_west)
        end
    catch
    end
    set(gca,'NextPlot','add')
    if ~isempty(mainfault)
        lc_map(mainfault(:,2),mainfault(:,1),s3_north,s4_south,s1_east,s2_west)
    end
    at_dep1 = ZG.primeCatalog.Depth<=dep1;
    at_dep2 = ZG.primeCatalog.Depth<=dep2 & ZG.primeCatalog.Depth>dep1;
    at_dep3 = ZG.primeCatalog.Depth<=dep3 & ZG.primeCatalog.Depth>dep2;
    if ZG.primeCatalog.Count > 5000
        %lc_event(ZG.primeCatalog.Latitude,ZG.primeCatalog.Longitude,'.k')
        lc_event(ZG.primeCatalog.Latitude(at_dep1),ZG.primeCatalog.Longitude(at_dep1),'.b',1);
        lc_event(ZG.primeCatalog.Latitude(at_dep2),ZG.primeCatalog.Longitude(at_dep2),'.g',1);
        lc_event(ZG.primeCatalog.Latitude(at_dep3),ZG.primeCatalog.Longitude(at_dep3),'.r',1);
    else
        lc_event(ZG.primeCatalog.Latitude(at_dep1),ZG.primeCatalog.Longitude(at_dep1),'+b');
        lc_event(ZG.primeCatalog.Latitude(at_dep2),ZG.primeCatalog.Longitude(at_dep2),'og');
        lc_event(ZG.primeCatalog.Latitude(at_dep3),ZG.primeCatalog.Longitude(at_dep3),'xr');

    end

    if ~isempty(ZG.maepi)
        lc_event(ZG.maepi.Latitude,ZG.maepi.Longitude,'hy',10,2.0)
    end
    if ~isempty(main)
        lc_event(main(:,2),main(:,1),'hk',10,2.0)
    end
    if ~isempty(vo)
        lc_event(vo.Latitude,vo.Longitude,'^r')
    end
    if ~isempty(well)
        lc_event(well(:,2),well(:,1),'dk')
    end
    %}
    labelList={'Select Endpoints by Mouse',...
        'Coordinate Input',...
        'Multiple segments',...
        'Rotate X-Section'};
    funList = { @do_nlammap2,... select endpoints by mouse
                @posinpu,...    coordinate input
                @musec,...      multiple segments
                @rotateit};     % rotate cross-section

    labelPos = [.05 .00 .40 .06];

    tmp1=ZG.primeCatalog.Latitude';
    tmp2=ZG.primeCatalog.Longitude';

    % dialog box for parameters
    zdlg=ZmapDialog();
    %zdlg.AddEdit(tag,label,value,tooltip);
    zdlg.AddEdit('xsec_width_km','Cross section width [km]',ZG.xsec_defaults.WidthKm,'cross section width, km');
    zdlg.AddPopup('uic',         'Selection Method:',labelList,1,...
        'Select an option for choosing cross section', funlist);
    zdlg.AddCheckbox('do_rotation','Rotate Cross Section', false, 'xsec_rotation_deg','Rotate Cross section');
    zdlg.AddEdit('xsec_rotation_deg','Rotation [deg]:',ZG.xsec_rotation_deg,'Rotate cross-section');
    [result,okPressed]=zdlg.Create('Name', 'Cross section parameters');
    if ~okPressed
        return
    end
    ZG.xsec_defaults.WidthKm = result.xsec_width_km;
    ZG.xsec_rotation_deg = result.xsec_rotation_deg;

    result.uic();

    function do_nlammap2()
        [xsecx xsecy,  inde] = mysect(tmp1,tmp2,ZG.primeCatalog.Depth,ZG.xsec_defaults.WidthKm);
        nlammap2;
    end

end

function rotateit()
    % turned into function by Celso G Reyes 2017

    ZG=ZmapGlobal.Data; % used by get_zmap_globals
    if ~exist('lat1')
        errordlg('Create a cross-section first!');
    else
        [lat1, lat2, lon1, lon2] = rotate_xsection(lat1, lat2, lon1, lon2, ZG.xsec_rotation_deg);

        [xsecx xsecy,  inde] = mysect(tmp1,tmp2,ZG.primeCatalog.Depth,ZG.xsec_defaults.WidthKm,0,lat1,lon1,lat2,lon2);
        nlammap2;
    end

end


function syncPos(RECT1,RECT2,RECT3,ref)
switch ref
    case 1
        pos2 = RECT2.getPosition; pos1 = RECT1.getPosition; pos2([2 4]) = pos1([1 3]); RECT2.newPosition(pos2,1);
        pos3 = RECT3.getPosition; pos1 = RECT1.getPosition; pos3([2 4]) = pos1([2 4]); RECT3.newPosition(pos3,1);
    case 2
        pos2 = RECT2.getPosition; pos1 = RECT1.getPosition; pos1([1 3]) = pos2([2 4]); RECT1.newPosition(pos1,1);
        pos3 = RECT3.getPosition; pos2 = RECT2.getPosition; pos3([1 3]) = pos2([1 3]); RECT3.newPosition(pos3,1);
    case 3
        pos3 = RECT3.getPosition; pos1 = RECT1.getPosition; pos1([2 4]) = pos3([2 4]); RECT1.newPosition(pos1,1);
        pos3 = RECT3.getPosition; pos2 = RECT2.getPosition; pos2([1 3]) = pos3([1 3]); RECT2.newPosition(pos2,1);
end
end


classdef TotalStateOfChargeOptimizationVariable < AbstractOptimizationVariable
    %TotalStateOfChargeOptimizationVariable Summary of this class goes here
    %   Detailed explanation goes here

    properties
        varObj(1,1) TotalVehicleEpsStateOfChargeTermCondition = TotalVehicleEpsStateOfChargeTermCondition(0);

        lb(1,1) double = 0;
        ub(1,1) double = 0;

        useTf(1,1) = false;
    end

    methods
        function obj = TotalStateOfChargeOptimizationVariable(varObj)
            obj.varObj = varObj;
            obj.varObj.optVar = obj;

            obj.id = rand();
        end

        function x = getXsForVariable(obj)
            x = [];

            if(obj.useTf)
                x = obj.varObj.perialt;
            end
        end

        function [lb, ub] = getBndsForVariable(obj)
            lb = obj.lb(obj.useTf);
            ub = obj.ub(obj.useTf);
        end

        function [lb, ub] = getAllBndsForVariable(obj)
            lb = obj.lwrBnd;
            ub = obj.uprBnd;
        end

        function setBndsForVariable(obj, lb, ub)
            obj.lb = lb;
            obj.ub = ub;
        end

        function useTf = getUseTfForVariable(obj)
            useTf = obj.useTf;
        end

        function setUseTfForVariable(obj, useTf)
            obj.useTf = useTf;
        end

        function updateObjWithVarValue(obj, x)
            obj.varObj.totalStateOfCharge = x;
        end

        function nameStrs = getStrNamesOfVars(obj, evtNum)
            nameStrs = {sprintf('Event %i Power Total State of Charge Termination Condition', evtNum)};
        end
    end
end


function result = compHolisticRanking( aid )
%COMPHOLISTICRANKING Summary of this function goes here
%   Detailed explanation goes here
global config
bufname = config.bufname;

did = config.valid_data_id(config.valid_anno_id==aid);

load(config.globalSceneSVMFile);
scenesvm = MODEL{config.globalSceneSVMiterID}.initModel;
clear MODEL

load(sprintf([bufname config.sceneFeatFile], 1));
SEED_HYPS = ALL_HYPS(1);
names = fieldnames(SEED_HYPS);
for i = 1:length(names)
    SEED_HYPS.(names{i}) = [];
end

HYPS = repmat(SEED_HYPS, 5000, 1);
ALL_COST = -10*ones(5000,1);
for rid = 1:config.sampleroomnum
    fprintf('>>%d:%d ', aid, rid);
    try
        load(sprintf([bufname '/' config.sceneFeatFile], rid));
    catch
        fprintf('no data\n');
        continue;
    end
    if isempty(ALL_HYPS)
        continue;
    end
    HYPS((rid-1)*100+1:rid*100) = ALL_HYPS;
    COST((rid-1)*100+1:rid*100) = vertcat(ALL_HYPS.COST);

    [ ~, hypScore] = sceneHypsEvaluation( vertcat(ALL_HYPS.sceneImgFea), ...
            vertcat(ALL_HYPS.MINSCORE), scenesvm, did );
    ALL_COST((rid-1)*100+1:rid*100) = hypScore;
    ROOMID((rid-1)*100+1:rid*100) = rid;
end
fprintf('\n');

load([bufname config.objHypoFile3D]);

%% get our detection performance
[~,I] = sort(ALL_COST,'descend');
%keyboard
scene = packupScene(HYPS(I(1)), CAN_POOL{ROOMID(I(1))});
DET = scene{1};

result.Hyps = HYPS(I(1));
result.GLOBAL = ALL_COST(I(1));
result.ROOMID = ROOMID(I(1));
result.DET = DET;

rot_file_name = [bufname config.IMGLIST(aid).name config.rotateImageSuffix];
rotImg = imread(rot_file_name);
figure; imshow(visualObject2D( rotImg, DET, 512, 1024 ));
figure; visualObject3D( DET, 4, 1 );

end


function [state] = CliffFrontLeftSensorRoomba(serPort);
%[state] = CliffFrontLeftSensorRoomba(serPort)
% Specifies the state of the Cliff Front Left sensor
% Either triggered or not triggered

% By; Joel Esposito, US Naval Academy, 2011

%Initialize preliminary return values
state = nan;
try

%Flush Buffer
N = serPort.BytesAvailable();
while(N~=0)
fread(serPort,N);
N = serPort.BytesAvailable();
end

warning off
global td

fwrite(serPort, [142]);  fwrite(serPort,10);
CliffFrntLft = dec2bin(fread(serPort, 1));
state = bin2dec(CliffFrntLft(end));

pause(td)
catch
    disp('WARNING:  function did not terminate correctly.  Output may be unreliable.')
end


%GETLABTYPE Get label type of dataset
%
%    LABTYPE = GETLABTYPE(A)
%
% Returns the label type of dataset A.


function bst_headtracking(varargin)
% BST_HEADTRACKING: Displays a subject's head position in realtime; used
% for quality control before recording MEG.
%
% USAGE:    bst_headtracking()              Defaults: isRealtimeAlign=0, hostIP='localhost' and TCPIP=1972
%           bst_headtracking(isRealtimeAlign)
%           bst_headtracking(isRealtimeAlign, hostIP, TCPIP)
%
% Inputs:   isRealtimeAlign = [0,1], 1 turns on realtime alignment with saved headposition
%           hostIP  = IP address of host computer
%           TCPIP   = TCP/IP port of host computer
%
% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Elizabeth Bock & Francois Tadel, 2012-2013

global isSaveAlignChannelFile
%% ===== DEFAULT INPUTS ====

% defaults
isRealtimeAlign = 0;
hostIP  = 'localhost';    % IP address of host computer
TCPIP   = 1972;             % TPC/IP port of host computer
PosFile = [];
if nargin == 1
    if strcmp(varargin{1},'RealtimeAlign')
        isRealtimeAlign = 1;
    end
elseif nargin == 2
    isRealtimeAlign = varargin{1};
    hostIP  = varargin{2};
elseif nargin == 3
    isRealtimeAlign = varargin{1};
    hostIP  = varargin{2};
    TCPIP   = varargin{3};
elseif nargin == 4
    isRealtimeAlign = varargin{1};
    hostIP  = varargin{2};
    TCPIP   = varargin{3};
    PosFile = varargin{4};
end

%% ===== CONFIGURATION ====
% % User Directory
% user_dir = bst_get('UserDir');

% Database
ProtocolName  =             'HeadTracking';
SubjectName   =             'HeadMaster';
ConditionHeadPoints =       'HeadPoints'; % Used to warp the head surface
ConditionChan =             'SensorPositions'; % Used to update sensor locations in real-time
ConditionRealtimeAlign =    'RealtimeAlign'; % Used for realtime alignment of previous head position
% Brainstorm
bst_dir =       bst_get('BrainstormHomeDir');
% bst_db_dir =    bst_get('BrainstormDbDir');
tmp_dir =       bst_get('BrainstormTmpDir');

% Initialize FieldTrip
[isInstalled, errMsg, PlugFt] = bst_plugin('Install', 'fieldtrip');
if ~isInstalled
    return;
end
ft_dir = bst_fileparts(which(PlugFt.TestFile));
% Add fieldtrip buffer to path
ft_rtbuffer = bst_fullfile(ft_dir, 'realtime', 'src', 'buffer', 'matlab');
ft_io = bst_fullfile(ft_dir, 'fileio');
if exist(ft_rtbuffer, 'dir') && exist(ft_io, 'dir')
    addpath(ft_rtbuffer);
    addpath(ft_io);
else
    error('Cannot find the FieldTrip buffer and/or io directories');
end
% Newer Fieldtrip version requires multithreading dll.
ft_pthreadlib = bst_fullfile(ft_dir, 'realtime', 'src', 'external', 'pthreads-win64', 'lib');
if ispc && ~exist(bst_fullfile(ft_rtbuffer, 'pthreadGC2-w64.dll'), 'file') && ...
        exist(bst_fullfile(ft_pthreadlib, 'pthreadGC2-w64.dll'), 'file')
    file_copy(bst_fullfile(ft_pthreadlib, 'pthreadGC2-w64.dll'), ...
        bst_fullfile(ft_rtbuffer, 'pthreadGC2-w64.dll'));
end

%% ===== PREPARE DATABASE =====
% Get protocol
iProtocol = bst_get('Protocol', ProtocolName);
% If the protocol doesn't exist yet
if isempty(iProtocol)
    % Create new protocol
    iProtocol = gui_brainstorm('CreateProtocol', ProtocolName, 1, 0); %#ok<NASGU>
else
    % Set as current protocol
    gui_brainstorm('SetCurrentProtocol', iProtocol);
end

%% ===== PREPARE SUBJECT =====
% Get subject
[sSubject, iSubject] = bst_get('Subject', SubjectName);
% If warping: we need to recreate the subject
isWarp = 0;
% Ask subject if the anatomy will be warped
res = java_dialog('question', ...
    'Do you want to warp the anatomy to subject headpoints?', ...
    'Add Headpoints', [], {'Yes', 'No', 'Cancel'});
% User cancelled operation
if isempty(res) || strcmpi(res, 'Cancel')
    return
end

% Warp
if strcmpi(res, 'Yes')
    isWarp = 1;
end

% Create if subject doesnt exist
if isempty(iSubject)
    [sSubject, iSubject] = db_add_subject(SubjectName, [], 1, 0);
end
% Update subject structure
sSubject = bst_get('Subject', iSubject);

if isWarp
    % Delete all the tess and anatomy files in the subject that are not
    % default
    for ii = 1:length(sSubject.Anatomy)
        if isempty(strfind(sSubject.Anatomy(ii).FileName, bst_get('DirDefaultSubject')))
            file_delete(file_fullpath(sSubject.Anatomy(ii).FileName), 1);
        end
    end
    for ii = 1:length(sSubject.Surface)
        if isempty(strfind(sSubject.Surface(ii).FileName, bst_get('DirDefaultSubject')))
            file_delete(file_fullpath(sSubject.Surface(ii).FileName), 1);
        end
    end
end
% Reload subject
db_reload_subjects(iSubject);
% Update subject structure
sSubject = bst_get('Subject', iSubject);

%% ===== PREPARE CONDITION: HEADPOINTS =====
% Get condition
[sStudy, iStudy] = bst_get('StudyWithCondition', [SubjectName '/' ConditionHeadPoints]);
% If warping: we need a channel file in HeadPoints, this will be populated
% with the head points measured and saved in a .pos file
if isWarp
    % Create if condition doesnt exist
    if isempty(sStudy)
        iStudy = db_add_condition(SubjectName, ConditionHeadPoints);
        sStudy = bst_get('Study', iStudy);
    end

    % Copy default channel file to this condition
    DefChannelFile = bst_fullfile(bst_dir, 'defaults', 'meg', 'channel_ctf_default.mat');
    file_copy(DefChannelFile, bst_fileparts(file_fullpath(sStudy.FileName)));
    % Reload condition
    db_reload_studies(iStudy);

    % Get updated study definition
    sStudy = bst_get('Study', iStudy);

    % Update the channel file with the head points
    if isempty(PosFile)
        LastUsedDirs = bst_get('LastUsedDirs');
        PosFile = java_getfile( 'open', 'Select POS file...', LastUsedDirs.ImportChannel, 'single', 'files', ...
            {{'*.pos'}, 'POS files', 'POLHEMUS'}, 0);
        if isempty(PosFile)
            return;
        end
    end
    % Read POS file and channel file
    HeadMat = in_channel_pos(PosFile);
    HPChannelFile = file_fullpath(sStudy.Channel.FileName);
    ChannelMat = in_bst_channel(HPChannelFile);

    % Copy head points
    ChannelMat.HeadPoints = HeadMat.HeadPoints;
    % Force re-alignment on the new set of NAS/LPA/RPA (switch from CTF coil-based to SCS anatomical-based coordinate system)
    ChannelMat = channel_detect_type(ChannelMat, 1, 0);
    save(HPChannelFile, '-struct', 'ChannelMat');

else
    HPChannelFile = file_fullpath(sStudy.Channel.FileName);
    ChannelMat = in_bst_channel(HPChannelFile);
end

% Get the transformation for HPI head coordinates (POS file) to Brainstorm
iTrans = find(~cellfun(@isempty,strfind(ChannelMat.TransfMegLabels, 'Native=>Brainstorm/CTF')));
if isempty(iTrans)
    bst_error('No SCS transformation in the channel file')
    return;
end
%ChannelMat.TransfMeg{end+1} = [ChannelMat.SCS.R, ChannelMat.SCS.T; 0 0 0 1];
trans = ChannelMat.TransfMeg{iTrans};
R = trans(1:3, 1:3);
T = trans(1:3, 4); %in meters

%% ===== WARP =====
if isWarp
    % Warp surface for new head points
    % bst_warp_prepare(ChannelFile, Options)
    %    Options     : Structure of the options
    %         |- tolerance    : Percentage of outliers head points, ignored in the calulation of the deformation.
    %         |                 Set to more than 0 when you know your head points have some outliers.
    %         |                 If not specified: asked to the user (default
    %         |- isInterp     : If 0, do not do a full interpolation (default: 1)
    %         |- isScaleOnly  : If 1, do not perform the full deformation but only a linear scaling in the three directions (default: 0)
    %         |- isSurfaceOnly: If 1, do not warp/scale the MRI (default: 0)
    %         |- isInteractive: If 0, do not ask anything to the user (default: 1)
    Options.tolerance = 0.02;
    Options.isInterp = [];
    Options.isScaleOnly = 0;
    Options.isSurfaceOnly = 1;
    Options.isInteractive = 1;
    hFig = bst_warp_prepare(HPChannelFile, Options);

    % Close figure
    close(hFig);
    % Update subject structure
    sSubject = bst_get('Subject', iSubject);
end

%% ===== PREPARE CONDITION: CHANNEL POSITIONS =====
% Get condition
[sStudyChan, iStudyChan] = bst_get('StudyWithCondition', [SubjectName '/' ConditionChan]);
% Create if condition doesnt exist, this will be populated with sensor
% positions measured from real-time res4 file
if isempty(sStudyChan)
    iStudyChan = db_add_condition(SubjectName, ConditionChan);
    sStudyChan = bst_get('Study', iStudyChan);
end

%% ===== INITIALIZE FIELDTRIP BUFFER =====
% find and kill any old matlab processes
pid = feature('getpid');
[tmp,tasks] = system('tasklist');
pat = '\s+';
str=tasks;
s = regexp(str, pat, 'split');
iMatlab = find(~cellfun(@isempty, strfind(s, 'MATLAB.exe')));

if numel(iMatlab) > 1
    % kill the extra matlab(s)
    disp('An old MATLAB process is still running, stopping now...');
    temp = str2double(s(iMatlab+1));
    iKill = find(temp ~= pid);
    for ii=1:length(iKill)
        [status,result] = system(['Taskkill /PID ' num2str(temp(iKill(ii))) ' /F']);
        if status
            disp(result);
            disp('The process could not be stopped.  Please stop it manually');
        else
            disp(result);
        end
    end
end

% Initialize the buffer
try
    disp('BST> Initializing FieldTrip buffer...');
    buffer('tcpserver', 'init', hostIP, TCPIP);
catch
    disp('BST> Warning: FieldTrip buffer is already initialized.');
    buffer('flush_hdr', [], hostIP, TCPIP);
end
% disp('BST> Remember to type ''clear buffer'' once done with head tracking.'); % Doesn't work: freezes.
% Waiting for acquisition to start
disp('BST> Waiting for acquisition to start...');
while (1) % To fix: This loop can make Matlab crash if wait is too long.
    try
        % [nsamples, nevents, timeout]
        numbers = buffer('wait_dat', [1 -1 1000], hostIP, TCPIP);
        disp('BST> Acquisition started.');
        break;
    catch
        pause(1);
    end
end

%% ===== READING RES4 INFO =====
% Reading header
hdr = buffer('get_hdr', [], hostIP, TCPIP);

% Write .res4 file
res4_file = bst_fullfile(tmp_dir, 'temp.res4');
fid = fopen(res4_file, 'w', 'l');
fwrite(fid, hdr.ctf_res4, 'uint8');
fclose(fid);
% Write empty .meg4
meg4_file = bst_fullfile(tmp_dir, 'temp.meg4');
fid = fopen(meg4_file, 'w', 'l');
fclose(fid);
% Reading structured res4
SensorPositionMat = in_channel_ctf(res4_file);
% Add channel file to the SensorPositions study
SensorPositionFile = db_set_channel(iStudyChan, SensorPositionMat, 2, 2);

%% ===== HEAD TRACKING =====
% Display subject's head
hFig = view_surface(sSubject.Surface(sSubject.iScalp).FileName);
% Set view from the left
figure_3d('SetStandardView', hFig, 'front');
% Check for RealtimeAlign
if isRealtimeAlign
    % Create save button
    btn = uicontrol('Style', 'pushbutton', 'String', 'Save',...
        'Position', [20 20 50 20],...
        'Callback', @SaveAlignCallback);
    [sStudyAlign, iStudyAlign] = bst_get('StudyWithCondition', [SubjectName '/' ConditionRealtimeAlign]);
else
    sStudyAlign = [];
end
ColorTable = [1,0,0; 0,1,0; 0,0,1];
colorInd = 2;
if ~isempty(sStudyAlign)
    % Display CTF helmet
    view_helmet_local(sStudyAlign.Channel.FileName, hFig); % _local
    % Get the helmet patch
    hHelmetPatch = findobj(hFig, 'Tag', 'HelmetPatch');
    color = ColorTable(mod(colorInd-1,size(ColorTable,1))+1,:);
    set(hHelmetPatch, 'FaceColor', color, 'FaceAlpha', .3, 'SpecularStrength', 0, ...
                            'EdgeColor', color, 'EdgeAlpha', .2, 'LineWidth', 1, ...
                            'Marker', 'none', 'Tag', 'MultipleSensorsPatches');
    AlignVertices = get(hHelmetPatch, 'Vertices');
end

% Display current position helmet
colorInd = 1;
% Display CTF helmet
view_helmet_local(SensorPositionFile, hFig);
% Get the helmet patch
hHelmetPatch = findobj(hFig, 'Tag', 'HelmetPatch');
color = ColorTable(mod(colorInd-1,size(ColorTable,1))+1,:);
set(hHelmetPatch, 'FaceColor', color, 'FaceAlpha', .3, 'SpecularStrength', 0, ...
                        'EdgeColor', color, 'EdgeAlpha', .2, 'LineWidth', 1, ...
                        'Marker', 'none', 'Tag', 'MultipleSensorsPatches', ...
                        'Visible', 'on');
% Get XYZ coordinates of the helmet patch object
InitVertices = get(hHelmetPatch, 'Vertices');

% Loop to update positions
while (1)
    % Number of samples to read
    nSamples = 300;
    % Read the last nSamples fiducial positions
    hdr = buffer('get_hdr', [], hostIP, TCPIP);
    currentSample = hdr.nsamples;
    if currentSample < nSamples-1
        % Wait
        pause(.2);
        continue;
    end
    dat = buffer('get_dat', [currentSample-nSamples-1,currentSample-1], hostIP, TCPIP);
    % Average in time
    buf = mean(double(dat.buf), 2);
    Fid = [buf(1:3), buf(4:6), buf(7:9)] ./ 1e3; % convert to mm
    % Get fiducial positions
    sMri.SCS.NAS = Fid(:,1)';
    sMri.SCS.LPA = Fid(:,2)';
    sMri.SCS.RPA = Fid(:,3)';
    % Compute transformation Dewar=>Native (CTF head coils)
    transfSCS = cs_compute(sMri, 'scs'); % NAS, LPA and RPA in mm
    sMri.SCS.R = transfSCS.R;
    sMri.SCS.T = transfSCS.T;
    sMri.SCS.Origin = transfSCS.Origin;
    % Apply transformation to helmet vertices.  sMri is in mm and vertices
    % are in m (as it should be according to cs_convert code).
    Vertices = cs_convert(sMri, 'mri', 'scs', InitVertices);
    % Convert HPI coordinates to Brainstorm coordinates (based on cardinal points)
    Vertices = bst_bsxfun(@plus, R * Vertices', T)';
    % Stop if the window was closed
    if ~ishandle(hHelmetPatch)
        break;
    end
    % Update helmet patch
    set(hHelmetPatch, 'Vertices', Vertices);

    % check difference between current and align position
    if ~isempty(sStudyAlign)
        maxDiff = (max(max(100*abs(AlignVertices - Vertices)/AlignVertices)));

        if maxDiff < 10
            colorInd = 2;
            color = ColorTable(mod(colorInd-1,size(ColorTable,1))+1,:);
            set(hHelmetPatch, 'FaceColor', color, 'FaceAlpha', .3, 'SpecularStrength', 0, ...
                                'EdgeColor', color, 'EdgeAlpha', .2, 'LineWidth', 1, ...
                                'Marker', 'none', 'Tag', 'MultipleSensorsPatches');
        else
            colorInd = 1;
            color = ColorTable(mod(colorInd-1,size(ColorTable,1))+1,:);
            set(hHelmetPatch, 'FaceColor', color, 'FaceAlpha', .3, 'SpecularStrength', 0, ...
                                'EdgeColor', color, 'EdgeAlpha', .2, 'LineWidth', 1, ...
                                'Marker', 'none', 'Tag', 'MultipleSensorsPatches');
        end
    end

    if isSaveAlignChannelFile
        % Check for RealtimeAlign condition
        [tmp, iStudyAlign] = bst_get('StudyWithCondition', [SubjectName '/' ConditionRealtimeAlign]);
        if isempty(iStudyAlign)
            % create the condition and channel file with the current sensor positions for subsequent alignment
            iStudyAlign = db_add_condition(SubjectName, ConditionRealtimeAlign);
        end
        SensorPositionMat.SCS = sMri.SCS; % in mm
        db_set_channel(iStudyAlign, SensorPositionMat, 2, 0);
        SaveAlignChannelFile(HPChannelFile, iStudyAlign, SensorPositionMat);
    end
    % Wait
    pause(.2);
end
end
%% SaveAlignCallback
function SaveAlignCallback(source,callbackdata)
    global isSaveAlignChannelFile
    isSaveAlignChannelFile = 1;
end
%% Head Localization
function SaveAlignChannelFile(HPChannelFile, iStudyAlign, ChannelMat)
    global isSaveAlignChannelFile
    % ChannelMat.SCS already contains the transformation Dewar=>Native (CTF
    % head coils), in mm

    % Get transformation Native=>Brainstorm/CTF (anatomical NAS/LPA/RPA)
    % from head points file.
    HPChannelMat = in_bst_channel(HPChannelFile);
    iTrans = find(~cellfun(@isempty,strfind(HPChannelMat.TransfMegLabels, 'Native=>Brainstorm/CTF')));
    if isempty(iTrans)
        bst_error('No SCS transformation in the head points channel file')
        return;
    end
    % Get the translation and rotation from the HeadPoints tranformation
    trans = HPChannelMat.TransfMeg{iTrans};
    anatR = trans(1:3, 1:3);
    anatT = trans(1:3, 4) * 1000; % convert from m to mm

    % Combine the tranformations
    transfAnat = [anatR, anatT; 0 0 0 1]*[ChannelMat.SCS.R, ChannelMat.SCS.T; 0 0 0 1]; % in mm

    % Update the ChannelMat structure
    ChannelMat.SCS.R = transfAnat(1:3, 1:3);
    ChannelMat.SCS.T = transfAnat(1:3, 4); % in mm

    % Process each sensor
    for i = 1:length(ChannelMat.Channel)
        if ~isempty(ChannelMat.Channel(i).Loc)
            % Converts the locations. ChannelMat.SCS is in mm and locations
            % are in m (as it should be according to cs_convert code).
            ChannelMat.Channel(i).Loc = cs_convert(ChannelMat, 'mri', 'scs', ChannelMat.Channel(i).Loc')';
        end
    end

    % Also transform the fiducial positions, temporarily converted to m.
    ChannelMat.SCS.NAS = cs_convert(ChannelMat, 'mri', 'scs', ChannelMat.SCS.NAS ./ 1000) .* 1000; % still in mm
    ChannelMat.SCS.LPA = cs_convert(ChannelMat, 'mri', 'scs', ChannelMat.SCS.LPA ./ 1000) .* 1000;
    ChannelMat.SCS.RPA = cs_convert(ChannelMat, 'mri', 'scs', ChannelMat.SCS.RPA ./ 1000) .* 1000;

    % Update the list of transformations.  Here the translation must be in
    % m.
    if isempty(ChannelMat.TransfMegLabels)
        iTrans = [];
    else
        iTrans = find(~cellfun(@isempty,strfind(ChannelMat.TransfMegLabels, 'Native=>Brainstorm/CTF')));
    end

    if isempty(iTrans)
        ChannelMat.TransfMeg{end+1} = [ChannelMat.SCS.R, ChannelMat.SCS.T ./ 1000; 0 0 0 1];
        ChannelMat.TransfMegLabels{end+1} = 'Native=>Brainstorm/CTF';
        ChannelMat.TransfEeg{end+1} = [ChannelMat.SCS.R, ChannelMat.SCS.T ./ 1000; 0 0 0 1];
        ChannelMat.TransfEegLabels{end+1} = 'Native=>Brainstorm/CTF';
    else
        ChannelMat.TransfMeg{iTrans} = [ChannelMat.SCS.R, ChannelMat.SCS.T ./ 1000; 0 0 0 1];
        ChannelMat.TransfMegLabels{iTrans} = 'Native=>Brainstorm/CTF';
        ChannelMat.TransfEeg{iTrans} = [ChannelMat.SCS.R, ChannelMat.SCS.T ./ 1000; 0 0 0 1];
        ChannelMat.TransfEegLabels{iTrans} = 'Native=>Brainstorm/CTF';
    end

    % Save new channel file to the target studies.
    db_set_channel(iStudyAlign, ChannelMat, 2, 0);
    isSaveAlignChannelFile = 0;

end

function view_helmet_local(ChannelFile, hFig)
% Local trimmed down version of view_helmet, such that it also uses
% channel_tesselate_local which was modified to work in dewar coordinates.
% The only change, at the end of this function, is that the sensor patch is
% deleted instead of making it invisible.

Modality = 'MEG';

% hFig = view_channels(ChannelFile, Modality, 1, 0, hFig);
  [hFig] = bst_figures('GetFigure', hFig);
  %   iDS = bst_memory('GetDataSetChannel', ChannelFile);
  %   if isempty(hFig)
  %       % Prepare FigureId structure
  %       FigureId = db_template('FigureId');
  %       FigureId.Type     = '3DViz';
  %       FigureId.SubType  = '';
  %       FigureId.Modality = Modality;
  %       % Create figure
  %       [hFig, iFig, isNewFig] = bst_figures('CreateFigure', iDS, FigureId);
  %       % If figure was not created: Display an error message and return
  %       if isempty(hFig)
  %           bst_error('Cannot create figure', '3D figure creation...', 0);
  %           return;
  %       end
  %   end

%   figure_3d('ViewSensors', hFig, 1, 0, 1, Modality);
    % Load channel file
    ChannelMat = in_bst_channel(ChannelFile);
    Channel = ChannelMat.Channel;
    selChan = good_channel(Channel, [], Modality);
    % Get sensors positions

%     [tmp, markersLocs] = GetChannelPositions(iDS, selChan);
    % Initialize returned variables
    vertices    = zeros(3,0);
    % Get device type
    Device = bst_get('ChannelDevice', ChannelFile);
    % Get selected channels
    Channel = Channel(selChan);
    % Find magnetometers
    if strcmpi(Device, 'Vectorview306')
        iMag = good_channel(Channel, [], 'MEG MAG');
    end
    % Loop on all the sensors
    for i = 1:length(Channel)
        % If position is not defined
        if isempty(Channel(i).Loc)
            Channel(i).Loc = [0;0;0];
        end
        % Get number of integration points or coils
        nIntegPoints = size(Channel(i).Loc, 2);
        % Switch depending on the device
        switch (Device)
            case {'CTF', '4D', 'KIT', 'RICOH'}
                if (nIntegPoints >= 4)
                    vertices    = [vertices,    Channel(i).Loc(:,1:4)]; %#ok<*AGROW>
                else
                    vertices    = [vertices,    Channel(i).Loc];
                end
            case 'KRISS'
                if (nIntegPoints >= 4)
                    vertices    = [vertices,    Channel(i).Loc(:,1:4)];
                else
                    vertices    = [vertices,    Channel(i).Loc(:,1)];
                end
            case 'Vectorview306'
                if isempty(iMag) || ismember(i, iMag)
                    vertices = [vertices, Channel(i).Loc];
                end
            case 'BabySQUID'
                vertices    = [vertices,    Channel(i).Loc(:,1)];
            case 'BabyMEG'
                vertices    = [vertices,    Channel(i).Loc];
            case {'NIRS-BRS', 'NIRS'}
                Factor = 1;
                % Position of the channel: mid-way between source and detector, organized in layers by wavelength
                vertices    = [vertices,    mean(Channel(i).Loc,2) .* Factor];
            otherwise
                vertices    = [vertices,    Channel(i).Loc];
        end
    end
    vertices    = double(vertices');
% End of content from GetChannelPositions subfunction.

    % Put focus on target figure
    hAxes = findobj(hFig, '-depth', 1, 'Tag', 'Axes3D');

%     PlotSensorsNet(hAxes, markersLocs, 1, isMesh, markersOrient);
      faces = channel_tesselate_local( vertices );
      % === DISPLAY PATCH ===
      % Display faces / edges / vertices
      FaceColor = [.7 .7 .5];
      EdgeColor = [.4 .4 .3];
      LineWidth = 1;
      % Create sensors patch
      hNet = patch(...
        'Vertices',         vertices, ...
        'Faces',            faces, ...
        'FaceVertexCData',  repmat([1 1 1], [length(vertices), 1]), ...
        'Parent',           hAxes, ...
        'Marker',           'o', ...
        'LineWidth',        LineWidth, ...
        'FaceColor',        FaceColor, ...
        'FaceAlpha',        1, ...
        'EdgeColor',        EdgeColor, ...
        'EdgeAlpha',        1, ...
        'MarkerEdgeColor',  [.4 .4 .3], ...
        'MarkerFaceColor',  'flat', ...
        'MarkerSize',       6, ...
        'BackfaceLighting', 'lit', ...
        'AmbientStrength',  0.5, ...
        'DiffuseStrength',  0.5, ...
        'SpecularStrength', 0.2, ...
        'SpecularExponent', 1, ...
        'SpecularColorReflectance', 0.5, ...
        'FaceLighting',     'gouraud', ...
        'EdgeLighting',     'gouraud', ...
        'Tag',              'SensorsPatch');
% End of content from figure_3d.

  % Update lights
  camlight(findobj(hFig, 'Tag', 'FrontLight'), 'headlight');
  % Update figure name
  bst_figures('UpdateFigureName', hFig);
  % Camera basic orientation
  %   if isNewFig
  %       figure_3d('SetStandardView', hFig, 'top');
  %   end
  % Show figure
  set(hFig, 'Visible', 'on');
% End of content from view_channels.

% Get sensors patch
hSensorsPatch = findobj(hFig, 'Tag', 'SensorsPatch');
if isempty(hSensorsPatch)
    return
elseif numel(hSensorsPatch) > 1
    hSensorsPatch = hSensorsPatch(1);
end
% Get sensors positions
vert = get(hSensorsPatch, 'Vertices');

% ===== CREATE HELMET SURFACE =====
% Get the acquisition device
Device = bst_get('ChannelDevice', ChannelFile);
% Distance sensors/helmet
switch (Device)
    case 'Vectorview306'
        dist = .019;
    case 'CTF'
        dist = .015;
    case '4D'
        dist = .015;
    case 'KIT'
        dist = .020;
    case 'KRISS'
        dist = .025;
    case 'BabyMEG'
        dist = .008;
    case 'RICOH'
        dist = .020;
    otherwise
        dist = 0;
end
% Shrink sensor patch to create the inner helmet surface
if (dist > 0)
    center = mean(vert);
    vert = bst_bsxfun(@minus, vert, center);
    [th,phi,r] = cart2sph(vert(:,1),vert(:,2),vert(:,3));
    [vert(:,1),vert(:,2),vert(:,3)] = sph2cart(th, phi, r - dist);
    vert = bst_bsxfun(@plus, vert, center);
end

% ===== DISPLAY HELMET SURFACE =====
% Copy sensor patch object
hHelmetPatch = copyobj(hSensorsPatch, get(hSensorsPatch,'Parent'));
% Make the sensor patch invisible
% set(hSensorsPatch, 'Visible', 'off');
delete(hSensorsPatch);
% Set patch properties
set(hHelmetPatch, 'Vertices',   vert, ...
                   'LineWidth',  1, ...
                   'EdgeColor',  [.5 .5 .5], ...
                   'EdgeAlpha',  1, ...
                   'FaceColor',  'y', ...
                   'FaceAlpha',  .3, ...
                   'Marker',     'none', ...
                   'Tag',        'HelmetPatch');

end

function Faces = channel_tesselate_local( Vertices, isPerimThresh )
% Modified copy of channel_tesselate to work in dewar coordinates:
% 2d projection changed to "centered - max(z)" coordinates and
% thresholdPerim increased to 8 std instead of 6 to avoid helmet holes.

% CHANNEL_TESSELATE: Tesselate a set of EEG or MEG sensors, for display purpose only.
%
% USAGE:  Faces = channel_tesselate( Vertices, isPerimThresh=1 )
%
% INPUT:
%    - Vertices      : [Nx3], set of 3D points (MEG or EEG sensors)
%    - isPerimThresh : If 1, remove the Faces that are too big
% OUTPUT:
%    - Faces    : [Mx3], result of the tesselation

% Parse inputs
if (nargin < 2) || isempty(isPerimThresh)
    isPerimThresh = 1;
end

% === TESSELATE ===
% Compute best fitting sphere
bfs_center = bst_bfs(Vertices)';
% Center Vertices on BFS center
coordC = bst_bsxfun(@minus, Vertices, bfs_center);
    % 2D Projection
    % Use centered points in case points are not in SCS coordinates, which
    % is the case e.g. when doing real-time head position display (dewar
    % coordinates).
    [X,Y] = bst_project_2d(coordC(:,1), coordC(:,2), coordC(:,3)-max(coordC(:,3)), '2dcap');
% Normalize coordinates
coordC = bst_bsxfun(@rdivide, coordC, sqrt(sum(coordC.^2,2)));
% Tesselation of the sensor array
Faces = convhulln(coordC);

% === REMOVE UNNECESSARY TRIANGLES ===
% For instance: the holes for the ears on high-density EEG caps
if isPerimThresh
    % Get border of the representation
    border = convhull(X,Y);
    % Keep Faces inside the border
    iInside = find(~(ismember(Faces(:,1),border) & ismember(Faces(:,2),border)& ismember(Faces(:,3),border)));
    %Faces   = Faces(iInside, :);

    % Compute perimeter
    triPerimeter = tess_perimeter(Vertices, Faces);
    % Threshold values
    thresholdPerim = mean(triPerimeter(iInside)) + 8 * std(triPerimeter(iInside));
    % Apply threshold
    iFacesOk = intersect(find(triPerimeter <= thresholdPerim), iInside);
    % Find Vertices that are not in the Faces matrix
    iVertNotInFaces = setdiff(1:length(Vertices), unique(Faces(:)));
    if ~isempty(iVertNotInFaces)
        disp(['CHANNEL_TESSELATE> WARNING: Some sensors are not in the Faces list: ' sprintf('%d ', iVertNotInFaces)]);
    end
    % Loop until all the Vertices are visible
    isMissing = 1;
    while isMissing
        % List all the Vertices ignored by the reduced mesh
        iVertOk = unique(reshape(Faces(iFacesOk,:),[],1));
        iVertMissing = setdiff(1:length(Vertices), iVertOk);
        iVertMissing = setdiff(iVertMissing, iVertNotInFaces);
        % If all the Vertices are included, next step
        if isempty(iVertMissing)
            isMissing = 0;
        else
            % Find Faces connected to the first missing vertex
            iFacesAdd = find(any(Faces == iVertMissing(1), 2));
            % From the potential candidate Faces, keep the one that has the smaller perimeter
            [minP, iMinP] = min(triPerimeter(iFacesAdd));
            % Add the smallest face to the list of Faces we keep
            iFacesOk(end+1) = iFacesAdd(iMinP);
        end
    end
    % Remove the Faces
    Faces = Faces(sort(iFacesOk),:);
end

end


function set_colorbar(conf)
%SET_COLORBAR draws a color bar to the plot
%
%   Usage: set_colorbar(conf)
%
%   Input parameters:
%       conf        - configuration struct (see SFS_config)
%
%   SET_COLORBAR(conf) draws a color bar on the figure and sets the map to the
%   color specified in conf.plot.colormap.
%
%   See also: plot_sound_field, set_colormap

%*****************************************************************************
% The MIT License (MIT)                                                      *
%                                                                            *
% Copyright (c) 2010-2019 SFS Toolbox Developers                             *
%                                                                            *
% Permission is hereby granted,  free of charge,  to any person  obtaining a *
% copy of this software and associated documentation files (the "Software"), *
% to deal in the Software without  restriction, including without limitation *
% the rights  to use, copy, modify, merge,  publish, distribute, sublicense, *
% and/or  sell copies of  the Software,  and to permit  persons to whom  the *
% Software is furnished to do so, subject to the following conditions:       *
%                                                                            *
% The above copyright notice and this permission notice shall be included in *
% all copies or substantial portions of the Software.                        *
%                                                                            *
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
% IMPLIED, INCLUDING BUT  NOT LIMITED TO THE  WARRANTIES OF MERCHANTABILITY, *
% FITNESS  FOR A PARTICULAR  PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL *
% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
% LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT  OR OTHERWISE, ARISING *
% FROM,  OUT OF  OR IN  CONNECTION  WITH THE  SOFTWARE OR  THE USE  OR OTHER *
% DEALINGS IN THE SOFTWARE.                                                  *
%                                                                            *
% The SFS Toolbox  allows to simulate and  investigate sound field synthesis *
% methods like wave field synthesis or higher order ambisonics.              *
%                                                                            *
% https://sfs.readthedocs.io                            sfstoolbox@gmail.com *
%*****************************************************************************

%% ===== Checking of input parameter =====================================
nargmin = 1;
nargmax = 1;
narginchk(nargmin,nargmax);
isargstruct(conf);

%% ===== Configuration ===================================================
p.caxis = conf.plot.caxis;
p.usedb = conf.plot.usedb;
p.colormap = conf.plot.colormap;

%% ===== Plotting ========================================================
% Change color map (default: gray)
set_colormap(p.colormap);

% Set the limits of the colormap and add a colorbar
if length(p.caxis)==2
    caxis(p.caxis);
end
if p.usedb
    h = colorbar;
    ylabel(h,'Amplitude (dB)');
    % Get the font size and name of the figure and adjust the colorbar
    fsize = get(gca,'FontSize');
    fname = get(gca,'FontName');
    set(h,'FontSize',fsize);
    set(h,'FontName',fname);
    temp = get(h,'Ylabel');
    set(temp,'FontSize',fsize);
    set(temp,'FontName',fname);
end


% This script was used once to create the demo dataset
% private/demo_waveforms.m. It has no further use and is kept only as
% sample. The originla dataset was California earthquake data in SAC files
% provided by Carl Tape. Original source unknown.
%
% To be run from within private directory. At the time demo data was
% created, a directory sample_data was in private/ as well.

% clear
% clear classes
% rmgismo
% addpath('/home/field/GISMO_BRANCH/GISMO/');
% startup_GISMO

% LOAD DATA
fileList = struct2cell(dir('sample_data/9155518*S*.BHZ.*'));
filesZ = strcat('sample_data/', fileList(1,:)');
fileList = struct2cell(dir('sample_data/9155518*S*.BHN.*'));
filesN = strcat('sample_data/', fileList(1,:)');
fileList = struct2cell(dir('sample_data/9155518*S*.BHE.*'));
filesE = strcat('sample_data/', fileList(1,:)');
files = [filesZ filesN filesE];
w = loadsacfile(files);
%save junk

% TRIM SIZE
w = w([36 19 20 4 21 9 18 10 17 11 8 5 14 26],:);

% ADJUST FIELDS
backAzimuth = get(w(:,1),'BAZ');
for n = 1:numel(w)
     w(n) = addfield( w(n) , 'stationLatitude' , get(w(n), 'STLA') );
     w(n) = addfield( w(n) , 'stationLongitude' , get(w(n), 'STLO') );
     w(n) = addfield( w(n) , 'originLatitude' , get(w(n), 'EVLA') );
     w(n) = addfield( w(n) , 'originLongitude' , get(w(n), 'EVLO') );
    channel = get(w(n), 'CHANNEL');
    w(n) = set( w(n) , 'CHANNEL' , channel(1:3) );
    network = get(w(n), 'NETWORK');
    w(n) = set( w(n) , 'NETWORK' , network(1:2) );
end
w = delfield(w,'AZ');
w = delfield(w,'BAZ');
w = delfield(w,'CMPAZ');
w = delfield(w,'CMPINC');
w = delfield(w,'DIST');
w = delfield(w,'EVDP');
w = delfield(w,'GCARC');
w = delfield(w,'HISTORY');
w = delfield(w,'IFTYPE');
w = delfield(w,'IZTYPE');
w = delfield(w,'KEVNM');
w = delfield(w,'KT1');
w = delfield(w, 'KT2');
w = delfield(w,'KUSER0');
w = delfield(w,'LCALDA');
w = delfield(w,'LOVROK');
w = delfield(w,'LPSPOL');
w = delfield(w,'NZHOUR');
w = delfield(w,'NZJDAY');
w = delfield(w,'NZMIN');
w = delfield(w,'NZMSEC');
w = delfield(w,'NZSEC');
w = delfield(w,'NZYEAR');
w = delfield(w,'O');
w = delfield(w,'SCALE');
w = delfield(w,'STDP');
w = delfield(w,'STEL');
w = delfield(w,'T1');
w = delfield(w,'T2');
w = delfield(w,'STLA');
w = delfield(w,'STLO');
w = delfield(w,'EVLA');
w = delfield(w,'EVLO');

% PLOT LOCATIONS
figure;
plot( get(w(:,1),'STATIONLONGITUDE') , get(w(:,1),'STATIONLATITUDE') , 'b+');
hold on;
plot( get(w(:,1),'ORIGINLONGITUDE') , get(w(:,1),'ORIGINLATITUDE') , 'ro');
set(gca,'DataAspectRatio',[1 cosd(35) 1]);
for n=1:length(backAzimuth)
   text( get(w(n,1),'STATIONLONGITUDE') , get(w(n,1),'STATIONLATITUDE') , num2str(n) );
end

% SAVE DEMO DATA
save('demo_waveforms.mat','w','backAzimuth');