function [resliced] = ft_volumereslice(cfg, mri)

% FT_VOLUMERESLICE flips, permutes, interpolates and/or reslices a volume along the
% principal axes of the coordinate system according to a specified resolution.
%
% Use as
%   mri = ft_volumereslice(cfg, mri)
% where the input MRI should be a single anatomical or functional MRI volume that
% results from FT_READ_MRI or FT_VOLUMEREALIGN. You can visualize the the input and
% output using FT_SOURCEPLOT.
%
% The configuration structure can contain
%   cfg.method     = string, 'flip', 'nearest', 'linear', 'cubic' or 'spline' (default = 'linear')
%   cfg.downsample = integer number (default = 1, i.e. no downsampling)
%
% If you specify the method as 'flip', it will only permute and flip the volume, but
% not perform any interpolation. For the other methods the input volumetric data will
% also be interpolated on a regular voxel grid.
%
% For the interpolation methods you should specify
%   cfg.resolution = number, in units of distance (e.g. mm)
%   cfg.xrange     = [min max], in units of distance (e.g. mm)
%   cfg.yrange     = [min max], in units of distance (e.g. mm)
%   cfg.zrange     = [min max], in units of distance (e.g. mm)
% or alternatively with
%   cfg.dim        = [nx ny nz], size of the volume in each direction
%
% If the input MRI has a coordsys-field and you don't specify explicit the
% xrange/yrange/zrange, the centre of the volume will be shifted (with respect to the
% origin of the coordinate system), for the brain to fit nicely in the box.
%
% To facilitate data-handling and distributed computing you can use
%   cfg.inputfile   =  ...
%   cfg.outputfile  =  ...
% If you specify one of these (or both) the input data will be read from a *.mat
% file on disk and/or the output data will be written to a *.mat file. These mat
% files should contain only a single variable, corresponding with the
% input/output structure.
%
% See also FT_VOLUMEREALIGN, FT_VOLUMEDOWNSAMPLE, FT_SOURCEINTERPOLATE, FT_SOURCEPLOT

% Copyright (C) 2010-2020, Robert Oostenveld & Jan-Mathijs Schoffelen
%
% 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$

% these are used by the ft_preamble/ft_postamble function and scripts
ft_revision = '$Id$';
ft_nargin   = nargin;
ft_nargout  = nargout;

% do the general setup of the function
ft_defaults
ft_preamble init
ft_preamble debug
ft_preamble loadvar    mri
ft_preamble provenance mri

% the ft_abort variable is set to true or false in ft_preamble_init
if ft_abort
  return
end

% check if the input data is valid for this function and ensure that the structures correctly describes a volume
if isfield(mri, 'inside')
  mri = ft_checkdata(mri, 'datatype', 'volume', 'feedback', 'yes', 'hasunit', 'yes', 'insidestyle', 'logical');
else
  mri = ft_checkdata(mri, 'datatype', 'volume', 'feedback', 'yes', 'hasunit', 'yes');
end

% set the defaults
cfg.method     = ft_getopt(cfg, 'method', 'linear');
cfg.downsample = ft_getopt(cfg, 'downsample', 1);

if isequal(cfg.method, 'flip')
  % these do not apply when flipping
  cfg = ft_checkconfig(cfg, 'forbidden', {'resolution', 'xrange', 'yrange', 'zrange', 'dim'});
else
  % these only applies when interpolating
  cfg.resolution = ft_getopt(cfg, 'resolution', 1 * ft_scalingfactor('mm', mri.unit)); % default is 1 mm, but the actual number depends on the units. See bug2906
  cfg.xrange     = ft_getopt(cfg, 'xrange', []);
  cfg.yrange     = ft_getopt(cfg, 'yrange', []);
  cfg.zrange     = ft_getopt(cfg, 'zrange', []);
  cfg.dim        = ft_getopt(cfg, 'dim', []);

  if isfield(mri, 'coordsys')
    % use some prior knowledge to optimize the location of the bounding box
    % with respect to the origin of the coordinate system
    switch mri.coordsys
      case {'ctf', '4d', 'bti', 'eeglab'}
        xshift = 30./cfg.resolution;
        yshift = 0;
        zshift = 40./cfg.resolution;
      case {'neuromag', 'itab'}
        xshift = 0;
        yshift = 30./cfg.resolution;
        zshift = 40./cfg.resolution;
      case {'acpc', 'spm', 'mni', 'tal'}
        ft_warning('FIXME, the bounding box needs a better default');
        xshift = 0;
        yshift = 0;
        zshift = 0;
      otherwise
        xshift = 0;
        yshift = 0;
        zshift = 0;
    end
  else % if no coordsys is present
    xshift = 0;
    yshift = 0;
    zshift = 0;
  end

  if ~isempty(cfg.dim)
    xrange = [-cfg.dim(1)/2+0.5 cfg.dim(1)/2-0.5] * cfg.resolution + xshift;
    yrange = [-cfg.dim(2)/2+0.5 cfg.dim(2)/2-0.5] * cfg.resolution + yshift;
    zrange = [-cfg.dim(3)/2+0.5 cfg.dim(3)/2-0.5] * cfg.resolution + zshift;
  else % if no cfg.dim is specified, use defaults
    range = [-127.5 127.5] * cfg.resolution; % 255 mm^3 bounding box, assuming human brain
    xrange = range + xshift;
    yrange = range + yshift;
    zrange = range + zshift;
  end

  % if ranges have not been specified by the user
  if isempty(cfg.xrange)
    cfg.xrange = xrange;
  end
  if isempty(cfg.yrange)
    cfg.yrange = yrange;
  end
  if isempty(cfg.zrange)
    cfg.zrange = zrange;
  end

end % if method~=fip

if cfg.downsample~=1
  % optionally downsample the anatomical and/or functional volumes
  tmpcfg = keepfields(cfg, {'downsample', 'showcallinfo', 'trackcallinfo', 'trackusage', 'trackdatainfo', 'trackmeminfo', 'tracktimeinfo', 'checksize'});
  mri = ft_volumedownsample(tmpcfg, mri);
  % restore the provenance information
  [cfg, mri] = rollback_provenance(cfg, mri);
end

if strcmp(cfg.method, 'flip')
  % this uses some private functions that change the volumes and the transform
  resliced = volumepermute(mri); % this makes the transform approximately diagonal
  flipvec = false(1,3);
  flipvec(1) = resliced.transform(1,1)<0;
  flipvec(2) = resliced.transform(2,2)<0;
  flipvec(3) = resliced.transform(3,3)<0;
  resliced = volumeflip(resliced, flipvec); % this flips along each of the dimensions
  if ~isequal(mri.transform, resliced.transform)
    ft_info('flipped the volume to make it consistent with the axes of the coordinate system');
  end

else
  % compute the desired grid positions
  xgrid = cfg.xrange(1):cfg.resolution:cfg.xrange(2);
  ygrid = cfg.yrange(1):cfg.resolution:cfg.yrange(2);
  zgrid = cfg.zrange(1):cfg.resolution:cfg.zrange(2);

  resliced           = [];
  resliced.dim       = [length(xgrid) length(ygrid) length(zgrid)];
  resliced.transform = translate([cfg.xrange(1) cfg.yrange(1) cfg.zrange(1)]) * scale([cfg.resolution cfg.resolution cfg.resolution]) * translate([-1 -1 -1]);
  resliced.anatomy   = zeros(resliced.dim, 'int8');
  resliced.unit      = mri.unit;

  % these take a lot of memory
  clear xgrid ygrid zgrid

  % these are the same in the resliced as in the input anatomical MRI
  if isfield(mri, 'coordsys')
    resliced.coordsys = mri.coordsys;
  end

  fprintf('reslicing from [%d %d %d] to [%d %d %d]\n', mri.dim(1), mri.dim(2), mri.dim(3), resliced.dim(1), resliced.dim(2), resliced.dim(3));

  % determine the fields to reslice
  fn = parameterselection('all', mri);

  % the actual work is being done by ft_sourceinterpolate
  % this interpolates the real volume on the resolution that is defined for the resliced volume
  tmpcfg                = [];
  tmpcfg.parameter      = fn;
  tmpcfg.interpmethod   = cfg.method;
  resliced              = ft_sourceinterpolate(tmpcfg, mri, resliced);
  resliced.cfg.previous = resliced.cfg.previous{1}; % the 2nd input is a dummy variable
  cfg.method = resliced.cfg.interpmethod;           % remember the method that was used
  % restore the provenance information
  [cfg, resliced] = rollback_provenance(cfg, resliced);

  % remove fields that were not present in the input
  % this applies specifically to the 'inside' field that may have been added by ft_sourceinterpolate
  resliced = keepfields(resliced, fieldnames(mri));

  % convert any non-finite values to 0 to avoid problems later on
  for i=1:numel(fn)
    resliced.(fn{i})(~isfinite((fn{i}))) = 0;
  end

end % if method=flip or interpolate

% do the general cleanup and bookkeeping at the end of the function
ft_postamble debug
ft_postamble previous   mri
ft_postamble provenance resliced
ft_postamble history    resliced
ft_postamble savevar    resliced


function SwatheOpt = PlotSwatheOption
% =======================================================================
% Optional inputs for PlotSwathe
% =======================================================================
% SwatheOpt = PlotSwatheOption
% =======================================================================
% VAR Toolbox 3.0
% Ambrogio Cesa-Bianchi
% ambrogiocesabianchi@gmail.com
% March 2015. Updated November 2020
% -----------------------------------------------------------------------

%% INITIALIZE VARIABLES
%color = bone(8);
SwatheOpt.swathecol  = [138, 178, 212]./255; % color(6,:);
SwatheOpt.linecol    = [13, 54, 84]./255;    % color(1,:);
SwatheOpt.do_dates   = 0;
SwatheOpt.frequency  = 'q';
SwatheOpt.swatheonly = 0;
SwatheOpt.marker     = 'none';
SwatheOpt.transp     = 0;   % Allow for transparency when plotting multiple swathes
SwatheOpt.alpha      = 1;   % Sets alpha for transparent swathes. Default is 1


function Obj = SOFAconvertTHK2SOFA(miroObj)
%SOFAconvertTHK2SOFA - converts from miroObj to SOFA format
%   Usage: OBJ=SOFAconvertTHK2SOFA(miroObj)
%
%   SOFAconvertTHK2SOFA(miroObj) converts the HRIRs, BRIRs, and DRIRs (VariSphear array measurements) described in miroObj to SOFA. miroObj is the miro object saved at the Technische Hochschule Koeln, provided by Benjamin Bernschuetz.
%
%   Input parameters:
%     miroObj : HRTF data in miro format
%
%   Output parameters:
%     Obj : New SOFA object (SOFA format)
%
%   Reference to the source format: http://www.audiogroup.web.th-koeln.de/FILES/miro_documentation.pdf
%   Reference to the source coordinate system: http://www.audiogroup.web.th-koeln.de/SOFiA_wiki/COORDINATES.html

% #Author: Tim Lübeck, TH Köln (2018)
% #Author: Piotr Majdak
% #Author: Michael Mihocic: header documentation updated (28.10.2021)
%
% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences;
% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License")
% You may not use this work except in compliance with the License.
% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl
% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing  permissions and limitations under the License.

%%
%if isoctave,
if exist('OCTAVE_VERSION','builtin') ~= 0
    error(['Octave is not able to convert THK to SOFA, use Matlab instead.']);
end

%% Check if miro.m class file is available, if not download file from server
% miro class might also be included in other toolboxes, eg. AKtools
if exist('miro','class') ~= 8
    % download miro.m
    disp('Downloading miro.m from TH Köln server...')
    url = 'http://audiogroup.web.th-koeln.de/FILES/miro.m';
    basepath=which('SOFAstart');
    basepath=basepath(1:end-12); % Kill the function name from the path.
    target=[basepath filesep 'helpers' filesep 'miro.m'];
    websave (target,url);
end

%% Get an empty conventions structure depending on miro format
if ( strcmp (miroObj.type,'HRIR') )
    Obj = SOFAgetConventions('SimpleFreeFieldHRIR');
    Obj.GLOBAL_Title = 'HRIR';
    Obj.GLOBAL_RoomType = 'free field';
    typeFlag = 0;
elseif ( strcmp (miroObj.type,'BRIR') )
    Obj = SOFAgetConventions('MultiSpeakerBRIR');
    Obj.GLOBAL_Title = 'BRIR';
    Obj.GLOBAL_RoomType = 'reverberant';
    typeFlag = 1;
else %( strcmp (miroObj.type,'MICARRAY') )
    Obj = SOFAgetConventions('SingleRoomDRIR');
    Obj.GLOBAL_Title = 'DRIR';
    Obj.GLOBAL_RoomType = 'reverberant';
    typeFlag = 2;
end

%% Fill global attributes
Obj.GLOBAL_ListenerShortName = miroObj.name;
Obj.GLOBAL_AuthorContact = miroObj.contact;
Obj.GLOBAL_Comment = [miroObj.context,' / Sampling Grid: ',miroObj.quadGrid];
Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History','Converted from the miro file format');
Obj.GLOBAL_License = 'CC 3.0 BY-SA';
Obj.GLOBAL_Organization = 'Technische Hochschule Koeln, Germany';
Obj.GLOBAL_Author = miroObj.engineer;
Obj.GLOBAL_Origin = 'http://audiogroup.web.th-koeln.de';
Obj.GLOBAL_DateCreated = datestr(datenum(miroObj.date),'yyyy-mm-dd HH:MM:SS');
Obj.GLOBAL_DatabaseName='THK';
Obj.GLOBAL_ListenerDescription = miroObj.microphone;
Obj.GLOBAL_ReceiverDescription = [miroObj.microphone '; ' miroObj.micPreamp];
Obj.GLOBAL_SourceDescription = miroObj.source;
Obj.GLOBAL_EmitterDescription = miroObj.source;
Obj.GLOBAL_RoomDescription = [miroObj.location,' / avgAirTemp: ',num2str(miroObj.avgAirTemp),' / avgRelHumidity: ',num2str(miroObj.avgRelHumidity)];

%% Set miroObj to degree mode
miroObj.shutUp = 1;
miroObj = setDEG(miroObj);

%% Get miroObject data and convert to SOFA structure
%M: number of measurements;
%R: number of receivers;
%N: number of data samples describing one measurement. Data is a function of N;
%E: number of emitters;
%C: coordinate dimension, always three with the meaning
%FIR : [M R N];

if (typeFlag == 0 || typeFlag == 1)  %BRIR or HRIR
    irChOne = zeros(miroObj.returnTaps,miroObj.nIr);
    irChTwo = zeros(miroObj.returnTaps,miroObj.nIr);
    for channel = 1 : miroObj.nIr
        IR = getIR( miroObj, channel );
        irChOne(:, channel) = IR(:,1);  %[N M]
        irChTwo(:, channel) = IR(:,2);  %[N M]
    end
    if (typeFlag == 0) %HRIR
        Obj.Data.IR = irChOne; % irChOne is [N M]
        Obj.Data.IR(:,:,2) = irChTwo;
        Obj.Data.IR = shiftdim(Obj.Data.IR,1); % convert from [N M R] to [M R N]
    else % BRIR
        Obj.Data.IR = zeros(size(irChOne,2), 2, 1, size( irChTwo,1)); %[N 2 1 M]
        Obj.Data.IR(:,1,:) = shiftdim(shiftdim(irChOne,-2),3);
        Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irChTwo,-2),3);
    end
else % DRIR
    irData = zeros(miroObj.returnTaps,miroObj.nIr);
    for channel = 1 : miroObj.nIr
        irData(:,channel) = miroObj.getIR(channel);
    end
    Obj.Data.IR             = zeros(1, miroObj.nIr ,miroObj.returnTaps); %[M R N]
    for R = 1 : miroObj.nIr
        Obj.Data.IR(1,R,:) = irData(:,R);
    end
    Obj.Data.Delay = zeros(1,miroObj.nIr);
end
Obj.Data.SamplingRate = miroObj.fs;

%% Fill the mandatory source emitter variables
Obj.ListenerPosition = [0 0 0]; % for BRIR and HRIR listener in center
Obj.ReceiverPosition = [0 +miroObj.radius 0; 0 -miroObj.radius 0];  % for HRIR and BRIR ears as receiver

if (typeFlag == 0)%HRIR
    Obj.ListenerView = [1 0 0];
    Obj.ListenerUp = [0 0 1];
    Obj.SourcePosition = [...
        miroObj.azimuth' ... % azimuth angle in a range of (0-360°(. Whereas AZ=0° is defined to be the front direction and AZ=180° to be the rear direction.
        90-miroObj.elevation' ... % elevation angle in range of (0-180°). EL=0 points upwards, EL=90° points to the horizontal plane and EL=180° points downwards.
        miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; % radius in meters
elseif (typeFlag == 1) %BRIR
    Obj.SourcePosition = [0 0 0]; % default edit manually!
    Obj.EmitterPosition = [miroObj.sourceDistance 0 0];   % default position is center, otherwise define manually
    Obj.EmitterPosition_Type  = 'cartesian';
    Obj.EmitterUp = [0 0 1];
    Obj.EmitterView = [-1 0 0];
    Obj.ListenerView = [miroObj.azimuth',  ...          % see HRIR definitions
                        90-miroObj.elevation',  ...
                        zeros(size(miroObj.azimuth'))]; %miroObj.sourceDistance*ones(size(miroObj.azimuth'))];
    Obj.ListenerView_Type = 'spherical';
    Obj.ListenerView_Units = 'degree, degree, metre';
    Obj.ListenerUp = [0 0 1];
else %DRIR
    Obj.SourcePosition  = [1,0,0]; % default edit manually!
    Obj.EmitterPosition = [0,0,0];
    Obj.ListenerPosition    = [0 0 0];
    Obj.ListenerView        = [1 0 0];
    Obj.ListenerUp          = [0 0 1];
    Obj.ListenerView_Type = 'spherical';
    Obj.ListenerView_Units = 'degree, degree, metre';
    Obj.ReceiverPosition = [...
                            miroObj.azimuth' ...
                            90-miroObj.elevation' ...
                            miroObj.radius*ones(size(miroObj.azimuth'))];
    Obj.ReceiverPosition_Type = 'spherical';
    Obj.ReceiverPosition_Units = 'degree, degree, metre';
end

%% Update dimensions
Obj=SOFAupdateDimensions(Obj);


function T = vertcat(varargin)
% overloads [T1,T2,T3..]

T = cat(1,varargin{:});


function [F,V]=patchNanFix(F,V)

numPoints=size(V,1); %Get original number of entries in vertex list

logicValid=~any(isnan(V),2); %Logic for valid vertices
logicValid_F=all(logicValid(F),2); %Logic vor valid faces

F=F(logicValid_F,:); %Get valid faces
V=V(logicValid,:); %Get valid vertices

%Fix indices in faces matrix
indFix1=1:nnz(logicValid);
indFix2=zeros(numPoints,1);
indFix2(logicValid)=indFix1;
F=indFix2(F); %Fix indices
%%
% _*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 enviwrite(filename,envi_data,datatype,resolu,UL,interleave,zone)
%  write envi format file of uint8 and int16
%  for example: enviwrite('testzz',data,'int16',[30,30],jiUL,'bsq',ZC,'this is for test only');
%  i,j => x, y => rows and cols
%  Input  1)  'filename' is the name of the file
%  Input  2)  'envi_data' is the data matrix
%  Input  3)  'dataype' is the datatype to write 'uint8' or 'int16'
%  Input  4)  'resolu' is the resolution of the pixel
%  Input  5)  'UL' is the UpperLeftPoint X Y of the UL pixel (not center of UL pixel)
%  Input  6)  'interleave' is the bsq bip bil format
%  Input  7)  'zone' is the UTM zone
% History: Projection of Landsat ARD is fixed. 18 Aug., 2020. Shi

if strcmp(datatype,'uint8')
    envi_data=uint8(envi_data);
    dt=1;
elseif strcmp(datatype,'int16')
    envi_data=int16(envi_data);
    dt=2;
elseif strcmp(datatype,'int32')
    envi_data=int32(envi_data);
    dt=3;
elseif strcmp(datatype,'uint16')
    envi_data=uint16(envi_data);
    dt=12;
elseif strcmp(datatype,'single')
    envi_data=single(envi_data);
    dt=4;
else
    fprintf('Invalid write data type!\n');
    return;
end

n_dims=size(envi_data);

nrows=n_dims(1);
ncols=n_dims(2);
bands=1;

if length(n_dims)>=3
    bands=n_dims(3);
end

multibandwrite(envi_data,filename,interleave);

filename_hdr=[filename,'.hdr'];

fid_out=fopen(filename_hdr,'wt');

fprintf(fid_out,'ENVI\n');
fprintf(fid_out,'description = {Landsat Scientific Data}\n');
fprintf(fid_out,'samples = %d\n',ncols); % samples is for j
fprintf(fid_out,'lines   = %d\n',nrows); % lines is for i
fprintf(fid_out,'bands   = %d\n',bands);
fprintf(fid_out,'header offset = 0\n');
fprintf(fid_out,'file type = ENVI Standard\n');
fprintf(fid_out,'data type = %d\n',dt);
fprintf(fid_out,'interleave = %s\n',interleave);
fprintf(fid_out,'sensor type = Landsat\n');
fprintf(fid_out,'byte order = 0\n');

if isempty(zone)
    %label as Landsat ARD
    fprintf(fid_out, 'map info = {Albers Conical Equal Area, 1, 1, %d, %d, %d, %d, WGS-84}\n',UL(1),UL(2),resolu(1),resolu(2));
    fprintf(fid_out, 'projection info = {9, 6378140, 6356755.288157528, 23, -96, 0, 0, 29.5, 45.5,WGS-84, Albers Conical Equal Area}\n');
    fprintf(fid_out, 'coordinate system string = {PROJCS["WGS_1984_Albers",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378140.0,298.257]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Albers"],PARAMETER["false_easting",0.0],PARAMETER["false_northing",0.0],PARAMETER["central_meridian",-96.0],PARAMETER["standard_parallel_1",29.5],PARAMETER["standard_parallel_2",45.5],PARAMETER["latitude_of_origin",23.0],UNIT["Meter",1.0]]}');
else
    if (zone > 0)
        fprintf(fid_out, 'map info = {UTM, 1.000, 1.000, %d, %d, %d, %d, %d, North, WGS-84, units=Meters}',UL(1),UL(2),resolu(1),resolu(2),zone);
    else
        fprintf(fid_out, 'map info = {UTM, 1.000, 1.000, %d, %d, %d, %d, %d, South, WGS-84, units=Meters}',UL(1),UL(2),resolu(1),resolu(2),-zone);
    end
end

fclose(fid_out);
end


function [bbci, data]= bbci_calibrate_ERPSpeller(bbci, data)
%BBCI_CALIBRATE_ERP_SPELLER - Calibrate online system for ERP Spellers
%
%This function is called by bbci_calibrate
%(if BBCI.calibate.fcn is set to @bbci_calibrate_ERPSpeller).
%Via BBCI.calibrate.settings, the details can be specified, se below.
%
%Synopsis:
% [BBCI, DATA]= bbci_calibrate_ERPSpeller(BBCI, DATA)
%
%Arguments:
%  BBCI -  the field 'calibrate' holds parameters specific to ERP Spellers.
%  DATA -  holds the calibration data
%
%Output:
%  BBCI - Updated BBCI structure in which all necessary fields for
%     online operation are set, see bbci_apply_structures.
%  DATA - As input but added some information of the analysis that might
%     be reused in a second run
%
%BBCI.calibrate.settings may include the following parameters:
%  ...to.be.filled.in...
%  'cue_markers': Markers that trigger the classification of an ERP,
%          default: [11:16,21:26,31:36,41:46]

% 11-2011 Benjamin Blankertz

default_grd= sprintf(['scale,FC3,FC1,FCz,FC2,FC4,legend\n' ...
                     'C5,C3,C1,Cz,C2,C4,C6\n' ...
                     'CP5,CP3,CP1,CPz,CP2,CP4,CP6\n' ...
                     'P7,P5,P3,Pz,P4,P6,P8\n' ...
                     'PO7,PO3,O1,Oz,O2,PO4,PO8']);

props= {'ref_ival'      [-200 0]                       '!DOUBLE[1 2]'
        'disp_ival'     [-200 800]                     '!DOUBLE[1 2]'
        'clab'          {'not','E*'}                   'CHAR|CELL{CHAR}'
				'clab_rereference'            ''               'CHAR|CELL{CHAR}'
        'cfy_clab'      {'not','E*','Fp*','A*'}        'CHAR|CELL{CHAR}'
        'cfy_ival'                    'auto'           'CHAR(auto)|DOUBLE[- 2]'
        'cfy_ival_pick_peak'          [100 700]        'DOUBLE[1 2]'
        'band'                        []               'DOUBLE[1 2]|DOUBLE[1]'
        'control_per_stimulus'        0                'BOOL'
        'model'             @train_RLDAshrink          'FUNC|CELL'
				'whitening'                   0                'BOOL'
        'nSequences'                  5                'INT'
        'nClasses'                    0                'INT'
        'cue_markers'       [11:16,21:26,31:36,41:46]  '!DOUBLE[1 -]'
        'cfy_maxival'                 []               'DOUBLE[1 2]'
        'reject_artifacts'            1                'BOOL'
        'reject_artifacts_opts'       {}               'PROPLIST'
        'reject_channels'             1                'BOOL'
        'reject_eyemovements'         0                'BOOL'
        'reject_eyemovements_crit'    []               'STRUCT'
        'grd'                         default_grd      'CHAR'
        'clab_erp'                    {'Cz','PO7'}     'CHAR|CELL{CHAR}'
        'clab_rsq'                    {}               'CHAR|CELL{CHAR}'
        'target_dist'                 0                'INT'
        'mrk2feedback_fcn'   @(x)(1+mod(x-1,10))       'FUNC'
        'create_figs'                 1                'BOOL'
       };
[opt, isdefault]= opt_setDefaults('bbci.calibrate.settings', props);

nClassesGuess= length(unique(opt.mrk2feedback_fcn(opt.cue_markers)));
[opt, isdefault]= ...
  opt_overrideIfDefault(opt, isdefault, 'nClasses', nClassesGuess);
[opt, isdefault]= ...
  opt_overrideIfDefault(opt, isdefault, 'clab_rsq', opt.clab_erp);

default_crit_ival= [100 800];
default_crit_ival(1)= max(opt.disp_ival(1), default_crit_ival(1));
default_crit_ival(2)= min(opt.disp_ival(2), default_crit_ival(2));
default_crit= {'maxmin'  100                        'DOUBLE[1]'
               'clab'    {{'EOG*','F9,10','Fp*'}}   'CHAR|CELL{CHAR}'
               'ival'    default_crit_ival          'DOUBLE[1 2]'
              };
[opt, isdefault]= ...
  opt_overrideIfDefault(opt, isdefault, 'reject_eyemovements_crit', ...
                        opt_propspecToStruct(default_crit));

% add possibly missing fields to opt.reject_eyemovements_crit
opt.reject_eyemovements_crit= ...
  opt_setDefaults(opt.reject_eyemovements_crit, default_crit);

[opt, isdefault]= ...
  opt_overrideIfDefault(opt, isdefault, ...
                        'clab_rsq', opt.clab_erp);

% store chosen default settings back in bbci variable
bbci.calibrate.settings= opt;

opt_scalp_erp= defopt_scalp_erp('colorOrder', [0.9 0 0.9; 0.4 0.4 0.4]);
opt_scalp_r= defopt_scalp_r;

mnt= mnt_setGrid(data.mnt, opt.grd);

if ~data.isnew && isfield(data, 'result'),
  previous= data.result;
else
  previous= struct;
end

if ~isempty(opt.band),
  [filt_b,filt_a]= cheby2(5, 20, opt.band/data.cnt.fs*2);
  data.cnt = proc_filt(data.cnt, filt_b, filt_a);
end

BC_result= [];
BC_result.mrk= data.mrk;

BC_result.clab= data.cnt.clab(util_chanind(data.cnt, opt.clab));
BC_result.cfy_clab= data.cnt.clab(util_chanind(data.cnt, opt.cfy_clab));
% The following figures are always generated
if opt.create_figs,
    data.figure_handles= [1 2 4 6];
end

if opt.target_dist,
  [BC_result.mrk, BC_result.selected_trials]= ...
      mrk_selectTargetDist(BC_result.mrk, opt.target_dist);
else
  BC_result.selected_trials= NaN;
end

if ~isempty(opt.clab_rereference),
	[data.cnt, dmy]= proc_commonAverageReference(data.cnt, opt.clab_rereference, '*');
	[dmy, A_reref]= proc_commonAverageReference(proc_selectChannels(data.cnt,BC_result.cfy_clab), opt.clab_rereference, '*');
	A_reref(:,	sum(A_reref==0,1) == size(A_reref,1)) = []; %removes the zero-channels
end

%% --- Artifact rejection (trials and/or channels) based on variance criterion
%
flds= {'reject_artifacts', 'reject_channels', ...
       'reject_artifacts_opts', 'target_dist', 'clab'};
if data.isnew || ~isfield(data, 'previous_settings') || ...
      ~struct_areFieldsEqual(opt, data.previous_settings, flds),
  BC_result.rejected_trials= NaN;
  BC_result.rejected_clab= NaN;
  if opt.reject_artifacts | opt.reject_channels,
    if opt.create_figs,
      fig_state= fig_set(5, 'Hide',1, 'Name','Artifact rejection');
      data.figure_handles(end+1)= 5;
    end
    [mk_clean , rClab, rTrials]= ...
        reject_varEventsAndChannels(data.cnt, BC_result.mrk, ...
                                    opt.disp_ival, ...
                                    'CLab',BC_result.clab, ...
                                    'DoMultipass', 1, ...
                                    'Verbose', 1, ...
                                    'Visualize', opt.create_figs, ...
                                    opt.reject_artifacts_opts{:});
    if opt.create_figs, fig_publish(fig_state); end
    if opt.reject_artifacts,
      bbci_log_write(data, 'Rejected: %d trial(s).', length(rTrials));
      BC_result.mrk= mrk_selectEvents(BC_result.mrk, 'not',rTrials);
      BC_result.rejected_trials= rTrials;
    end
    if opt.reject_channels,
      bbci_log_write(data, 'Rejected channels: <%s>', str_vec2str(rClab));
      BC_result.rejected_clab= rClab;
      if iscell(BC_result.rejected_clab),   %% that means rejected_clab is not NaN
          cidx= find(ismember(BC_result.clab, BC_result.rejected_clab));
          BC_result.clab(cidx)= [];
      end
    end
  else
    % Avoid confusion with old figure from previous run
    fig_closeIfExists(5);
  end
else
  result_flds= {'rejected_trials', 'rejected_clab', 'clab'};
  BC_result= struct_copyFields(BC_result, previous, result_flds);
end

%% --- Segmentation and baselining ---
%
epo= proc_segmentation(data.cnt, BC_result.mrk, opt.disp_ival, ...
                       'clab', BC_result.clab);

%% Rejection of eyemovements based on max-min criterium
%
if opt.reject_eyemovements && opt.reject_eyemovements_crit.maxmin>0,
  [epo, iArte]= ...
      proc_rejectArtifactsMaxMin(epo, ...
                                 opt.reject_eyemovements_crit.maxmin, ...
                                 'clab', opt.reject_eyemovements_crit.clab, ...
                                 'ival', opt.reject_eyemovements_crit.ival, ...
                                 'verbose',1);
  BC_result.mrk= mrk_selectEvents(BC_result.mrk, 'not',iArte);
  BC_result.eyemovement_trials= iArte;
else
  BC_result.eyemovement_trials= NaN;
end

epo= proc_baseline(epo, opt.ref_ival, 'channelwise', 1);

%% --- Plot r^2 matrix and select intervals if requested ---
%
epo_r= proc_rSquareSigned(proc_selectChannels(epo,BC_result.cfy_clab));
%epo_r= proc_rSquareSigned(epo);
epo_r.className= {'sgn r^2 ( T , NT )'};  %% just make it shorter
if opt.create_figs,
  fig_state= fig_set(6, 'Hide',1, 'Name','r^2 Matrix');
end
if isempty(opt.cfy_ival) || isequal(opt.cfy_ival, 'auto'),
  [BC_result.cfy_ival, nfo]= ...
      procutil_selectTimeIntervals(epo_r, 'Visualize', opt.create_figs, ...
                            'VisuScalps', opt.create_figs, ...
                            'Sort', 1, ...
                            'IntersampleTiming', 1, ...
                            'IvalPickPeak', opt.cfy_ival_pick_peak, ...
                            'IvalMax', opt.cfy_maxival);
  bbci_log_write(data.log.fid, 'Selected time intervals:');
  bbci_log_write(data.log.fid, '  [%g %g] ms', BC_result.cfy_ival');
else
  BC_result.cfy_ival= opt.cfy_ival;
  if opt.create_figs,
    plot_scoreMatrix(epo_r, BC_result.cfy_ival);
  end
end
if opt.create_figs,
  fig_publish(fig_state);
end

%% --- Visualize ERPs ---
%
if opt.create_figs,
  fig_state= fig_set(1, 'Hide',1, 'Name','ERP - grid plot');
  H= grid_plot(epo, mnt, defopt_erps, 'ColorOrder',opt_scalp_erp.ColorOrder);
  %grid_markInterval(BC_result.cfy_ival);
  if isfield(H, 'scale'),
    grid_addBars(epo_r, 'HScale',H.scale);
  else
    grid_addBars(epo_r);
  end
  fig_publish(fig_state);

  fig_state= fig_set(2, 'Hide',1, 'Name','ERP - scalp maps');
  H= plot_scalpEvolutionPlusChannel(epo, mnt, opt.clab_erp, ...
                                    BC_result.cfy_ival, ...
                                    opt_scalp_erp);
  grid_addBars(epo_r);
  fig_publish(fig_state);

  if isempty(opt.clab_rsq) || isequal(opt.clab_rsq,'auto'),
    opt.clab_rsq= unique_unsort({nfo.peak_clab}, 4);
  end
  fig_state= fig_set(4, 'Hide',1, 'Name','ERP - r^2 scalp maps');
  plot_scalpEvolutionPlusChannel(epo_r, mnt, opt.clab_rsq, ...
                                 BC_result.cfy_ival, ...
                                 opt_scalp_r);
  fig_publish(fig_state);
end
clear epo*

%% --- Feature extraction ---
%
BC_result.ref_ival= opt.ref_ival;
BC_result.nSequences= opt.nSequences; %% Future extension: select by simulation

bbci.signal.clab= BC_result.cfy_clab;

cnt_processed = proc_selectChannels(data.cnt,bbci.signal.clab);

if ~isempty(opt.clab_rereference),
	cnt_processed = proc_linearDerivation(cnt_processed, A_reref);
	bbci.signal.proc=  {{@online_linearDerivation, A_reref}};
else
	bbci.signal.proc= {};
end

if opt.whitening
	C= cov(cnt_processed.x);
	[V,D]= eig(C);
	A_whitening= V*diag(1./sqrt(diag(D)))*V';
    cnt_processed= proc_linearDerivation(cnt_processed, A_whitening);
	bbci.signal.proc= cat(2, bbci.signal.proc, {{@online_linearDerivation, A_whitening}});
end

if ~isempty(opt.band)  %set filter if required!
  online_fs= data.cnt.fs;   %extract sampling rate from bbci-strukt
  [filt_b,filt_a]= cheby2(5, 20, opt.band/online_fs*2);
  bbci.signal.proc= cat(2, bbci.signal.proc, {{@online_filt, filt_b, filt_a}});
end

if isempty(opt.ref_ival),     % no baselining
  bbci.feature.proc= {{@proc_jumpingMeans, BC_result.cfy_ival}};
  min_t = min(BC_result.cfy_ival(:));
else
  bbci.feature.proc= {{@proc_baseline, BC_result.ref_ival, 'beginning_exact'}, ...
                      {@proc_jumpingMeans, BC_result.cfy_ival}};
  min_t =  min(BC_result.ref_ival(1), min(BC_result.cfy_ival(:)));
end
bbci.feature.ival= [min_t max(BC_result.cfy_ival(:))];

if opt.control_per_stimulus,
  bbci.control.fcn= @bbci_control_ERPSpellerBinary;
else
  bbci.control.fcn= @bbci_control_ERPSpeller;
end
bbci.control.param= {struct('nClasses',         opt.nClasses, ...
                            'nSequences',       BC_result.nSequences, ...
                            'mrk2feedback_fcn', opt.mrk2feedback_fcn)};
bbci.control.condition.marker= opt.cue_markers;
if ~isfield(bbci, 'quit_condition') || ~isfield(bbci.quit_condition, 'marker'),
  bbci.quit_condition.marker = 255;
end

fv= proc_segmentation(cnt_processed, BC_result.mrk, bbci.feature.ival);
fv= bbci_calibrate_evalFeature(fv, bbci.feature);

bbci.classifier.C= trainClassifier(fv, opt.model);

opt_xv= struct('SampleFcn',    {{@sample_chronKFold, 10}}, ...
               'LossFcn',      @loss_rocArea);

loss= crossvalidation(fv, opt.model, opt_xv);
bbci_log_write(data.log.fid, 'ROC-loss: %.1f%%', 100*loss);
%[loss, dum, outTe]= crossvalidation(fv, opt.model, opt_xv);
%me= val_confusionMatrix(fv, outTe, 'Mode','normalized');
%bbci_log_write(data.log.fid, ['ROC-loss: %.1f%%  |  ' ...
%                    'Correct Hits: %.1f%%,  Correct Miss: %.1f%%'], ...
%               100*loss, 100*me(1,1), 100*me(2,2));

data.feature= fv;
data.result= BC_result;
data.result.rocloss = 100*loss;
%data.result.me = me;


function [J] = Nm2J(Nm)
% Convert energy or work from newton-meters to joules.
% Chad A. Greene 2012
J = Nm;
% You say tomato, I say tomatermort.


function value = file_char_count ( file_name )

%*****************************************************************************80
%
%% FILE_CHAR_COUNT counts the number of characters in a file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 June 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string FILE_NAME, the name of the input file.
%
%    Output, integer VALUE, the number of characters in the file.
%
  value = -1;

  input = fopen ( file_name );

  if ( input < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FILE_CHAR_COUNT - Error!\n' );
    fprintf ( 1, '  Could not open the file "%s".\n', file_name );
    error ( 'FILE_CHAR_COUNT - Error!' );
    return;
  end

  value = 0;

  while ( 1 )

    [ c, count ] = fread ( input, 1 );

    if ( count < 1 )
      break;
    end

    value = value + 1;

  end

  fclose ( input );

  return
end


function [hdr] = read_wdq_header(filename)

% READ_WDQ_HEADER reads header information from wdq files
%
% Use as
%  [hdr] = read_wdq_header(filename)
%

% Copyright (C) 2011, Jan-Mathijs Schoffelen
%
% 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: read_wdq_header.m $

% information about how to interpret the file are taken from the document
% 'CODAS data storage format'

fid = fopen(filename, 'r');
%tmp = fread(fid, 110); % the first 110 bytes are always interpretable equally
hdr = [];
hdr.nchan         = fread(fid, 1, 'uint16');
hdr.nchan         = hdr.nchan - bitand(hdr.nchan, 32);
i2                = fread(fid, 1, 'uint16');
hdr.offset        = fread(fid, 1, 'uint8');
hdr.nbyteschanhdr = fread(fid, 1, 'uint8');
hdr.nbyteshdr     = fread(fid, 1, 'int16');
hdr.nbytesdat     = fread(fid, 1, 'uint32'); %FIXME only for unpacked files
hdr.nbytestrailer1 = fread(fid, 1, 'uint32');
hdr.nbytestrailer2 = fread(fid, 1, 'uint16');
i9  = fread(fid, 1, 'uint16'); % not used
i10 = fread(fid, 1, 'uint16'); % not used
i11 = fread(fid, 1, 'int16');
i12 = fread(fid, 4, 'int8');
i13 = fread(fid, 1, 'double');

% FIXME there seems to be a discrepancy here, according to the
% documentation it should be the next (commented) line. according to the
% file I have at hand it should be the uncommented line.
%hdr.fsample        = double(hdr.nchan)./i13;
hdr.fsample = 1./i13;
i14 = fread(fid, 1, 'uint32');
i15 = fread(fid, 1, 'uint32');
i16 = fread(fid, 1, 'uint32');
i17 = fread(fid, 1, 'uint32');
i18 = fread(fid, 1, 'uint32');
i19 = fread(fid, 2, 'uint16');
i20 = fread(fid, 1, 'int16');
i21 = fread(fid, 1, 'int16');
i22 = fread(fid, 1, 'int8');
i23 = fread(fid, 1, 'int8');
i24 = fread(fid, 1, 'int8');
i25 = fread(fid, 1, 'int8');
i26 = fread(fid, 32, 'int8');
i27 = fread(fid, 1, 'uint16');
i28 = fread(fid, 1, 'uint8');
empty = fread(fid, 1, 'uint8');
i29 = fread(fid, 1, 'int8');
i30 = fread(fid, 1, 'int8');
i31 = fread(fid, 1, 'int8');
empty = fread(fid, 1, 'uint8');
i32 = fread(fid, 1, 'int8');
i33 = fread(fid, 1, 'int8');

% interpret relevant stuff from i27
% other stuff may or may not be relevant
hdr.ispacked  = bitand(i27, 2^15)>0;
hdr.lowchan   = bitand(i27, 2^9) >0;

% get channel info
for k = 1:(hdr.nbyteshdr-hdr.offset-2)/hdr.nbyteschanhdr
  fseek(fid, hdr.offset + (k-1)*hdr.nbyteschanhdr, 'bof');
  chanhdr(k).scalingslope     = fread(fid, 1, 'float');
  chanhdr(k).scalingintercept = fread(fid, 1, 'float');
  chanhdr(k).scale            = fread(fid, 1, 'double');
  chanhdr(k).intercept        = fread(fid, 1, 'double');
  chanhdr(k).unit             = fread(fid, 1, 'uint8=>char');
  fread(fid, 1, 'uint8');
  fread(fid, 1, 'uint8'); % may be relevant for packed files
  chanhdr(k).channr = fread(fid, 1, 'uint8');
  chanhdr(k).label  = num2str(k);
end
hdr.chanhdr = chanhdr;

fseek(fid, hdr.nbyteshdr + hdr.nbytesdat, 'bof');
x = fread(fid, hdr.nbytestrailer1, 'uint8');
hdr.x = x; % what shall we do with this?

fseek(fid, hdr.nbyteshdr + hdr.nbytesdat + hdr.nbytestrailer1, 'bof');
annot = fread(fid, hdr.nbytestrailer2, 'uint8');
sel   = find(annot==0);
indx  = find(annot>0, 1, 'first');
sel   = [0;sel];
for k = 1:numel(sel)-1
  hdr.chanhdr(k).annot = char(annot(sel(k)+1:sel(k+1)-1))';
end

fclose(fid);


%% change gaussian width
tmp_gsiz = str2double(get(edit_gsiz, 'string'));
neuron_raw.options.gSiz = tmp_gsiz;
if ~exist('neuron', 'var')
    neuron.options.gsiz = tmp_gsiz / neuron_raw.options.ssub;
end


function n = ndims( x )
n = length( x.size_ );

% 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 w = getplot
f = figure;
plot(1:10);
w = webfigure(f);
close(f);


classdef IncreaseLast_LineSearchInitiator < LineSearchInitiator

    properties (Access = private)
        incrementFactor
        maxValue
        minValue
    end

    methods (Access = public)

        function obj = IncreaseLast_LineSearchInitiator(cParams)
            obj.init(cParams);
            obj.incrementFactor = cParams.incrementFactor;
            obj.maxValue        = cParams.maxValue;
            obj.minValue        = cParams.minValue;
        end

        function initStep = compute(obj,lastStep)
            if lastStep <= obj.minValue
                initStep = 5*lastStep;
            else
                k = obj.incrementFactor;
                initStep = k*lastStep;
                initStep = min(initStep,obj.maxValue);
            end
        end

    end

end


function s = maxitmess()
%MAXITMESS Create a standard error message when training reaches max. iterations.
%
%	Description
%	S = MAXITMESS returns a standard string that it used by training
%	algorithms when the maximum number of iterations (as specified in
%	OPTIONS(14) is reached.
%
%	See also
%	CONJGRAD, GLMTRAIN, GMMEM, GRADDESC, GTMEM, KMEANS, OLGD, QUASINEW, SCG
%

%	Copyright (c) Ian T Nabney (1996-2001)

s = 'Maximum number of iterations has been exceeded';


function test_bug3174

% WALLTIME 00:20:00
% MEM 3gb
% DEPENDENCY ft_volumerealign

load(dccnpath('/home/common/matlab/fieldtrip/data/test/bug3174.mat'));

% co-register the CT to the MRI
cfg             = [];
cfg.method      = 'spm';
cfg.spmversion  = 'spm12';
cfg.viewresult  = 'yes'; % view realignment result
cfg.coordsys    = 'tal';
ct2              = ft_volumerealign(cfg, cttal, mri);


function varargout = auto_classify(varargin)
% AUTO_CLASSIFY M-file for auto_classify.fig
%      AUTO_CLASSIFY, by itself, creates a new AUTO_CLASSIFY or raises the existing
%      singleton*.
%
%      H = AUTO_CLASSIFY returns the handle to a new AUTO_CLASSIFY or the handle to
%      the existing singleton*.
%
%      AUTO_CLASSIFY('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in AUTO_CLASSIFY.M with the given input arguments.
%
%      AUTO_CLASSIFY('Property','Value',...) creates a new AUTO_CLASSIFY or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before auto_classify_OpeningFunction gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to auto_classify_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Copyright 2002-2003 The MathWorks, Inc.

% Edit the above text to modify the response to help auto_classify

% Last Modified by GUIDE v2.5 21-Jun-2006 00:34:13

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @auto_classify_OpeningFcn, ...
                   'gui_OutputFcn',  @auto_classify_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before auto_classify is made visible.
function auto_classify_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to auto_classify (see VARARGIN)

% input parameters

if isempty(varargin)
    handles.matrix2classify = [];
    handles.ncepstral = 5;
else
    handles.matrix2classify = varargin{1};
    handles.ncepstral = varargin{2};
end

handles.distancemeasure = 'sqEuclidean';

handles.cluster_method = 'kmeans';

set(handles.CepstralPopupMenu,'String',num2str([0:handles.ncepstral]'));
set(handles.CepstralPopupMenu,'Value',handles.ncepstral); %handles.ncepstral +1 );
% set(handles.CepstralPopupMenu,'Value',handles.ncepstral-1);

% Choose default command line output for auto_classify
% handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes auto_classify wait for user response (see UIRESUME)
% uiwait(handles.figure1);

uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = auto_classify_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;

close;

function clusters = clusterdata(X,k,dmeasure)
% A wrapper function for clustering

try
    clusters = kmeans(X,k,'distance',dmeasure,'EmptyAction','singleton','replicates',30);
catch
    clusters = k;
end

% --- Executes on button press in AutoClassifyButton.
function AutoClassifyButton_Callback(hObject, eventdata, handles)
% hObject    handle to AutoClassifyButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

set(handles.AcceptButton,'Enable','off');
guidata(gcbo,handles);

cncepstral = get(handles.CepstralPopupMenu,'Value');

matrix2classify = handles.matrix2classify;
matrix2classify = madnormalize(matrix2classify,1); % normalize the columns
matrix2classify = matrix2classify(:,1:cncepstral+1); % include the cepstral coefficients that you want

if length(matrix2classify(1,:)) > 3
    matrix2classify = matrix2classify(:,[1,3:cncepstral+1]); % exclude the first cepestral coefficient
end

try
    segweight = str2num(get(handles.SegLenWeight,'String'));
catch
    segweight = 1;
    set(handles.SegLenWeight,'String','1');
end

% Weight the segment lengths by square root of the weight
matrix2classify(:,1) = matrix2classify(:,1)*sqrt(segweight);

% Other weightings can be added here but the cepestral coefficients have a
% natural exponential decline which acts a weighting

%Handle transformations to segment length

contents = get(handles.TransformPopupMenu,'String');
value = get(handles.TransformPopupMenu,'Value');

switch contents{value}
    case 'None'
        matrix2classify = matrix2classify;
    case 'Exclude'
        matrix2classify = matrix2classify(:,2:length(matrix2classify(1,:)));
    case 'Log'
        matrix2classify(:,1) = log(matrix2classify(:,1));
    case 'Exp'
        matrix2classify(:,1) = exp(matrix2classify(:,1));
end

if length(matrix2classify(1,:)) == 0 % matrix to classify has no information
    return
end

rangestate = get(handles.RangeSpecify,'Value');
diagnosticstate = get(handles.DiagnosticCheckbox,'Value');

if strcmp(handles.cluster_method,'hierarchical')
    handles.classification = cluster_hierarchical(matrix2classify);
    nclusters = length(unique(handles.classification)) - 1;
    set(handles.KClasses,'String',nclusters);

    if diagnosticstate
        pcaplot(matrix2classify,handles.classification);
    end

else if strcmp(handles.cluster_method, 'kmeans')

if not(rangestate)

    kclassstr = get(handles.KClasses,'String');

    if not(isempty(kclassstr))
        try
            nclasses = str2num(kclassstr);
        catch
            return;
        end

        classification =  clusterdata(matrix2classify,nclasses,handles.distancemeasure);% this can be changed to a different clustering algorithm

        % clusterdata shows how a clustering algorithm can be hooked in where the number of
        % classes need to be assigned.

        if length(classification) == 1
            msgbox('Error in clustering. Try changing the number of target clusters or rerunning.');
        else
            if diagnosticstate
                figure();
                [silh h] = silhouette(matrix2classify,classification);
                pcaplot(matrix2classify,classification);
            end
        handles.classification = classification;
        end
    else
        return;
    end
else
    try
        minclust = str2num(get(handles.MinClusters,'String'));
    catch
        return;
    end
    try
        maxclust = str2num(get(handles.MaxClusters,'String'));
    catch
        return;
    end

    resultsclust = cell((1+ maxclust)-minclust,1);

    hw = waitbar(0,'Clustering data set ');
    for i = 1:(1+maxclust)-minclust
        resultsclust{i} = clusterdata(matrix2classify,minclust + (i-1),handles.distancemeasure);
        if length(resultsclust{i}) == 1
            msgbox(['Clustering failed at ' num2str(resultsclust{i}) ' clusters. Try changing the range of clusters or rerunning.']);
            return;
        end
        waitbar(i/(1+maxclust-minclust));
    end
    close(hw);

    silhmean = zeros((1+ maxclust)-minclust,1);

    for i = 1:1+(maxclust)-minclust

        if diagnosticstate
            figure();
            [silh h] = silhouette(matrix2classify,resultsclust{i});
            pcaplot(matrix2classify,resultsclust{i});
        else
            silh = silhouette(matrix2classify,resultsclust{i});
        end

        silhmean(i) = mean(silh);
    end

    [x I] = max(silhmean);
    handles.classification = resultsclust{I(1)};

    set(handles.KClasses,'String',num2str(minclust + (I(1)-1)));
end
end
    end

set(handles.AcceptButton,'Enable','on');

guidata(gcbo,handles);

% --- Executes on button press in CancelButton.
function CancelButton_Callback(hObject, eventdata, handles)
% hObject    handle to CancelButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

handles.output = 0;
guidata(hObject,handles);
uiresume(handles.figure1);

% --- Executes on button press in AcceptButton.
function AcceptButton_Callback(hObject, eventdata, handles)
% hObject    handle to AcceptButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

handles.output = handles.classification;
guidata(hObject,handles);
uiresume(handles.figure1);

function CepstralEdit_Callback(hObject, eventdata, handles)
% hObject    handle to CepstralEdit (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of CepstralEdit as text
%        str2double(get(hObject,'String')) returns contents of CepstralEdit as a double

% --- Executes during object creation, after setting all properties.
function CepstralEdit_CreateFcn(hObject, eventdata, handles)
% hObject    handle to CepstralEdit (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function MinClusters_Callback(hObject, eventdata, handles)
% hObject    handle to MinClusters (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of MinClusters as text
%        str2double(get(hObject,'String')) returns contents of MinClusters as a double

% --- Executes during object creation, after setting all properties.
function MinClusters_CreateFcn(hObject, eventdata, handles)
% hObject    handle to MinClusters (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function MaxClusters_Callback(hObject, eventdata, handles)
% hObject    handle to MaxClusters (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of MaxClusters as text
%        str2double(get(hObject,'String')) returns contents of MaxClusters as a double

% --- Executes during object creation, after setting all properties.
function MaxClusters_CreateFcn(hObject, eventdata, handles)
% hObject    handle to MaxClusters (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

% --- Executes on selection change in TransformPopupMenu.
function TransformPopupMenu_Callback(hObject, eventdata, handles)
% hObject    handle to TransformPopupMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns TransformPopupMenu contents as cell array
%        contents{get(hObject,'Value')} returns selected item from TransformPopupMenu

% value = get(hObject,'Value');
%
% if value == 2
%     handles.matrix2classify(:,1) = log(handles.matrix2classify(:,1));
% else
%     handles.matrix2classify(:,1) = exp(handles.matrix2classify(:,1));
% end

% --- Executes during object creation, after setting all properties.
function TransformPopupMenu_CreateFcn(hObject, eventdata, handles)
% hObject    handle to TransformPopupMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function KClasses_Callback(hObject, eventdata, handles)
% hObject    handle to KClasses (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of KClasses as text
%        str2double(get(hObject,'String')) returns contents of KClasses as a double

% --- Executes during object creation, after setting all properties.
function KClasses_CreateFcn(hObject, eventdata, handles)
% hObject    handle to KClasses (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

% --- Executes on selection change in CepstralPopupMenu.
function CepstralPopupMenu_Callback(hObject, eventdata, handles)
% hObject    handle to CepstralPopupMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns CepstralPopupMenu contents as cell array
%        contents{get(hObject,'Value')} returns selected item from CepstralPopupMenu

% --- Executes during object creation, after setting all properties.
function CepstralPopupMenu_CreateFcn(hObject, eventdata, handles)
% hObject    handle to CepstralPopupMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

% --- Executes on button press in RangeSpecify.
function RangeSpecify_Callback(hObject, eventdata, handles)
% hObject    handle to RangeSpecify (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of RangeSpecify

state = get(hObject,'Value');

if state
    set(handles.KClasses,'Enable','off');
    set(handles.text3,'Visible','on');
    set(handles.MinClusters,'Visible','on');
    set(handles.text4,'Visible','on');
    set(handles.MaxClusters,'Visible','on');
else
    set(handles.KClasses,'Enable','on');
    set(handles.text3,'Visible','off');
    set(handles.MinClusters,'Visible','off');
    set(handles.text4,'Visible','off');
    set(handles.MaxClusters,'Visible','off');
end

% --- Executes on selection change in DistancePopupMenu.
function DistancePopupMenu_Callback(hObject, eventdata, handles)
% hObject    handle to DistancePopupMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns DistancePopupMenu contents as cell array
%        contents{get(hObject,'Value')} returns selected item from DistancePopupMenu

contents = get(hObject,'String');

dstring = contents{get(hObject,'Value')};

switch dstring
    case 'Squared Euclidean'
        handles.distancemeasure = 'sqEuclidean'
    case 'City Block (L1)'
        handles.distancemeasure = 'cityblock'
    case 'Cosine'
        handles.distancemeasure = 'cosine'
    case 'Correlation'
        handles.distancemeasure = 'correlation'
end

guidata(gcbo,handles);

% --- Executes during object creation, after setting all properties.
function DistancePopupMenu_CreateFcn(hObject, eventdata, handles)
% hObject    handle to DistancePopupMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

handles.distancemeasure = 'sqEuclidean';

guidata(gcbo,handles);

% --- Executes on button press in DiagnosticCheckbox.
function DiagnosticCheckbox_Callback(hObject, eventdata, handles)
% hObject    handle to DiagnosticCheckbox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of DiagnosticCheckbox

function pcaplot(matrix2classify,classification)
% Plots the first two principal components uses different shapes selected
% randomly and different colors selected randomly to show classes.

nclusters = length(unique(classification));

if not(isempty(find(classification == 0)))
    nclusters = nclusters -1;
end

colors = rand(nclusters,3);
mark = mod(1:nclusters,13)+1;

[coef, score] = princomp(matrix2classify);

figure();

for i = 1:length(classification)
    h = line(score(i,1),score(i,2));
    markers = set(h,'Marker');
    if classification(i) == 0 % For segments which are not classified
        set(h,'Marker',markers{4});
        set(h,'Color',[0 0 0]);
    else
        set(h,'Marker',markers{mark(classification(i))});
        set(h,'Color',colors(classification(i),:));
    end
end

xlabel('PCA 1');
ylabel('PCA 2');

function classifymatrix = madnormalize(classifymatrix, cols2normalize)
  for i = cols2normalize
    classifymatrix(:,i) = (classifymatrix(:,i) - median(classifymatrix(:,i))) / mad(classifymatrix(:,i));
  end

% This code is modified from http://phys.columbia.edu/~aylin/clustering

function c=cluster_aylin(p1,p2);
%enter the p1,p2 found from hneighbors.m and get the struct array c.
%c(i).c will contain the indices of the objects that is in cluster i.
%c(1).c will be the cluster that has the maximum number of objects.
nn=size(p1,2);
p=std(p1);g=p(p2);p=p';
z=zeros(nn,1);zz=zeros(nn,1);
n=zeros(1,nn);
for i=1:nn
    n(i)=max(max(p1(:,p2(:,i))));
end
gg=[1:nn; max(g); n]';n=find(n<1);
[q1,q1]=sort(gg(n,2)');
g=gg(n(q1),1);
t=cputime;
j=1;m=1
	for i=1:length(n)
        ii=g(i);b=p2(:,ii);a=b;aa=a(find(gg(a,2)<1));
        if length([0; unique(z(aa))])<=2;a1=1;a2=0;
            while a1~=a2;a1=length(aa);
                a=unique(p2(:,a));a=a(find(gg(a,2)<1));
                a=unique(a(find(gg(a,2)<=mean(gg(aa,2))+std(gg(aa,2)))));
                a=a(find(ismember(a,aa)==0));
                if ~isempty(a);aa=[aa;a];
                    jj=aa(find(z(aa)));
                    if ~isempty(jj);;
                         u=unique(z(jj));
                         if length(u)==1;
                            zz(aa(find(~z(aa))))=m;z(aa)=u;m=m+1;
                         end
                         break;
                    end
                end;a2=length(aa);
            end;a=aa;
            jj=a(find(z(a)));
            if isempty(jj);
                z(a)=j;j=j+1;
                zz(a)=m;zz(b)=m-.1;zz(ii)=m-.2;m=m+1;
            end
        end
    end
    u=unique(z)
    u=u(find(u));v=length(u);vv=floor(1/v);if vv;vv=' is';else vv='s      are';end
    fprintf([int2str(v) ' cluster' vv ' found in ' num2str(cputime-t) 'sec\n\n'])
	q0=[];for i=1:v;qq=find(z==u(i));q0=[q0 length(qq)];end;
    [q1,q2]=sort(q0);%q2=q2(find(100*q1/nn>1));v=length(q2);
	c=[];for i=1:v;qq=find(z==u(q2(i)));[j,j]=sort(zz(qq));c(v-i+1).c=qq(j);end;
    if isempty(c);fprintf('\tNo cluster was found. \n \tscale the data (step size must be 1)\n');end

    function [p1,p2]=hneighbors(e);
	% this function finds the neighbors of each object in 'e' within a unit hypercube
	% and returns the sorted object distances to q.q1 and their identities to q.q2 , 'e' is a
	% matrix where i th row and j th column represents the j th component of the i th object.
	s='find(';i='abs(e(:,%d)-e(i,%d))<1&';
    % assuming that the data is given scaled and the characteristic step size is 1, variable s
	% keeps a script to find the objects that lie within a unit hypercube around the i th object.
    for j=1:size(e,2);
        s=[s sprintf(i,j,j)];
	end;s([end end+1])=');';
     % runs the script s for each of the objects and stores the sorted distances
     % from the i th object in q(i).q1 and their indentities in q(i).q2
    nn=size(e,1);m=ceil(nn^(1/4));p1=ones(m,nn);p2=kron(ones(m,1),1:nn);
    for i=1:nn;
        j=eval(s);
        [q,qq]=sort(sqrt(sum((e(j,:)-kron(ones(length(j),1),e(i,:)))'.^2)));q=q(find(q<1));mm=length(q);
        qq=j(qq(1:mm))';mn=min([m mm]);
        p1(1:mn,i)=q(1:mn)';
        p2(1:mn,i)=qq(1:mn)';
    end

function classification = cluster_hierarchical(matrix2classify)
    [p1,p2] = hneighbors(matrix2classify);
    c = cluster_aylin(p1,p2);

    nclusters = size(c,2);

    total_classified = 0

    nsegments = size(matrix2classify,1);

    classification = zeros(nsegments,1);

    for i = 1:nclusters
        for j = 1:length(c(i).c)
            classification(c(i).c(j)) = i;
        end
    end
;

% --- Executes on button press in HierarchicalRadioButton.
function HierarchicalRadioButton_Callback(hObject, eventdata, handles)
% hObject    handle to HierarchicalRadioButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of HierarchicalRadioButton

selected = get(hObject,'Value');

if selected
    handles.cluster_method = 'hierarchical';
end

guidata(gcbo,handles);

% --- Executes on button press in KmeansRadioButton.
function KmeansRadioButton_Callback(hObject, eventdata, handles)
% hObject    handle to KmeansRadioButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of KmeansRadioButton

selected = get(hObject,'Value');

if selected
    handles.cluster_method = 'kmeans';
end

guidata(gcbo,handles);

function SegLenWeight_Callback(hObject, eventdata, handles)
% hObject    handle to SegLenWeight (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of SegLenWeight as text
%        str2double(get(hObject,'String')) returns contents of SegLenWeight as a double

% --- Executes during object creation, after setting all properties.
function SegLenWeight_CreateFcn(hObject, eventdata, handles)
% hObject    handle to SegLenWeight (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end


classdef Perimeter3DCompliance < handle

    properties (Access = public)

    end

    properties (Access = private)
        fileName
        topOptSet
        topOptProblem
    end

    methods (Access = public)

        function obj = Perimeter3DCompliance()
            obj.init();
            obj.createTopOptSettings();
            obj.solveProblem();
        end

    end

    methods (Access = private)

        function init(obj)
          %  obj.fileName = 'CantileverTetra';
            obj.fileName = 'CantileverFlat';
        end

        function createTopOptSettings(obj)
          t = SettingsTopOptProblem(obj.fileName);
          obj.topOptSet = t;
        end

        function solveProblem(obj)
            obj.topOptProblem = TopOpt_Problem(obj.topOptSet);
            obj.topOptProblem.computeVariables();
            obj.topOptProblem.postProcess();
        end

    end

end


function [vertex,face] = check_face_vertex(vertex,face, options)

% check_face_vertex - check that vertices and faces have the correct size
%
%   [vertex,face] = check_face_vertex(vertex,face);
%
%   Copyright (c) 2007 Gabriel Peyre

vertex = check_size(vertex);
face = check_size(face);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function a = check_size(a)
if isempty(a)
    return;
end
if size(a,1)>size(a,2)
    a = a';
end
if size(a,1)<3 && size(a,2)==3
    a = a';
end
if size(a,1)<=3 && size(a,2)>=3 && sum(abs(a(:,3)))==0
    % for flat triangles
    a = a';
end
if size(a,1)~=3 && size(a,1)~=4
    error('face or vertex is not of correct size');
end


%----STORED STREAMING CREDENTIALS----%
my_credentials = loadplotlycredentials;
try
    my_stream_token = my_credentials.stream_ids{1};
catch
    fprintf(['\nOops - No stream_keys found! please run: >>saveplotlycredentials(',...
        ' ''username'',''api_key'',''stream_key).'' \n',...
        'Your stream key(s) can be found online at: https://plot.ly or contact chuck@plot.ly',...
        'for more information.\n\n']);
    return
end

%----SETUP-----%

p = plotlyfig('visible','off');
p.data{1}.x = [];
p.data{1}.y = [];
p.data{1}.type = 'scatter';
p.data{1}.stream.token = my_stream_token;
p.data{1}.stream.maxpoints = 30;
p.PlotOptions.Strip = false;
p.PlotOptions.FileName = 'stream_test';
p.PlotOptions.FileOpt = 'overwrite';

%----PLOTLY-----%

p.plotly;

%----CREATE A PLOTLY STREAM OBJECT----%

ps = plotlystream(my_stream_token);

%----OPEN THE STREAM----%

ps.open();

%----WRITE TO THE STREAM----%

for i = 1:2000
    mydata.x = i;
    mydata.y = rand;
    ps.write(mydata);
    %take a breath
    pause(0.05);
end

%----CLOSE THE STREAM----%
ps.close;


function varargout = mesh(varargin)
%MESH   3-D mesh surface of a SPHEREFUN.
%   MESH is not supported for SPHEREFUN objects, and so returns an error.
%
% See also PLOT, SURF.

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

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

end


classdef VademecumDataLoader < handle

   properties (Access = public)
      cellDataSameSign
      cellDataDifferentSign
   end

   properties (Access = private)
        vademecumPath
        fileNameSameSign
        fileNameDiffSign
        nMx
        nMy
        nPhi
   end

   methods (Access = public)

       function obj = VademecumDataLoader(cParams)
            obj.init(cParams);
            obj.loadVademecumDataBase();
       end

   end

   methods (Access = private)

       function init(obj,cParams)
          obj.nMx = cParams.nMx;
          obj.nMy = cParams.nMy;
          obj.nPhi = cParams.nPhi;
          obj.vademecumPath = '/media/alex/My Passport/Vademecum/';
          obj.fileNameSameSign = 'OptimalSuperEllipseSameStressSign';
          obj.fileNameDiffSign = 'OptimalSuperEllipseDifferentStressSign';
       end

        function loadVademecumDataBase(obj)
            cS = cell(obj.nMx,1);
            cD = cell(obj.nMx,1);
            for iMx = 1:obj.nMx
                [cS{iMx},cD{iMx}] = obj.loadBothVademecum(iMx);
            end
            obj.cellDataSameSign      = cS;
            obj.cellDataDifferentSign = cD;
        end

        function [cS,cD] = loadBothVademecum(obj,iMx)
            cS = obj.loadSameSignVademecum(iMx);
            cD = obj.loadDifferentSignVademecum(iMx);
        end

        function d = loadSameSignVademecum(obj,iMx)
            fName = obj.fileNameSameSign;
            d = obj.loadVademecum(fName,iMx);
        end

        function d = loadDifferentSignVademecum(obj,iMx)
            fName = obj.fileNameDiffSign;
            d = obj.loadVademecum(fName,iMx);
        end

     function cS = loadVademecum(obj,fileName,iMx)
            fName = [obj.vademecumPath,fileName,num2str(iMx),'.mat'];
            d = load(fName);
            cS = cell(obj.nMx,obj.nMy,obj.nPhi);
            for iMy = 1:obj.nMy
                for iphi = 1:obj.nPhi
                    cS{iMx,iMy,iphi}.mesh = d.c{iMx,iMy,iphi}.mesh;
                    cS{iMx,iMy,iphi}.rho = d.c{iMx,iMy,iphi}.rho;
                    cS{iMx,iMy,iphi}.q   = d.c{iMx,iMy,iphi}.q;
                    cS{iMx,iMy,iphi}.xi  = d.c{iMx,iMy,iphi}.xi;
                    cS{iMx,iMy,iphi}.phi = d.c{iMx,iMy,iphi}.phi;
                end
            end
        end

   end

end


function test_bug2511

% WALLTIME 00:20:00
% MEM 8gb
% DEPENDENCY ft_sourceplot ft_read_headshape

t1 = ft_read_mri(dccnpath('/home/common/matlab/spm8/canonical/single_subj_T1.nii'));
load(dccnpath('/home/common/matlab/fieldtrip/data/test/bug2511.mat'));

% loading the data takes quite some time, as it is 4.7GB on disk, which is
% a bit silly, because only 1 variable is used, and the whole
% XXX.cfg.previous...... is not needed. JM reduced the file size on
% 20140629

cfg                  = [];
cfg.parameter        = 'avg.pow';
cfg.interpmethod    = 'sphere_avg';
sourceDiffIntAVG     = ft_sourceinterpolate(cfg, AverageSource ,t1);

cfgS                     = [];
cfgS.funparameter        = 'avg.pow';
cfgS.funcolormap         = 'jet';
cfgS.opacitylim          = [0 1];
cfgS.opacitymap          = 'rampup';
cfgS.method              = 'surface';
cfgS.projmethod          = 'nearest';
cfgS.interactive         = 'yes';
% cfgS.surffile            = 'surface_l4_both.mat'; % this was causing the problem, the file was removed from FT
cfgS.surffile            = 'surface_white_both.mat'; % this is the new surface that should be used instead
cfgS.surfdownsample      = 10;
cfgS.funcolorlim         = 'maxabs';
cfgS.interactive         = 'yes';
ft_sourceplot(cfgS, sourceDiffIntAVG);

%% error occurs with
% addpath(dccnpath('/home/common/matlab/fieldtrip/'));
%% but not with
% addpath(dccnpath('/home/common/matlab/fieldtrip-20131231/'));

%% Error description
%
% the input is volume data with dimensions [91 109 91]
% scaling anatomy to [0 1]
% no masking parameter
% The source data is defined on a 3D grid, interpolation to a surface mesh will be performed
% Warning: could not determine filetype of surface_l4_both.mat
% > In fileio/private/ft_warning at 158
%   In ft_filetype at 1189
%   In ft_read_headshape at 110
%   In ft_sourceplot at 890
% Error using ft_read_headshape (line 888)
% unknown fileformat "unknown" for head shape information
%
% Error in ft_sourceplot (line 890)
%     surf  = ft_read_headshape(cfg.surffile);


function [C_smooth]=patchSmoothFaceMeasure(varargin)

% function [C_smooth]=patchSmoothFaceMeasure(F,V,C,smoothPar)

%% Parse input
switch nargin
    case 3
        F=varargin{1};
        V=varargin{2};
        C=varargin{3};
        smoothPar=[];
    case 4
        F=varargin{1};
        V=varargin{2};
        C=varargin{3};
        smoothPar=varargin{4};
end

smoothParDefault.lambda=0.5;
smoothParDefault.n=1;
smoothParDefault.faceFaceConnectivity=[];
smoothPar=structComplete(smoothPar,smoothParDefault,1);

%% Get connectivity array
if isempty(smoothPar.faceFaceConnectivity)
    [connectivityStruct]=patchConnectivity(F,V);
    faceFaceConnectivity=connectivityStruct.face.face;
end

%%

numSmoothIterations=smoothPar.n;
lambdaSmooth=smoothPar.lambda;

%%

nDims=size(C,2); %Number of dimensions
logicValid=faceFaceConnectivity>0;
C_smooth=C;
C_smooth_step=C;
for qIter=1:numSmoothIterations
    %Loop for all dimensions
    for qDim=1:1:nDims
        Xp=NaN(size(C,1),size(faceFaceConnectivity,2));
        Xp(logicValid)=C_smooth(faceFaceConnectivity(logicValid),qDim);
        Xp=gnanmean(Xp,2);
        C_smooth_step(:,qDim)=Xp;
    end
    C_smooth=((1-lambdaSmooth).*C_smooth)+(lambdaSmooth.*C_smooth_step);
end
%%
% _*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/>.