function  FileC = file2cell(FileNameS, opt)
%Put a file into a cellarray.  Each cell is a
%line converted to a character string.
%If opt is set to 'spreadsheet', each word on each line becomes a cell within a
%cell array for each line, which is in a cell array of all lines.
%If opt is not present, each line becomes a character cell in a cell array.
%copyright (c) 2001, J.O. Deasy and Washington University in St. Louis.
%Use is granted for non-commercial and non-clinical applications.
%No warranty is expressed or implied for any use whatever.
%
%LM:  14 Feb 02, JOD.
%   13 Mar 03, JOD.  Added 'spreadsheet' option.
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

spread = 0;
if nargin > 1
  if strcmpi(opt,'spreadsheet')
    spread = 1;
  end
end

try
  fid = fopen(FileNameS,'r');
  FileV = fread(fid);
  fclose(fid);
catch
  FileC = {}
  warning(['Attempt to open ' FileNameS ' failed!'])
  return
end

FileC={};

if ~isempty(FileV)

  if any([FileV == 13])
    Newline = 13; %Define value of newline character; start assuming PC value, but check for UNIX below.
    FileV(FileV == 10) = []; %remove UNIX 'corruption'
  else
    Newline = 10;  %raw UNIX
  end

  %Break into lines.  Find all the newline characters.
  [LocationV] = find(FileV == Newline);

  %Reprocess to a cellarray
  Start = 1;
  for i = 1:length(LocationV)
    Stop = LocationV(i);

    strV = char(FileV(Start:Stop-1))';
    if spread == 0
      FileC{i} = strV;
    elseif spread == 1
      FileC{i} = str2Cell(strV, 'convert');
    end

    Start = Stop + 1;
  end

end


function colors = colorcube_colors(varargin)

wh = [10 11 13 17 18 21 22 23 28 30 32 24 36];

nofigs = isempty(findobj(0, 'Type', 'Figure'));

cm = colormap('colorcube');
cm = [cm(wh, :); cm];

% Maybe different versions of mat2cell? Not so stable...
nc = ones(size(cm, 1), 1);
try
    cm = mat2cell(cm, nc, 3)';
catch
    cm = mat2cell(cm, ones(nc, 1))';
end

colors = cm;

if nofigs
    % we created one for colormap, so close
    close
end

if ~isempty(varargin)
    n = varargin{1};

    while length(colors) < n, colors = [colors colors]; end

    colors = colors(1:n);
end

end


function [img, mmPerVox, hdr, filename, fullHeader] = loadAnalyze(filename, endianType, nativeTypeFlag, overrideScale)
% function [img, mmPerVox, hdr, filename, fullHeader] = loadAnalyze(analHeaderFileName, ...
%   [endianType], [nativeTypeFlag], [overrideScale]);
%
% Reads Analyze7.5 image data into a matlab array 'img'.
% Certain parts of the Analyze header info are stored in 'hdr'.
%
% If you pass in the (optional) endianType it will use this when
% reading 16bit data files. Defaults to 'ieee-le' (little-endian- intel).
% Another common option is 'ieee-be' (big-endian, ie. non-intel).
% NOTE: as of 2004.02.25, the endianType is automatiacally determined, so
% this parameter is not needed and should go away. It is currently silently
% ignored.
%
% If nativeTypeFlag is 1 (default = 0), then the data are returned in an
% array of the same type as the file data. Eg. int16, uint8, etc.
%
% If overrideScale is passed, the passed value is used to scale the data
% rather than the value in the Analyze file header.  This is useful for
% incorrectly formated Analyze files.
%
% After this routine scales the image data, it sets the scale factor in
% returned hdr.pinfo(1) = 1.  This allows backward compatibility with
% routines that performed the scaling outside of this routine, before
% we folded the scaling in.  We don't see any obvious problem with this
% action, but it does deviate from what you would get if you used the
% routine pair hdr = spm_vol(filename); img = spm_read_vols(hdr).  This
% would result in the returned data being scaled (as here), but the hdr
% would in that case still have the scale factor used.
%
% NOTE: as of 2004.02.25, the hdr.dim(4) value is no longer spm-compatible.
% Spm uses this 4th dimension to store the data type. We now return that
% separately. Thus, we are ready to allow 4-dimensional data files.
%
% REQUIRES:
%   No longer requires spm code. We now use a function adapted from
%   Worsley's fmristat (http://www.math.mcgill.ca/~keith/fmristat/)
%   This function (fmris_read_analyze) should be in our repository.
%
% SEE ALSO: analyze2mrGray, mrGray2Analyze, spm_read_vols
%  In particular, analyze2mrGray provides an example of how to orient the
%  data for mrGray.
% s
% HISTORY:
%   2001.12.13 RFD (bob@white.stanford.edu) wrote it.
%   2003.06.13 DHB (brainard@psych.upenn.edu)  Change comment above,
%       as default for nativeTypeFlag is in fact 0 as coded, not 1 as
%       the previous comment said.
%  2003.06.18  DHB (brainard@psych.upenn.edu)  Multiply read image data
%       by scale factor in header.  Set this scale factor to 1 in returned
%       data.  Also added overrideScale arg.   This change made after
%       consultation with RFD.
%  2003.07.03 RFD Fixed typo-looking bug that prevented the scale factor
%       from getting set to 1.
%  2004.01.06 RFD: Replaced "hdr = spm_vol(filename);" with the relevant
%  lines of code from that spm function. We do this because the mmPerVox
%  value in the Analyze header is more likely to be accurate than the one
%  in the spm space-transform 'mat' file. That scale factor is still
%  available in the transform matrix (hdr.mat). Note that this change will
%  only affect those of us who dare to use the spm-style transform files
%  with our analyze data. (This is a third file, in addition to the .img
%  and .hdr files, that is a matlab 'mat' file containing extra spatial
%  transform info that doesn't fit into the Analyze header, such as a full
%  affine transform.)
%  2004.02.25 RFD: Removed spm-dependent code. We now use a function
%  adapted from FMRISTAT (fmris_read_analyze).
%

disp('Obsolete.  Use analyzeRead');
evalin('caller','mfilename');

if ~exist('filename','var') | isempty(filename)
   [fname, fpath] = uigetfile({'*.img','Analyze 7.5 format (*.img)'}, 'Select analyze volume file...');
   filename = [fpath fname];
   if fname == 0  % user cancelled
      return;
   end
end
%[p,f,ext] = fileparts(filename);

% Fix filename to point to the .img file.
[p,f,e] = fileparts(filename);
if(strcmpi(e,'.hdr'))
    filename = fullfile(p,[f '.img']);
elseif(isempty(e) | ~strcmpi(e,'.img'))
    % This will allow dots in the filename
    filename = [filename '.img'];
end
baseFilename = filename(1:end-4);

% Note that the following applies the scale factor for us.
d = fmris_read_analyze(filename);
img = d.data;
mmPerVox = d.vox(1:3);
filename = d.file_name;
fullHeader = d.hdr;
hdr.fname = d.file_name;
hdr.dim = d.dim;
% build spm-style mat field
d.vox = d.vox(1:3);
%hdr.mat = [[diag(d.vox), [d.origin.*-d.vox-d.vox./2]']; [0 0 0 1]];
hdr.mat = [[diag(d.vox), [d.origin.*-d.vox]']; [0 0 0 1]];
hdr.pinfo = [d.scale;0;d.vox_offset];
hdr.descrip = d.descrip;

% NOTE: no longer needed- fmris_read_analyze automatically determins this.
if (exist('endianType','var') & ~isempty(endianType))
    disp([mfilename ': endianType no longer needed- it will be silently ignored.']);
end
if ~exist('nativeTypeFlag','var') | isempty(nativeTypeFlag)
    nativeTypeFlag = 0;
end
if ~exist('overrideScale','var') | isempty(overrideScale)
    overrideScale = 0;
end

% load an spm-style transform file, if it exists
xformFile = [baseFilename '.mat'];
if(exist(xformFile, 'file'))
    xform = load(xformFile);
    hdr.mat = xform.M;
end

% We could check the file size (d.bytes) against the expected number of bytes.
% d = dir(hdr.fname);
% if(length(d)<1)
%     error (['Could not find image file (',hdr.fname,') for this header file (',analHeaderFileName,').']);
% end

% Override scale factor in header?
% Note that the scale factor has already been applied, so we only have to
% apply and 'ajustment' if a different scale is desired.
if (overrideScale)
    hdr.pinfo(1) = overrideScale;
    img = overrideScale./hdr.pinfo(1).*img;
end

% Since the scale factor has been applied, we set it to 1 so that old code
% will still work.
hdr.pinfo(1) = 1;

if (nativeTypeFlag)
    eval(['img=' d.precision '(img);'], ...
        ['disp(''could not convert to native type "' d.precision '"'');']);
end

return


function net_inputs = rfcn_get_minibatch(conf, image_roidb)
% net_inputs = rfcn_get_minibatch(conf, image_roidb)
% --------------------------------------------------------
% D&T implementation
% Modified from MATLAB  R-FCN (https://github.com/daijifeng001/R-FCN/)
% and Faster R-CNN (https://github.com/shaoqingren/faster_rcnn)
% Copyright (c) 2017, Christoph Feichtenhofer
% Licensed under The MIT License [see LICENSE for details]
% --------------------------------------------------------
    visualize = false;

    num_images = length(image_roidb);
    if num_images == 0
      net_inputs = NaN; return;
    end
    if conf.bbox_class_agnostic
        num_classes = 1;
    else
        % Infer number of classes from the number of columns in gt_overlaps
        num_classes = size(image_roidb(1).overlap, 2);
    end
    % Sample random scales to use for each image in this batch
    random_scale_inds = randi(length(conf.scales), num_images, 1);

    if conf.batch_size > 0
        assert(mod(conf.batch_size, num_images) == 0, ...
        sprintf('num_images %d must divide BATCH_SIZE %d', num_images, conf.batch_size));

        rois_per_image = conf.batch_size / num_images;
        fg_rois_per_image = round(rois_per_image * conf.fg_fraction);
    else
        rois_per_image = inf;
        fg_rois_per_image = inf;
    end
    if conf.use_flipped
      flip_im = rand(num_images,1) > .5;
      if isfield(conf,'sample_vid') && conf.sample_vid, flip_im = repmat(flip_im(1), size(flip_im)); end;
    else
      flip_im = zeros(num_images,1) ;
    end
    % Get the input image blob
    [im_blob, im_scales] = get_image_blob(conf, image_roidb, random_scale_inds, flip_im);
    if isnan(im_blob), net_inputs = NaN; return; end
    % build the region of interest and label blobs
    rois_blob = zeros(0, 5, 'single');
    labels_blob = zeros(0, 1, 'single');
    bbox_targets_blob = zeros(0, 4 * (num_classes+1), 'single');
    bbox_loss_blob = zeros(size(bbox_targets_blob), 'single');
    track_rois_blob = rois_blob; track_targets_blob = bbox_targets_blob; track_loss_blob = bbox_loss_blob;
    for i = 1:num_images
        [labels, ~, im_rois, bbox_targets, bbox_loss] = ...
            sample_rois(conf, image_roidb(i), fg_rois_per_image, rois_per_image);

        if flip_im(i)
            im_rois(:, [1, 3]) = image_roidb(i).im_size(2) + 1 - im_rois(:, [3, 1]);
            %flip horizontal regression target: targets_dx = (gt_ctr_x - ex_ctr_x) ./ (ex_widths+eps);
            bbox_targets(:, 5) = - bbox_targets(:, 5);
        end

        if visualize
          im = (imread(  image_roidb(i).image_path ));
          boxes_cell = {im_rois(:,:)};

          figure('windowstyle','docked');
          imd(im);
          drawBBoxes(im_rois(:,:), 'LineWidth', 1);
        end

        % Add to ROIs blob
        feat_rois = rfcn_map_im_rois_to_feat_rois(conf, im_rois, im_scales(i));
        batch_ind = i * ones(size(feat_rois, 1), 1);
        rois_blob_this_image = [batch_ind, feat_rois];
        rois_blob = [rois_blob; rois_blob_this_image];

        % Add to labels, bbox targets, and bbox loss blobs
        labels_blob = [labels_blob; labels];
        bbox_targets_blob = [bbox_targets_blob; bbox_targets];
        bbox_loss_blob = [bbox_loss_blob; bbox_loss];

        if isfield(image_roidb(i), 'track_targets') && ~isempty(image_roidb(i).track_targets)
          [track_targets, track_loss_weights] = get_bbox_regression_labels(conf,  image_roidb(i).track_targets, num_classes);

          if flip_im(i)
             image_roidb(i).track_rois(:, [1, 3])  = image_roidb(i).im_size(2) + 1 - image_roidb(i).track_rois(:, [3, 1]);
             track_targets(:, 5) = - track_targets(:, 5);
          end
            track_rois_blob = [track_rois_blob; [ones(size(image_roidb(i).track_rois, 1), 1), rfcn_map_im_rois_to_feat_rois(conf, image_roidb(i).track_rois, im_scales(i))]];
            track_targets_blob = [track_targets_blob; track_targets];
            track_loss_blob = [track_loss_blob; track_loss_weights];
        end
    end

    % permute data into caffe c++ memory, thus [num, channels, height, width]
    im_blob(:, :, 1:3, :) = im_blob(:, :, [3, 2, 1], :); % from rgb to brg
    if size(im_blob,3) > 3
      im_blob(:, :, 4:6, :) = im_blob(:, :, [6, 5, 4], :); % from rgb to brg
    end
    im_blob = single(permute(im_blob, [2, 1, 3, 4]));
    rois_blob = rois_blob - 1; % to c's index (start from 0)
    rois_blob = single(permute(rois_blob, [3, 4, 2, 1]));
    labels_blob = single(permute(labels_blob, [3, 4, 2, 1]));
    bbox_targets_blob = single(permute(bbox_targets_blob, [3, 4, 2, 1]));
    bbox_loss_blob = single(permute(bbox_loss_blob, [3, 4, 2, 1]));

    track_rois_blob = track_rois_blob -1;
    track_rois_blob = single(permute(track_rois_blob, [3, 4, 2, 1]));
    track_targets_blob = single(permute(track_targets_blob, [3, 4, 2, 1]));
    track_loss_blob = single(permute(track_loss_blob, [3, 4, 2, 1]));

    try
    assert(~isempty(im_blob));
    assert(~isempty(rois_blob));
    assert(~isempty(labels_blob));
    assert(~isempty(bbox_targets_blob));
    assert(~isempty(bbox_loss_blob));
    catch
      fprintf('no object in image %s\n', image_roidb(1).image_path );
       net_inputs = NaN; return;
    end
    if ~isempty(track_rois_blob)
      net_inputs = {im_blob, rois_blob, labels_blob, bbox_targets_blob, bbox_loss_blob, ...
        track_rois_blob, track_targets_blob, track_loss_blob};
    else
      net_inputs = {im_blob, rois_blob, labels_blob, bbox_targets_blob, bbox_loss_blob};
    end

end

%% Build an input blob from the images in the roidb at the specified scales.
function [im_blob, im_scales] = get_image_blob(conf, images, random_scale_inds, flip_im)

    num_images = length(images);
    processed_ims = cell(num_images, 1);
    im_scales = nan(num_images, 1);
    for i = 1:num_images
      try
        if ~ispc
          images(i).image_path = strrep(images(i).image_path,'\','/');
        end
        nFrames = 1;
       if isfield(conf, 'nFrames')
         nFrames = conf.nFrames;
       end
        if isfield(conf, 'input_modality') && ~strcmp(conf.input_modality, 'rgb')
          if strcmp(conf.input_modality, '2framergb') || strcmp(conf.input_modality, 'framebatch')
            time_stride = 10;
             if isfield(conf, 'time_stride')
               time_stride = conf.time_stride;
             end
            [vid, frame, ext] = fileparts(images(i).image_path);
            nextframe = fullfile(vid, [sprintf('%06d',str2num(frame)+time_stride) ext]) ;
            frames = str2num(frame)-nFrames/2*time_stride:time_stride:str2num(frame)+nFrames/2*time_stride;
            im = {};
            for frame=frames
              nextframe = fullfile(vid, [sprintf('%06d',frame) ext]) ;
              im{end+1} = imread(nextframe);
            end
            if strcmp(conf.input_modality, 'framebatch')
              im = cat(4,im{:});
            else
              im = cat(3,im{:});
            end

          else
            if strcmp(images(i).imdb_name(1:12), 'ilsvrc15_vid')
              img_file_u = strrep(images(i).image_path, ['Data' filesep 'VID'], ...
                ['Data' filesep 'VID' filesep 'tvl1_flow_600' filesep 'u'] ) ;
              img_file_v = strrep(images(i).image_path, ['Data' filesep 'VID'], ...
                ['Data' filesep 'VID' filesep 'tvl1_flow_600' filesep 'v'] ) ;
              try
                [path_u, ~, ~] = fileparts(img_file_u);
                [path_v, frame, ext] = fileparts(img_file_v);
                frames = str2num(frame)-nFrames+1:str2num(frame)+nFrames-1;
                frames(frames <0) = 0; frames(frames > imdb.num_frames(i)) = imdb.num_frames(i);
                im_u = []; im_v = [];
                for frame=frames
                  img_file_u = fullfile(path_u, [sprintf('%06d',frame), ext]) ;
                  img_file_v = fullfile(path_v, [sprintf('%06d',frame), ext]) ;
                  im_u{end+1} = imread(img_file_u); im_v{end+1} = imread(img_file_v);
                end
                im_u = cat(3,im_u{:});im_v = cat(3,im_v{:});
              end
            else
              im_u = 128*ones(images(i).im_size); im_v = 128*ones(images(i).im_size);
            end
            sz = size(im_u);
          end
          switch conf.input_modality
            case 'flow'
              flow = single(cat(3,im_u,im_v)) - 128;
              flow = bsxfun(@minus,flow, median(median(flow,1),2)) ;
              mag_flow = sqrt(sum(flow.^2,3)) - 128;
              im = (cat(3,flow,mag_flow));
              im = imresize( im, images(i).im_size);
            case 'grayflow'
              imrgb = imread(images(i).image_path); sz = size(imrgb);
              imgray = rgb2gray(imrgb);
              flow = single(cat(3,im_u,im_v)) ;
              im = cat(3,imresize( flow, sz(1:2)),imgray);
            case 'rgbflow'
            if isfield(conf, 'subflow_mean') && ~conf.subflow_mean
              flow = single(cat(3,im_u,im_v));
            else
              flow = single(cat(3,im_u,im_v)) - 128;
            end
            imrgb = single(imread(images(i).image_path));

            if size(imrgb,3) < 3
              imrgb = imrgb(:,:,[1 1 1]);
            end
            sz = size(imrgb);
            im = cat(3,imrgb,imresize( flow, sz(1:2)));
          end
        else
            im = imread(images(i).image_path);
        end
      catch
        fprintf('could not read %s\n', images(i).image_path);
        im_blob = NaN;
        return;
      end
        target_size = conf.scales(random_scale_inds(i));

        if flip_im(i)
            im = fliplr(im);
        end
        [im, im_scale] = prep_im_for_blob(im, conf.image_means, target_size, conf.max_size);
        if isfield(conf,'image_std')
          im = bsxfun(@rdivide, im, conf.image_std);
        end
        im_scales(i) = im_scale;
        processed_ims{i} = im;
    end

    im_blob = im_list_to_blob(processed_ims);
end

%% Generate a random sample of ROIs comprising foreground and background examples.
function [labels, overlaps, rois, bbox_targets, bbox_loss_weights] = sample_rois(conf, image_roidb, fg_rois_per_image, rois_per_image)

    [overlaps, labels] = max(image_roidb(1).overlap, [], 2);
    rois = image_roidb(1).boxes;

    % Select foreground ROIs as those with >= FG_THRESH overlap
    fg_inds = find(overlaps >= conf.fg_thresh);
    % Guard against the case when an image has fewer than fg_rois_per_image
    % foreground ROIs
    fg_rois_per_this_image = min(fg_rois_per_image, length(fg_inds));
    % Sample foreground regions without replacement
    if ~isempty(fg_inds)
       fg_inds = fg_inds(randperm(length(fg_inds), fg_rois_per_this_image));
    end

    % Select background ROIs as those within [BG_THRESH_LO, BG_THRESH_HI)
    bg_inds = find(overlaps < conf.bg_thresh_hi & overlaps >= conf.bg_thresh_lo);
    % Compute number of background ROIs to take from this image (guarding
    % against there being fewer than desired)
    bg_rois_per_this_image = rois_per_image - fg_rois_per_this_image;
    bg_rois_per_this_image = min(bg_rois_per_this_image, length(bg_inds));
    % Sample foreground regions without replacement
    if ~isempty(bg_inds)
       bg_inds = bg_inds(randperm(length(bg_inds), bg_rois_per_this_image));
    end
    % The indices that we're selecting (both fg and bg)
    keep_inds = [fg_inds; bg_inds];
    % Select sampled values from various arrays
    labels = labels(keep_inds);
    % Clamp labels for the background ROIs to 0
    labels((fg_rois_per_this_image+1):end) = 0;
    overlaps = overlaps(keep_inds);
    rois = rois(keep_inds, :);

    if conf.bbox_class_agnostic
        assert(all((labels>0) == image_roidb.bbox_targets(keep_inds, 1)));
    else
        assert(all(labels == image_roidb.bbox_targets(keep_inds, 1)));
    end

    % Infer number of classes from the number of columns in gt_overlaps
    num_classes = size(image_roidb(1).overlap, 2);

    [bbox_targets, bbox_loss_weights] = get_bbox_regression_labels(conf, ...
        image_roidb.bbox_targets(keep_inds, :), num_classes);

end

function [bbox_targets, bbox_loss_weights] = get_bbox_regression_labels(conf, bbox_target_data, num_classes)
%% Bounding-box regression targets are stored in a compact form in the roidb.
 % This function expands those targets into the 4-of-4*(num_classes+1) representation used
 % by the network (i.e. only one class has non-zero targets).
 % The loss weights are similarly expanded.
% Return (N, (num_classes+1) * 4, 1, 1) blob of regression targets
% Return (N, (num_classes+1 * 4, 1, 1) blob of loss weights
    if conf.bbox_class_agnostic
        num_classes = 1;
    end

    clss = bbox_target_data(:, 1);
    bbox_targets = zeros(length(clss), 4 * (num_classes+1), 'single');
    bbox_loss_weights = zeros(size(bbox_targets), 'single');
    inds = find(clss > 0);
    for i = 1:length(inds)
       ind = inds(i);
       cls = clss(ind);
       targets_inds = (1+cls*4):((cls+1)*4);
       bbox_targets(ind, targets_inds) = bbox_target_data(ind, 2:end);
       bbox_loss_weights(ind, targets_inds) = 1;
    end
end


function out = input2(text,def)
    %
    %	out = input2(text,default)
    %
    %	Compliments of Charles Stark Draper Labs
    if ischar(def) == 1
        eval(['y = input('' ',text,' [',def,'] '',''s'');'])
        if isempty(y)
            out = def;
        else
            out = y;
        end
    else
        eval(['y = input('' ',text,' [',num2str(def),'] '',''s'');'])
        if isempty(y)
            out = def;
        else
            out = eval(y);
        end
    end


function t_end
%T_END  Finish running tests and print statistics.
%   T_END checks the global counters that were updated by calls to
%   T_OK, T_IS and T_SKIP and prints out a summary of the test results.
%
%   Example:
%       quiet = 0;
%       t_begin(5, quiet);
%       t_ok(pi > 3, 'size of pi');
%       t_skip(3, 'not yet written');
%       t_is(2+2, 4, 12, '2+2 still equals 4');
%       t_end;
%
%   See also T_BEGIN, T_OK, T_IS, T_SKIP, T_RUN_TESTS.

%   MP-Test
%   Copyright (c) 2004-2020, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MP-Test.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://github.com/MATPOWER/mptest for more info.

global t_quiet;
global t_num_of_tests;
global t_counter;
global t_ok_cnt;
global t_not_ok_cnt;
global t_skip_cnt;
global t_clock;

t_counter = t_counter - 1;

if t_counter == t_num_of_tests && ...
        t_counter == t_ok_cnt + t_skip_cnt && ...
        t_not_ok_cnt == 0
    all_ok = 1;
else
    all_ok = 0;
end

if t_quiet
    if all_ok
        fprintf('ok');
        if t_skip_cnt
            fprintf(' (%d of %d skipped)', t_skip_cnt, t_num_of_tests);
        end
    else
        fprintf('not ok\n');
        fprintf('\t#####  Ran %d of %d tests: %d passed, %d failed', ...
            t_counter, t_num_of_tests, t_ok_cnt, t_not_ok_cnt);
        if t_skip_cnt
            fprintf(', %d skipped', t_skip_cnt);
        end
    end
    fprintf('\n');
else
    if all_ok
        if t_skip_cnt
            fprintf('All tests successful (%d passed, %d skipped of %d)', ...
                t_ok_cnt, t_skip_cnt, t_num_of_tests);
        else
            fprintf('All tests successful (%d of %d)', t_ok_cnt, t_num_of_tests);
        end
    else
        fprintf('Ran %d of %d tests: %d passed, %d failed', ...
            t_counter, t_num_of_tests, t_ok_cnt, t_not_ok_cnt);
        if t_skip_cnt
            fprintf(', %d skipped', t_skip_cnt);
        end
    end
    fprintf('\nElapsed time %.2f seconds.\n', toc(t_clock));
end


function model = createEmptyFields(model,fieldNames, fieldDefinitions)
% Create the specified model field with its default values. Works only for
% fields defined in the toolbox if fieldDefinitions are not supplied.
%
% USAGE:
%    model = createEmptyFields(model,fieldName, fieldDefinitions)
%
% INPUTS:
%
%    model:                 The model to add a field to
%    fieldNames:            The names of the fields to add.
%
% OPTIONAL INPUTS:
%    fieldDefinitions:      The Specifications of the field. Only necessary
%                           if a field which is not defined yet should be
%                           added.
%
% OUTPUTS:
%
%    model:                 The original model struct with the specified
%                           field added.
%
% Author:
%    Thomas Pfau Nov 2017

if ischar(fieldNames)
    fieldNames = {fieldNames};
end

if ~exist('fieldDefinitions','var') || isempty(fieldDefinitions)
    fieldDefinitions = getDefinedFieldProperties('SpecificFields',fieldNames);
end

if isempty(fieldDefinitions)
    error('Supplied Field name invalid.')
end
for field = 1:length(fieldNames)
    %Get the dimensions
    xdim = fieldDefinitions{field,2};
    ydim = fieldDefinitions{field,3};

    %And adjust if necessary
    if isnan(xdim)
        xdim = 1;
    end

    %If its listed as a char, it refers to a field (and the first dimension
    %of that field)
    if ischar(xdim)
        if isfield(model,xdim)
            xdim = size(model.(xdim),1);
        else
            xdim = 0;
        end
    end

    if isnan(ydim)
        ydim = 1;
    end

    %If its listed as a char, it refers to a field (and the first dimension
    %of that field)
    if ischar(ydim)
        if isfield(model,ydim)
            ydim = size(model.(ydim),1);
        else
            ydim = 0;
        end
    end

    %Get the field definitions
    fieldType = fieldDefinitions{field,7};
    defaultValue = fieldDefinitions{field,5};
    %define i, for checks relating to model fields which have non ''
    %defaults
    i = 1;
    switch fieldType
        case 'sparse'
            model.(fieldNames{field}) = sparse(xdim,ydim);
        case 'cell'
            model.(fieldNames{field}) =cell(xdim,ydim);
            % need to both check, whether the eval is a char AND if it is empty.
            if xdim > 0 && ischar(eval(defaultValue)) && strcmp(eval(defaultValue),'')
                model.(fieldNames{field})(:) = {''};
            else
                for i = 1:xdim
                    eval(['currentvalue = ' defaultValue ';' ]);
                    model.(fieldNames{field}){i} = currentvalue;
                end
            end
        case 'numeric'
            model.(fieldNames{field}) = repmat(defaultValue,xdim,ydim);
        case 'sparselogical'
            model.(fieldNames{field}) = sparse(repmat(logical(defaultValue),xdim,ydim));
        case 'char'
            model.(fieldNames{field}) = repmat(defaultValue,xdim,ydim);
    end
end


function [ obj ] = remove( obj, idx )
% Remove data (fMRI time series, confounds, DCM network structure, ... )
% and estimation results from HUGE object.
%
% INPUTS:
%   obj - A tapas_Huge object.
%
% OPTIONAL INPUTS:
%   idx - Only remove data of the subjects indicated in 'idx'. 'idx' must
%         be a vector containing numeric or logical array indices.
%
% OUTPUTS:
%   obj - A tapas_Huge object with data and results removed.
%
% EXAMPLES:
%   [obj] = REMOVE(obj)    Remove results and data of all subjects.
%
%   [obj] = REMOVE(obj,1:5)    Remove results and data for first 5
%                              subjects.
%
%   [obj] = REMOVE(obj,'all') is the same as [obj] = REMOVE(obj)
%
%   [obj] = REMOVE(obj,0) is the same as [obj] = REMOVE(obj)
%
% See also tapas_Huge.IMPORT
%

% Author: Yu Yao (yao@biomed.ee.ethz.ch)
% Copyright (C) 2019 Translational Neuromodeling Unit
%                    Institute for Biomedical Engineering,
%                    University of Zurich and ETH Zurich.
%
% This file is part of TAPAS, which is released under the terms of the GNU
% General Public Licence (GPL), version 3. For further details, see
% <https://www.gnu.org/licenses/>.
%
% This 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 non-infringement.
%
% This software is intended for research only. Do not use for clinical
% purpose. Please note that this toolbox is under active development.
% Considerable changes may occur in future releases. For support please
% refer to:
% https://github.com/translationalneuromodeling/tapas/issues
%

%% check input
if nargin < 2 || (ischar(idx) && strcmpi(idx, 'all'))
    idx = 0;
end

if obj.N == 0 || isempty(idx)
    return
end

if isscalar(idx) && idx == 0
    idx = 1:obj.N;
end

assert((all(idx >= 1) && all(rem(idx,1) == 0)) || islogical(idx),...
    'TAPAS:HUGE:invalidIndex',...
    'idx must be real positive integers or logicals');

assert(max(idx) <= obj.N, 'TAPAS:HUGE:invalidIndex',...
    'idx exceeds number of subjects');

if islogical(idx)
    assert(numel(idx) == obj.N, 'TAPAS:HUGE:invalidIndex',...
        'idx must have length %u', obj.N);
end

%% remove data
obj.data(idx)   = [];
obj.inputs(idx) = [];

if isnumeric(obj.options.nvp.startingvaluedcm) && ...
        ~isempty(obj.options.nvp.startingvaluedcm)
    obj.options.nvp.startingvaluedcm(idx,:) = [];
end

if ~isempty(obj.model)
    obj.model.d(idx, :) = [];
    obj.model.theta_c(idx, :) = [];
    obj.model.theta_h(idx, :) = [];
    obj.model.lambda(idx, :) = [];
    obj.model.pi = sum(obj.model.d)/sum(obj.model.d(:));
end

obj.N = numel(obj.data);
if ~obj.N
    obj = reset_properties(obj);
end

% reset prior, posterior and trace
obj.prior = [];
obj.posterior = [];
obj.trace = [];

end

function [ obj ] = reset_properties( obj )

tmp = obj.default_options();
obj.options.nvp.priorclustermean        = tmp.nvp.priorclustermean;
obj.options.nvp.priorclustervariance    = tmp.nvp.priorclustervariance;
obj.options.nvp.priordegree             = tmp.nvp.priordegree;
obj.options.nvp.priorvarianceratio      = tmp.nvp.priorvarianceratio;
obj.options.nvp.startingvaluedcm        = tmp.nvp.startingvaluedcm;
obj.options.nvp.startingvaluegmm        = tmp.nvp.startingvaluegmm;
obj.options.nvp.confoundsvariant        = tmp.nvp.confoundsvariant;

obj.R = 0;
obj.L = 0;
obj.M = 0;
obj.dcm = [];
obj.labels = struct();
obj.model = [];
obj.idx = struct();

end


function s6_resave_annot_after_remaing()
%image chnaged
% stb = load('annot_test.mat');
% base_annot = stb.videos;
% clear stb;clear all
close all
stb = load('annotV5.mat');
%stb = load('annot.mat');
base_annot = stb.videos;
clear stb;

stp = load('annot_full_Philippe.mat'); % train+test
phill_annot = stp.videos;
clear stp;

stp = load('annot_apt.mat'); % train+test
apt_annot = stp.videos;
clear stp;

baseList = {};
for i=1:length(base_annot)
    baseList{i,1} = base_annot(i).name; % store all the cor vid in a cellarray
end

philList = {};
for i=1:length(phill_annot)
    philList{i,1} = phill_annot(i).name; % store all the cor vid in a cellarray
end

aptList = {};
for i=1:length(apt_annot)
    aptList{i,1} = apt_annot(i).name; % store all the cor vid in a cellarray
end

images_dir = '/mnt/sun-alpha/datasets/UCF101/images';
save_path = './saved/';
%for v = 403 % : length(base_annot)
% rvid = randperm(length(base_annot));

% FigHandle = figure(1);
% FigHandle = figure('Position', [100, 100, 1049, 895]);
% hold on
count = 0;
load('lastdata.mat')
% merged_annot = struct();
load('merged_annot_temporal');
load('checkpoint_improved_temporal.mat')
v = 1;vc =0;
while v <= length(baseList)

    videoName = baseList{v,1};

    base_tubes = base_annot(v).tubes;

    index = find(strcmp(philList,videoName));
    phil_tubes = phill_annot(index).tubes;

    index = find(strcmp(aptList,videoName));
    apt_tubes = apt_annot(index).tubes;

    class = base_annot(v).tubes(1).class;
    num_imgs = base_annot(v).num_images;

    merged_annot(v).num_imgs = num_imgs;
    merged_annot(v).name = base_annot(v).name;

    if ~isgood(v) % && strcmp(inputs{v},'t')
        vc = vc +1;
        newcell = tdata{v};
        tline = newcell{1};
        stl = strsplit(tline,' ');

        if length(stl{1})>1
            inputs{v} = 'ra';
            isgood(v) = 0;
            merged_annot(v).tubes = base_annot(v).tubes;
        else
            merged_annot(v).tubes = extract_bounds(newcell, base_tubes, phil_tubes, apt_tubes, num_imgs,class);
            inputs{v} = 'y';
            isgood(v) = 1;
        end

    end
    v=v+1;

end
% vc
fprintf('%d\n',sum(isgood));
save('checkpoint_improved_after_remaining.mat','isgood','inputs');
save('merged_annot_remianing.mat','merged_annot')

function tubes = extract_bounds(newcell, base_tubes, phil_tubes, apt_tubes, num_imgs,class)
tubes = struct();
alltubes = {base_tubes,phil_tubes,apt_tubes};
for t = 1 : length(newcell)
    tline = newcell{t};
    stl = strsplit(tline,' ');

    if length(stl)<6
        [sf,ef,boxes] = gettube(alltubes,stl,num_imgs,0);
    else
        [sf,ef,boxes] = gettube(alltubes,stl,num_imgs,1);
    end
    tubes(t).sf = sf;
    tubes(t).ef = ef;
    tubes(t).class = class;
    tubes(t).boxes = boxes;
end

function [sf,ef,boxes] = gettube(alltubes,stl,num_imgs,isone)
tube  = [];
annotType = {'b','p','a'};
ind = find(strcmp(annotType,stl{1}));

annot = alltubes{ind};

tid = str2num(stl{2});

sf = max(str2num(stl{3}),annot(tid).sf);

ef = min(str2num(stl{4}),annot(tid).ef);
st = sf-annot(tid).sf+1;
et = ef-sf+st; ct = 1;
boxes = annot(tid).boxes(st:et,:);
if isone
    ind = find(strcmp(annotType,stl{5}));
    annot = alltubes{ind};
    tid = str2num(stl{6});
    sfa = str2num(stl{7});
    if (sfa-ef)>1
        for kk = 1:(sfa-ef-1)
            boxes = [boxes;boxes(end,:)];
        end
    end
    ef = str2num(stl{8});
    st = sfa-annot(tid).sf+1;
    et = ef-sfa+st; ct = 1;
    boxes = [boxes;annot(tid).boxes(st:et,:)];
end


%% vectorTensorProductArray
% Below is a demonstration of the features of the |vectorTensorProductArray| function

%%
clear; close all; clc;

%% Syntax
% |[AB]=vectorTensorProductArray(a,b);|

%% Description
% UNDOCUMENTED
%% Examples
%
%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>
%%
% _*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 mask=getMask_onlineEvaluation(fn_sb)
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
% @InProceedings{ZhengICCV09,
%   author = {Yuanjie Zheng and Chandra Kambhamettu},
%   title = {Learning Based Digital Matting},
%   booktitle = {The 20th IEEE International Conference on Computer Vision},
%   year = {2009},
%   month = {September--October}
% }
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
% Copyright Yuanjie Zheng @ PICSL @ UPenn on May 9th, 2011
% zheng.vision@gmail.com
% http://sites.google.com/site/zhengvision/
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
I=imread(fn_sb);
mask=zeros(size(I,1),size(I,2));
fore=(I==255);
back=(I==0);

mask(fore)=1;
mask(back)=-1;


% Author: Guosheng Lin (guosheng.lin@gmail.com)
% example code for multi-scale predictions, fusion and accuracy evaluation

function demo_predict_mscale_sunrgbd()

rng('shuffle');

addpath('./my_utils');
dir_matConvNet='../libs/matconvnet/matlab';
run(fullfile(dir_matConvNet, 'vl_setupnn.m'));

run_config=[];
ds_config=[];

run_config.use_gpu=true;
% run_config.use_gpu=false;
run_config.gpu_idx=1;

%-------------------------------------------------------------------------------------------------------------------------
% settings for using trained model:

ds_name_subfix='sunrgbd';

% result dir:
result_name=['result_' datestr(now, 'YYYYmmDDHHMMSS') '_predict_custom_data'];
result_dir=fullfile('../cache_data', ['test_examples_' ds_name_subfix], result_name);

% using a trained model:
run_config.trained_model_path='../model_trained/refinenet_res101_sunrgbd.mat'; % resnet101 based refinenet
% run_config.trained_model_path='../model_trained/refinenet_res152_sunrgbd.mat'; % resnet152 based refinenet

% provide class_info for the trained model:
ds_config.class_info=gen_class_info_sunrgbd();

% control the size of input images to avoid excessively small or large images
run_config.input_img_short_edge_min=450;
run_config.input_img_short_edge_max=800;
%-------------------------------------------------------------------------------------------------------------------------

% specify the folder that contains testing images:
img_data_dir='../datasets/example_imgs_sunrgbd';

% providing ground-truth mask folder for evaluation, or set to empty if not available
% if the folder of ground-truth masks are provided (an example is shown below),
% this code will perform evaluation after multi-scale prediction and fusion.
gt_mask_dir=[];

%-------------------------------------------------------------------------------------------------------------------------
% settings for accuracy evaluation after multi-scale prediction and fusion:
% the following example specifies images for testing and the ground-truth masks for evaluation:

% Notes: for the evaluation purpose, the image folder should only contain testing images, excluding any training images:
% Notes: the ground-truth masks should follow the class label definition in the variable specified above: 'ds_config.class_info'

% uncomment the following lines to enable accuracy evaluation, should replace by your folders:

% img_data_dir='../datasets/sunrgbd/images_testonly';
% gt_mask_dir='../datasets/sunrgbd/gt_testonly';
%-------------------------------------------------------------------------------------------------------------------------

%-------------------------------------------------------------------------------------------------------------------------
% settings for multi-scale prediction, you can consider 3 scales or 5 scales:

prediction_scales=[0.4 0.6 0.8 1 1.2]; % 5 scales
% prediction_scales=[0.6 0.8 1]; % 3 scales
% prediction_scales=[0.8]; % or only use 1 scale
%-------------------------------------------------------------------------------------------------------------------------

ds_config.img_data_dir=img_data_dir;
result_evaluate_param=[];
result_evaluate_param.gt_mask_dir=gt_mask_dir;
ds_config.result_evaluate_param=result_evaluate_param;

run_config.prediction_scales=prediction_scales;
run_config.model_name=result_name;
run_config.root_cache_dir=result_dir;

do_predict_and_evaluate(run_config, ds_config);

end

function do_predict_and_evaluate(run_config, ds_config)

run_config.gen_net_opts_fn=@gen_net_opts_model_type1;

run_config.run_evaonly=true;
ds_config.use_custom_data=true;
ds_config.use_dummy_gt=true;
run_config.use_dummy_gt=ds_config.use_dummy_gt;

ds_config.ds_name='tmp_data';
mkdir_notexist(run_config.root_cache_dir);

diary_dir=run_config.root_cache_dir;
mkdir_notexist(diary_dir);
diary(fullfile(diary_dir, 'output.txt'));
diary on

run_dir_name=fileparts(mfilename('fullpath'));
[~, run_dir_name]=fileparts(run_dir_name);
run_config.run_dir_name=run_dir_name;
run_config.run_file_name=mfilename();

ds_info=gen_dataset_info(ds_config);
my_diary_flush();

if run_config.use_gpu
	gpu_num=gpuDeviceCount;
	if gpu_num>=1
		gpuDevice(run_config.gpu_idx);
    else
        error('no gpu found!');
	end
end

train_opts=run_config.gen_net_opts_fn(run_config, ds_info.class_info);

imdb=my_gen_imdb(train_opts, ds_info);
data_norm_info=[];
data_norm_info.image_mean=128;
imdb.ref.data_norm_info=data_norm_info;

[net_config, net_exp_info]=prepare_running_model(train_opts);

prediction_scales=run_config.prediction_scales;
scale_num=length(prediction_scales);
predict_result_dirs=cell(scale_num, 1);

for s_idx=1:scale_num

	one_scale=prediction_scales(s_idx);
	one_result_dir=fullfile(run_config.root_cache_dir, sprintf('predict_result_%d', s_idx));
	predict_result_dirs{s_idx}=one_result_dir;

	fprintf('\n\n--------------------------------------------------\n\n');
	fprintf('conduct prediction using image scale: %1.2f  (current scale / total scales: %d/%d) \n', one_scale, s_idx, scale_num);

	train_opts.root_cache_dir=one_result_dir;
	train_opts.input_img_scale=one_scale;
	train_opts.eva_param=update_eva_param_mscale(train_opts.eva_param, train_opts);

	my_net_tool(train_opts, imdb, net_config, net_exp_info);

	fprintf('\n\n--------------------------------------------------\n\n');
	disp('results are saved in:');
	disp(train_opts.root_cache_dir);

	my_diary_flush();

end

if length(predict_result_dirs)>1

    fprintf('\n\n--------------------------------------------------\n\n');
    disp('fusing multiscale predictions');

    fuse_param=[];
    fuse_param.predict_result_dirs=predict_result_dirs;
    fuse_param.fuse_result_dir=fullfile(run_config.root_cache_dir, 'predict_result_final_fused');
    fuse_param.cache_fused_score_map=true;
    fuse_multiscale_results(fuse_param, ds_config.class_info);

    fprintf('\n\n--------------------------------------------------\n\n');
    disp('final fused results are saved in:');
    disp(fuse_param.fuse_result_dir);

    my_diary_flush();

    final_prediction_dir=fuse_param.fuse_result_dir;

else

    final_prediction_dir=predict_result_dirs{1};
end

% evaluate the final fused result, if ground-truth is provided
result_evaluate_param=ds_config.result_evaluate_param;
if ~isempty(result_evaluate_param) && ~isempty(result_evaluate_param.gt_mask_dir)
	result_evaluate_param.predict_result_dir=fullfile(final_prediction_dir, 'predict_result_mask');
	fprintf('\n\n--------------------------------------------------\n\n');
	disp('perform evaluation of the predicted masks');
	result_info=evaluate_predict_results(result_evaluate_param, ds_config.class_info);
    disp_evaluate_result(result_info, ds_config.class_info);

    eva_result_cached_file=fullfile(final_prediction_dir, 'eva_result_info.mat');
    fprintf('saving evaluation result to: %s\n', eva_result_cached_file);
    save(eva_result_cached_file, 'result_info');
end

my_diary_flush();
diary off

end


classdef myPoint
    %MYPOINT Summary of this class goes here
    %   Detailed explanation goes here

    properties (GetAccess='public', SetAccess='public')
    x;
    y;
    end

    methods
        function obj = myPoint(x,y)
           obj.x = x;
           obj.y = y;
        end
    end

end


function [svolpulse, spulse, spulse_per_vol, verbose] = tapas_physio_get_onsets_from_locs(t, VOLLOCS, LOCS, sqpar, verbose)
% creates timing vectors of found
%
%   [svolpulse, spulse, spulse_per_vol] = tapas_physio_get_onsets_from_locs(t, VOLLOCS,
%                                           LOCS, sqpar, verbose);
%
% IN
%   t           time vector of logfile (in seconds)
%   VOLLOCS     volume scan events (in samples of logfile)
%   LOCS        all slice (including volume) scan events (in samples of logfile)
%   sqpar                   - sequence timing parameters
%           .Nslices        - number of slices per volume in fMRI scan
%           .NslicesPerBeat - usually equals Nslices, unless you trigger with the heart beat
%           .TR             - repetition time in seconds
%           .Ndummies       - number of dummy volumes
%           .Nscans         - number of full volumes saved (volumes in nifti file,
%                             usually rows in your design matrix)
%           .Nprep          - number of non-dummy, volume like preparation pulses
%                             before 1st dummy scan. If set, logfile is read from beginning,
%                             otherwise volumes are counted from last detected volume in the logfile
%           .time_slice_to_slice - time between the acquisition of 2 subsequent
%                             slices; typically TR/Nslices or
%                             minTR/Nslices, if minimal temporal slice
%                             spacing was chosen
%            onset_slice    - slice whose scan onset determines the adjustment of the
%                             regressor timing to a particular slice for the whole volume
%
%   verbose             physio.verbose, See also tapas_physio_new
% OUT
%   svolpulse   vector of volume scan pulse events (in seconds from logfile start)
%   spulse      vector of scan pulse events (in seconds from logfile start)
%   spulse_per_vol  cell of slice scan events; one cell element per volume
% EXAMPLE
%   [ons_secs.svolpulse, ons_secs.spulse] = tapas_physio_get_onsets_from_locs(ons_secs.t, VOLLOCS, LOCS);
%
%   See also tapas_physio_main_create_regressors tapas_physio_read_physlogfiles_philips

% Author: Lars Kasper
% Created: 2013-02-16
%
% Copyright (C) 2013, Institute for Biomedical Engineering, ETH/Uni Zurich.
%
% This file is part of the PhysIO toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

Nscans          = sqpar.Nscans;
Ndummies        = sqpar.Ndummies;
NslicesPerBeat  = sqpar.NslicesPerBeat;
Nslices         = sqpar.Nslices;
do_count_from_start = isfield(sqpar, 'Nprep') && ~isempty(sqpar.Nprep);
if do_count_from_start
    Nprep = sqpar.Nprep;
end

%% remove slice scan events for last, incompletely acquired volume
if VOLLOCS(end) ~= LOCS(end-NslicesPerBeat+1)
    LOCS(LOCS>=VOLLOCS(end))=[];
    VOLLOCS(end) = [];
end

Nallvols = length(VOLLOCS);

hasWarned = false;

for v = 1:Nallvols-1
    SLICELOCS{v} = LOCS(intersect(find(LOCS>=VOLLOCS(v), Nslices, 'first'), ...
        find(LOCS<VOLLOCS(v+1))));
    if length(SLICELOCS{v})~=Nslices && ~hasWarned
        verbose = tapas_physio_log(sprintf(...
            'First volume with missing slice events (%d: %d instead of %d found)\n', ...
            Nallvols, length(SLICELOCS{v}), Nslices), ...
            verbose, 1);
        hasWarned = true;
    end

end

SLICELOCS{Nallvols} = LOCS(find(LOCS>=VOLLOCS(Nallvols), Nslices, 'first'));

if length(SLICELOCS{Nallvols})~=Nslices && ~hasWarned
    verbose = tapas_physio_log(sprintf(...
        'First volume with missing slice events (%d: %d instead of %d found)\n', ...
        Nallvols, length(SLICELOCS{Nallvols}), Nslices), ...
        verbose, 1);
end

if verbose.level >= 3
    stringTitle =  'Sync: Slice bundles belonging to 1 volume';
    verbose.fig_handles(end+1) = tapas_physio_get_default_fig_params();
    set(gcf, 'Name', stringTitle);
    for v=1:Nallvols-1, stem(t(SLICELOCS{v}),ones(size(SLICELOCS{v})));hold all;end
    title(stringTitle);
    xlabel('t (seconds since SCANPHYSLOG-start)');
end

try
    if do_count_from_start
        REALLOCS = cell2mat(SLICELOCS(Nprep+Ndummies+(1:Nscans))');
        DUMMYLOCS = cell2mat(SLICELOCS(Nprep+(1:Ndummies))');
    else
        REALLOCS = cell2mat(SLICELOCS(end-Nscans+1:end)');
        DUMMYLOCS = cell2mat(SLICELOCS(end-Nscans-Ndummies+1:end-Nscans)');
    end
catch err
    if exist('REALLOCS', 'var')
        verbose = tapas_physio_log(...
            sprintf('Number of dummy slice event bundles does not match Ndummies. Check parameter sqpar.Ndummies or set to 0.\n\t (Matlab error: %s)', ...
            err.message), verbose, 2);
    else
        verbose = tapas_physio_log(...
            sprintf('Number of slice event bundles does not match Nscans. Check parameters sqpar.Nscans, Ndummies and Nprep.\n\t (Matlab error: %s)', ...
            err.message), verbose, 2);
    end
end

DUMMYLOCS = reshape(DUMMYLOCS,length(DUMMYLOCS),1);
REALLOCS = reshape(REALLOCS,length(REALLOCS),1);

ons.acq_slice_all = [DUMMYLOCS; REALLOCS];

if do_count_from_start
    ons.acq_vol_all   = VOLLOCS(Nprep+(1:Nscans+Ndummies));
    ons.acq_slice_per_vol_all = SLICELOCS(Nprep+(1:Nscans+Ndummies));
else
    ons.acq_vol_all   = VOLLOCS(end-Ndummies-Nscans+1:end);
    ons.acq_slice_per_vol_all = SLICELOCS(end-Nscans-Ndummies+1:end);
end

%% set scan time (in phys time scale) corresponding to index, where valid index exists
% (i.e. for scan events occuring during phys logfile

spulse = NaN(size(ons.acq_slice_all));
svolpulse = NaN(size(ons.acq_vol_all));

iValidSlice = find(~isnan(ons.acq_slice_all));
spulse(iValidSlice) = t(ons.acq_slice_all(iValidSlice));

iValidVol = find(~isnan(ons.acq_vol_all));
svolpulse(iValidVol) = t(ons.acq_vol_all(iValidVol));

spulse_per_vol = cellfun(@(x) t(x), ons.acq_slice_per_vol_all, 'UniformOutput', false);


function  [F_struc,K,binary_variables] = expandsemivar(F_struc,K,semicont_variables)

model.F_struc = F_struc;
model.K = K;
model.lb = -inf(size(model.F_struc,2)-1,1);
model.ub = -model.lb
model = presolve_bounds_from_modelbounds(model,1);

if any(isinf(model.lb(semicont_variables))) ||  any(isinf(model.ub(semicont_variables)))
    error('There are unbounded semi-continuous variables.');
end

% m new binaries required.
m = length(semicont_variables);


function obj = coef_Jacob3_qt_pTop_func_new(in1)
coef_J3 = in1(:,3);
coef_J6 = in1(:,6);
coef_J8 = in1(:,8);
coef_J9 = in1(:,9);
coef_J16 = in1(:,16);
coef_J18 = in1(:,18);
coef_J19 = in1(:,19);
coef_J25 = in1(:,25);
coef_J26 = in1(:,26);
coef_J27 = in1(:,27);
coef_J28 = in1(:,28);
coef_J29 = in1(:,29);
coef_J30 = in1(:,30);
coef_J31 = in1(:,31);
coef_J38 = in1(:,38);
coef_J40 = in1(:,40);
coef_J41 = in1(:,41);
coef_J47 = in1(:,47);
coef_J48 = in1(:,48);
coef_J49 = in1(:,49);
coef_J50 = in1(:,50);
coef_J51 = in1(:,51);
coef_J52 = in1(:,52);
coef_J53 = in1(:,53);
coef_J59 = in1(:,59);
coef_J60 = in1(:,60);
coef_J61 = in1(:,61);
coef_J62 = in1(:,62);
coef_J63 = in1(:,63);
coef_J64 = in1(:,64);
coef_J65 = in1(:,65);
coef_J66 = in1(:,66);
coef_J67 = in1(:,67);
coef_J68 = in1(:,68);
coef_J69 = in1(:,69);
coef_J70 = in1(:,70);
obj = [coef_J3,coef_J6,coef_J8.*2.0,coef_J9,coef_J16,coef_J18.*2.0,coef_J19,coef_J25.*3.0,coef_J26.*2.0,coef_J27,coef_J28,coef_J29,coef_J30,coef_J31,coef_J38,coef_J40.*2.0,coef_J41,coef_J47.*3.0,coef_J48.*2.0,coef_J49,coef_J50,coef_J51,coef_J52,coef_J53,coef_J59.*4.0,coef_J60.*3.0,coef_J61.*2.0,coef_J62.*2.0,coef_J63.*2.0,coef_J64.*2.0,coef_J65.*2.0,coef_J66,coef_J67,coef_J68,coef_J69,coef_J70];


% eeg_eventformat() - Convert the event information of a dataset from struct
%                 to array or vice versa.
%
% Usage: >> [eventout fields] = eeg_eventformat( event, 'format', fields );
%
% Inputs:
%   event  - event array or structure
%   format - ['struct'|'array'] see below
%   fields - [optional] cell array of strings containing the names of
%            the event struct fields. If this field is empty, it uses
%            the following list for
%            the names of the fields { 'type' 'latency' 'var1' ...
%            'var2' ... }.
% Output:
%   eventout  - output event array or structure
%   fields    - output cell array with the name of the fields
%
% Event formats:
%   struct - Events are organised as an array of structs with at
%            least two fields ('type' and 'latency')
%            (Ex: reaction_time may be type 1).
%   array  - events are organized as an array, the first column
%            representing the type, the second the latency and the
%            other ones user-defined variables.
%
% Note: 1) The event structure is defined only for continuous data
%          or epoched data derived from continuous data.
%       2) The event 'struct' format is more comprehensible.
%          For instance, to see all the properties of event 7,
%          type >> EEG.event(7)
%          Unfortunately, structures are awkward for expert users to deal
%          with from the command line (Ex: To get an array of latencies,
%           >> [ EEG.event(:).latency ] )
%          In array format, the same information is obtained by typing
%           >> EEG.event(:,2)
%       3) This function automatically updates the 'eventfield'
%          cell array depending on the format.
%
% Author: Arnaud Delorme, CNL / Salk Institute, 27 Jan 2002
%
% See also: eeglab(), pop_selectevent(), pop_importevent()

% Copyright (C) Arnaud Delorme, CNL / Salk Institute, 27 Jan 2002, arno@salk.edu
%
% 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 2 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, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

% 2/06/02 modifed header - sm & ad
% 2/08/02 add field input - ad
% 2/12/02 reprogrammed function using epochformat.m - ad

function [event, eventfield] = eeg_eventformat(event, format, fields);

if nargin < 2
   help eeg_eventformat;
   return;
end;

if exist('fields') ~= 1, fields = { 'type', 'latency' }; end;

[event eventfield] = eeg_epochformat( event, format, fields);


% The COBRA Toolbox: testPruneModel.m
%
% Purpose:
%     - test the pruneModel function
%
% Author:
%     - Loic Marx, December 2018

% save the current path
currentDir = pwd;

% initialize the test
fileDir = fileparts(which(mfilename));
cd(fileDir);

% load reference data
load('refData_pruneModel.mat')

% define input
model = getDistributedModel('ecoli_core_model.mat');

% retrieve the default biomass reaction
biomassRxn = checkObjective(model);
biomassRxn = biomassRxn{1};

minGrowth = 1; % this value is for testing only

% generate data
[modelUpdated, modelPruned, Ex_Rxns] = pruneModel(model, minGrowth, biomassRxn);

% if biomassRxn is not define
[modelUpdated_2inputs, modelPruned_2inputs, Ex_Rxns_2inputs] = pruneModel(model, minGrowth);

% comparison between refData and generated data
assert(isequal(modelUpdated_ref, modelUpdated))
assert(isequal(modelPruned_ref, modelPruned))
assert(isequal(Ex_Rxns_ref, Ex_Rxns))

% comparison between refData and data generated without the biomassRxn input
assert(isequal(modelUpdated_ref, modelUpdated_2inputs))
assert(isequal(modelPruned_ref, modelPruned_2inputs))
assert(isequal(Ex_Rxns_ref, Ex_Rxns_2inputs))


function PlotBoxEdges
factor=1.00;
plot3(factor*[0 1],factor*[0 0],factor*[0 0],'k','LineWidth',5),hold on
plot3(factor*[0 0],factor*[0 0],factor*[0 1],'k','LineWidth',5)
plot3(factor*[0 0],factor*[0 1],factor*[0 0],'k','LineWidth',5)
plot3(factor*[0 1],factor*[1 1],factor*[1 1],'k','LineWidth',5)
plot3(factor*[1 1],factor*[1 1],factor*[1 0],'k','LineWidth',5)
plot3(factor*[1 1],factor*[0 1],factor*[1 1],'k','LineWidth',5)
plot3(factor*[0 0],factor*[0 1],factor*[1 1],'k','LineWidth',5)
plot3(factor*[1 1],factor*[0 1],factor*[0 0],'k','LineWidth',5)
plot3(factor*[0 1],factor*[1 1],factor*[0 0],'k','LineWidth',5)
plot3(factor*[0 1],factor*[0 0],factor*[1 1],'k','LineWidth',5)
plot3(factor*[0 0],factor*[1 1],factor*[0 1],'k','LineWidth',5)
plot3(factor*[1 1],factor*[0 0],factor*[1 0],'k','LineWidth',5)

github-repos/MATLAB/Sable-mcbench-benchmarks/mcbench-benchmarks-ba13b2f0296ef49491b95e3f984c7c41fccdb6d8/34985-monte-carlo-simulation-of-three-dimensional-grain-growth-code-version-no-1-basic/Monte Carlo Simulation Q-state Potts model 3D square-lattice - microstructure/PlotBoxEdges.m


function haveNewerRelease = tapas_check_for_new_release(verbose)
    %% Check if a new release is available.
    %
    % Input
    %       verbose         -- Show information on command prompt:
    %                               0   no information
    %                               1   only if there is a new release (or not)
    %                               2   as 1, but if there is a new release also
    %                                   the release notes for the lase release
    %                               3   as 1, but if there is a new release also
    %                                   the release notes for all newer
    %                                   releases.
    %
    % Output
    %       haveNewerRelease  -- True if there is a newer release on github

    % muellmat@ethz.ch
    % copyright (C) 2020
    %

    if nargin < 1
        verbose = 3;
    end

    [online_version,data] = tapas_check_online_version();
    if isempty(online_version) % Could not communicate with server
        haveNewerRelease = false;
        if verbose
            fprintf(1, 'Could not reach github to get current TAPAS version!\n');
        end
        return;
    end
    offline_version = tapas_get_current_version();
    % both versions are strings in the form '3.3.0'.
    haveNewerRelease = tapas_compare_versions(online_version,offline_version);

    if verbose % Show info
        if ~haveNewerRelease
            fprintf(1, 'Your TAPAS version is up-to-date.\n\n');
        else
            fprintf(1, ['There is a new TAPAS release available (installed %s /'...
                +'newest %s)!\n\n'],offline_version,online_version);
            if verbose > 1 % Show release notes of the new releases
                try % in case the api changed and the structure of the struct is
                    % different
                    n_data = numel(data);
                    fprintf(1, 'Release notes:\n')
                    if verbose == 2
                        n_data = 1; % Just iterate once through loop
                    end
                    for i_data = 1:n_data
                        str_version = data(i_data).tag_name;
                        str_version = strrep(str_version,'v','');
                        if tapas_compare_versions(str_version,offline_version)
                            fprintf(1, '===== TAPAS v%s =====\n',str_version)
                            body = data(i_data).body;
                            body = tapas_remove_problematic_escape_characters(body);
                            fprintf(1,body);
                            fprintf(1,'\n======================\n')
                        end
                    end
                catch
                    fprintf(1, ['Cannot print release notes. Maybe the github API'...
                        ' has changed.\n']);
                end
            end
        end
    end

end

function str = tapas_remove_problematic_escape_characters(str)
    %% Removing problematic escape characters
    %
    % Input
    %       str     -- String with problematic escape characters
    %
    % Output
    %       str     -- String without problematic escape characters

    % matlab does not like some escape sequences from github
    str = strrep(str,'\','');
end


function dmapErrors = wrapperEvalSIRFS(classes)
    globals
    dmapErrors = cell(length(classes),1);

    map = load(fullfile(cachedir,'test_sets.mat'));
    map = map.map; map = map(~cellfun(@isempty,map));
    map = cellfun(@(x)(strcat(x,'.mat')),map,'UniformOutput',false);
    map = map(:);

    for ii=1:length(classes)
        dmapDir = fullfile(cachedir,classes{ii},'sirfsDir');
        gtDmapDir = fullfile(cachedir,classes{ii},'gtDepthMap');
        evalFileName = fullfile(cachedir,classes{ii},'evalStructSIRFS.mat');
        disp(classes{ii});
        if(exist(evalFileName,'file'))
            tmp = load(evalFileName);
            idx = ismember(tmp.fnames(:),map);
            dmapErrors{ii} = tmp.dmapErrors(idx);
            continue;
        end
        dmapErrors{ii} = evalSIRFS(dmapDir,gtDmapDir,evalFileName);
        disp(size(dmapErrors{ii},1));
    end
    fprintf('Class\t\tDepth Correlation (Mean)\n');
    for ii=1:length(classes)
        fprintf('%s\t\t%1.3f\n',classes{ii},mean(dmapErrors{ii}(~isnan(dmapErrors{ii}))));
    end

    fprintf('Class\t\tDepth Correlation (Median)\n');
    for ii=1:length(classes)
        fprintf('%s\t\t%1.3f\n',classes{ii},median(dmapErrors{ii}(~isnan(dmapErrors{ii})))*100);
    end

end

function dmapErrors = evalSIRFS(dmapDir,gtDmapDir,evalFileName)
    globals;
    fnames = getFileNamesFromDirectory(dmapDir,'types',{'.mat'});
    disp('Depth map evaluation');
    dmapErrors = zeros(length(fnames),1);
    p =  TimedProgressBar( length(fnames), round(length(fnames)/4), ...
    'Depth Map Errors: Remaining ', ', Completed ', 'Total Time: ' );

    parfor i=1:length(fnames)
        GtFile = fullfile(gtDmapDir,fnames{i});
        dmapFile = fullfile(dmapDir,fnames{i});
        try
            gtdmap = load(GtFile,'dmap');gtdmap = gtdmap.dmap;
        catch
            dmapErrors(i) = nan;
            continue;
        end
        dmap = load(dmapFile);
        mask = dmap.state.mask; dmap = dmap.state.dmap;
        %dmapErrors(i) = dmapMetric(dmap,gtdmap,mask);
        dmapErrors(i) = dmapMetricZMAE(dmap,gtdmap,mask);
        p.progress;
    end
    p.stop;
    save(evalFileName,'dmapErrors','fnames');
end


function candoit = canGetPrecon(problem)
% Checks whether a preconditioner was specified in the problem description.
%
% function candoit = canGetPrecon(problem)
%
% Returns true if a preconditioner was specified, false otherwise. Notice
% that even if this function returns false, it is still possible to call
% getPrecon, as the default preconditioner is simply the identity operator.
% This check function is mostly useful to tell whether that default
% preconditioner will be in use or not.
%
% See also: getPrecon getSqrtPrecon canGetSqrtPrecon getHessian

% This file is part of Manopt: www.manopt.org.
% Original author: Nicolas Boumal, July 3, 2013.
% Contributors:
% Change log:

    candoit = isfield(problem, 'precon') || canGetSqrtPrecon(problem);

end


function x = is_Nd_distributed(x)
x = iscell(x) && length(x) == 2 && ischar(x{1}) && strcmp(x{1},'mvn') && iscell(x{2});


function [ni] = niftiApplyAndCreateXform(nii,xformType)
%First create then apply a specified transform onto the supplied nifti
%struct.
%
% USAGE
%  nii = readNifti(niftiFullPath);
%  xformType = 'Inplane';
%  niftiApplyAndCreateXform(nii,xformType);
%
% INPUTS
%  Nifti struct
%  String specifying the transform to apply
%
% RETURNS
%  Nifti Struct
%
%
% Copyright Stanford VistaLab 2013

xformType = mrvParamFormat(xformType);

xform = niftiCreateXform(nii,xformType);
%Create transform
if (xform == 0)
   %We shouldn't do anything
   ni = nii;
else
   ni = niftiApplyXform(nii,xform);
end

return


function [version] = hasyokogawa(desired)

% HASYOKOGAWA tests whether the data input toolbox for MEG systems by
% Yokogawa (www.yokogawa.com, designed by KIT/EagleTechnology) is
% installed. Only the newest version of the toolbox is accepted.
%
% Use as
%   [string]  = hasyokogawa;
% which returns a string describing the toolbox version, e.g. "12bitBeta3",
% "16bitBeta3", or "16bitBeta6". An empty string is returned if the toolbox
% is not installed. The string "unknown" is returned if it is installed but
% the version is unknown.
%
% Alternatively you can use it as
%   [boolean] = hasyokogawa(desired);
% where desired is a string with the desired version.
%
% See also READ_YOKOGAWA_HEADER, READ_YOKOGAWA_DATA, READ_YOKOGAWA_EVENT,
% YOKOGAWA2GRAD

% Copyright (C) 2010, Tilmann Sander-Thoemmes
%
% 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: hasyokogawa.m 2885 2011-02-16 09:41:58Z roboos $

% return empty if not present
version = [];

try
  warning('off', 'MATLAB:pfileOlderThanMfile');
  % Call some functions with input argument "Inf": If
  % the functions are present they return their revision number.
  % Call first GetMeg160ADbitInfoM as this is not present in
  % the 12bit library, in case of error the "catch" part will take over.
  % The code below is intentionally very literal for easy of reading.
  res = textscan(evalc('GetMeg160ADbitInfoM(Inf);'),'%s %s %c %s %s %d');
  rev_ADbitInfoM = res{6};
  res = textscan(evalc('GetMeg160ChannelInfoM(Inf);'),'%s %s %c %s %s %d');
  rev_ChannelInfoM = res{6};
  res = textscan(evalc('GetMeg160AmpGainM(Inf);'),'%s %s %c %s %s %d');
  rev_AmpGainM = res{6};
  res = textscan(evalc('GetMeg160MatchingInfoM(Inf);'),'%s %s %c %s %s %d');
  rev_MatchingInfoM = res{6};
  if [0 2 1 5] == [rev_ADbitInfoM rev_ChannelInfoM rev_AmpGainM rev_MatchingInfoM]
    version='16bitBeta3';
  elseif [0 2 2 5] == [rev_ADbitInfoM rev_ChannelInfoM rev_AmpGainM rev_MatchingInfoM]
    version='16bitBeta6';
  else
    warning('Yokogawa toolbox is installed, but the version cannot be determined.');
    version = 'unknown';
  end
  if nargin>0
    version = strcmpi(version, desired);
    if ~version
        warning('The required version of the Yokogawa input toolbox (%s) is not installed.', desired);
    end
  end
  warning('on', 'MATLAB:pfileOlderThanMfile');
catch
  warning('on', 'MATLAB:pfileOlderThanMfile');
  m = lasterror;
  m.identifier;
  if strcmp(m.identifier, 'MATLAB:UndefinedFunction') || strcmp(m.identifier, 'MATLAB:FileIO:InvalidFid')
    if (exist('GetMeg160ChannelInfoM') && exist('GetMeg160ContinuousRawDataM'));
      version = '12bitBeta3';
    else
      version = 'unknown';
   end
  end
  if nargin>0
    version = 0; % logical output
  end

end


% Copyright (C) 2018  Symeon Symeonidis, Stefanos Tsantilas, Stelios Mitilineos
% simos421@gmail.com, steftsantilas@gmail.com, smitil@gmail.com
% 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.

function CstAlignWCSwithFace(mws)

WCS = invoke(mws,'WCS');
invoke(WCS,'AlignWCSWithSelected','Face');
end


function m = modes()
% modes of operation
m.OPEN = 1;
m.CLOSE = 2;
m.KSEARCH = 3;
m.PRISEARCH=4;
m.FRSEARCH=5;


% STD_CHANGROUP - Create channel groups for plotting.
%
% Usage:
%                >> STUDY = std_changroup(STUDY, ALLEEG);
%                >> STUDY = std_changroup(STUDY, ALLEEG, chanlocs, 'interp');
% Inputs:
%   ALLEEG     - Top-level EEGLAB vector of loaded EEG structures for the dataset(s)
%                in the STUDY. ALLEEG for a STUDY set is typically loaded using
%                POP_LOADSTUDY, or in creating a new STUDY, using POP_CREATESTUDY.
%   STUDY      - EEGLAB STUDY set comprising some or all of the EEG datasets in ALLEEG.
%   chanlocs   - EEGLAB channel structure. Only construct the STUDY.changrp
%                structure for a subset of channels.
%   'interp'   - optional input in case channel locations are interpolated
%
% Outputs:
%   STUDY      - The input STUDY set structure modified according to specified user
%                edits, if any. The STUDY.changrp structure is created. It contains as
%                many elements as there are channels. For example, STUDY.changrp(1)
%                is the first channel. Fields of the changrp structure created at this
%                point are
%                    STUDY.changrp.name      : name of the channel group
%                    STUDY.changrp.channels  : cell array containing channel labels
%                                              for the group.
%                    STUDY.changrp.setinds   : indices of datasets containing the
%                                              selected channels.
%                    STUDY.changrp.allinds   : indices of channels within the datasets
%                                              above.
%
% Authors: Arnaud Delorme, CERCO, 2006

% Copyright (C) Arnaud Delorme, CERCO, arno@salk.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

function STUDY = std_changroup(STUDY, ALLEEG, alllocs, interp);

if nargin < 4
    interp = 'off';
end

% union of all channel structures
% -------------------------------
inputloc = 0;
if nargin >= 3
    if ~isempty(alllocs)
        inputloc = 1;
    end
end
if ~inputloc
    alllocs = eeg_mergelocs(ALLEEG.chanlocs);
end

% create group for each electrode
% -------------------------------
if isstruct(alllocs)
    alllocs = { alllocs.labels };
end
STUDY.changrp = [];
for indc = 1:length(alllocs)
    STUDY.changrp(indc).name     = alllocs{indc};
    STUDY.changrp(indc).channels = { alllocs{indc} };
end


function svgGaussianBlur(s, source, deviation, result)
% Adds a feGaussianBlur SVG filter
% PRELIMINARY IMPLEMENTATION (Parameters may change)
%
% svgGaussianBlur(s, source, deviation, result)
% Parameters:
%   s : Array of plot object handles
%   source : Any previous defined filter result string, 'SourceGraphic',
%            or 'SourceAlpha'.
%   deviation : Blur strength
%   result : String that identifies the filter result for following filter
%            stages.
for i = 1:length(s)
    userdata = get(s(i),'UserData');
    if isfield(userdata, 'svg') && isfield(userdata.svg, 'Filter')
        next = length(userdata.svg.Filter) + 1;
    else
        next = 1;
    end
    userdata.svg.Filter(next).Subfilter.Type = 'feGaussianBlur';
    userdata.svg.Filter(next).Subfilter.Deviation = deviation;
    userdata.svg.Filter(next).Subfilter.Source = source;
    userdata.svg.Filter(next).Subfilter.Result = result;
    set(s(i),'UserData', userdata);
end


function [net, state, stats, db] = train_network(net, getBatch, opts)
% TRAIN_NETWORK  Adapted version of CNN_TRAIN_DAG from MatConvNet package.
% It performs the training of a CNN using the DagNN wrapper.

% Copyright (C) 2014-16 Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

opts.plotStatistics = true;
opts.prefetch = false ;
opts.postEpochFn = [] ;  % postEpochFn(net,params,state) called after each epoch; can return a new learning rate, 0 to stop, [] for no change
opts.extractStatsFn = @extractStats ;

if ~exist(opts.expDir, 'dir'), mkdir(opts.expDir) ; end

% -------------------------------------------------------------------------
%                                                         		Prepare data
% -------------------------------------------------------------------------
%
% Load db.mat for the training data and initialize negatives
if exist(opts.dbPath, 'file')
  fprintf('>> Loading DB file...\n'); t=tic;
  db = load(opts.dbPath) ;
  db.train.nidxs = zeros(opts.numNegative, numel(db.train.qidxs));
  db.val.nidxs = zeros(opts.numNegative, numel(db.val.qidxs));
  fprintf('>>>> done in %s\n', htime(toc(t)));
  if ~isfield(db.val, 'data')
    fprintf('>> Validation images not provided, loading...\n');
    fprintf('>>>> imageDir: %s\n', opts.augment.imageDir);
    % we dont use augmentation for validation data
    optsValData.imageDir = opts.augment.imageDir;
    optsValData.crop = opts.augment.crop;
    optsValData.gpus = opts.augment.gpus;
    optsValData.imageSize = opts.augment.imageSize;
    optsValData.jitterFlip = false;
    optsValData.jitterLocation = false;
    optsValData.jitterScale = 1;
    optsValData.jitterBrightness = 0;
    optsValData.jitterContrast = 0;
    optsValData.jitterSaturation = 0;
    images = cellfun(@(x) cid2filename(x, optsValData.imageDir), db.val.cids, 'UniformOutput', false);
    db.val.data = get_images(images, optsValData);
  end
else
  disp('!!! DB file doesnt exist. KEYBOARD');
  keyboard
end

% -------------------------------------------------------------------------
%                                                        Train and validate
% -------------------------------------------------------------------------

if isempty(opts.derOutputs)
  error('!!! DEROUTPUTS must be specified when training.\n') ;
end

modelPath = @(ep) fullfile(opts.expDir, sprintf('net-epoch-%d.mat', ep));
modelFigPath = fullfile(opts.expDir, 'net-train.pdf') ;

start = opts.continue * findLastCheckpoint(opts.expDir) ;
if start >= 1
  fprintf('>> Resuming by loading epoch %d\n', start) ;
  [net, state, stats] = loadState(modelPath(start)) ;
else
  state = [] ;
  saveState(modelPath(0), net, state) ;
end

for epoch=start+1:opts.numEpochs

  % Set the random seed based on the epoch and opts.randomSeed.
  % This is important for reproducibility, including when training
  % is restarted from a checkpoint.
  rng(epoch + opts.randomSeed) ;
  prepareGPUs(opts, epoch == start+1) ;

  % Train for one epoch.
  params = opts ;
  params.epoch = epoch ;
  params.getBatch = getBatch ;
  params.learningRate = opts.learningRate(min(epoch, numel(opts.learningRate))) ;

  % Augment data if necessary: epochSize, imread with jitter, flip pairs, etc
  params.db = augment_database(db, opts.augment);

  if numel(opts.gpus) <= 1
    [net, state] = processEpoch(net, state, params, 'train') ;
    [net, state] = processEpoch(net, state, params, 'val') ;
    saveState(modelPath(epoch), net, state) ;
    lastStats = state.stats ;
  else
    spmd
      [net, state] = processEpoch(net, state, params, 'train') ;
      [net, state] = processEpoch(net, state, params, 'val') ;
      if labindex == 1
        saveState(modelPath(epoch), net, state) ;
      end
      lastStats = state.stats ;
    end
    lastStats = accumulateStats(lastStats) ;
  end

  stats.train(epoch) = lastStats.train ;
  stats.val(epoch) = lastStats.val ;
  clear lastStats ;
  saveStats(modelPath(epoch), stats) ;

  if opts.plotStatistics
    switchFigure(1) ; clf ;
    plots = setdiff(cat(2,fieldnames(stats.train)',fieldnames(stats.val)'), {'num', 'time'}) ;
    for p = plots
      p = char(p) ; values = zeros(0, epoch) ; leg = {} ;
      for f = {'train', 'val'}
        f = char(f) ;
        if isfield(stats.(f), p)
          tmp = [stats.(f).(p)] ; values(end+1,:) = tmp(1,:)' ; leg{end+1} = f ;
        end
      end
      subplot(1,numel(plots),find(strcmp(p,plots))) ; plot(1:epoch, values','o-') ;
      xlabel('epoch') ; title(p) ; legend(leg{:}) ; grid on ;
    end
    drawnow ; print(1, modelFigPath, '-dpdf') ;
  end

  if ~isempty(opts.postEpochFn)
    if nargout(opts.postEpochFn) == 0
      opts.postEpochFn(net, params, state) ;
    else
      lr = opts.postEpochFn(net, params, state) ;
      if ~isempty(lr), opts.learningRate = lr; end
      if opts.learningRate == 0, break; end
    end
  end

  % With multiple GPUs, return one copy
  if isa(net, 'Composite'), net = net{1} ; end

end

% -------------------------------------------------------------------------
function [net, state] = processEpoch(net, state, params, mode)
% -------------------------------------------------------------------------
% Note that net is not strictly needed as an output argument as net
% is a handle class. However, this fixes some aliasing issue in the
% spmd caller.

% create opts needed for getBatch (so that we dont send all)
getbatchopts.batchSize = params.batchSize;
getbatchopts.numSubBatches = params.numSubBatches;
getbatchopts.numRemine = params.numRemine;
getbatchopts.memoryMapRemine = params.memoryMapRemine;
getbatchopts.gpus = params.gpus;

% initialize with momentum 0
if isempty(state) || isempty(state.solverState)
  state.solverState = cell(1, numel(net.params)) ;
  state.solverState(:) = {0} ;
end

% move CNN  to GPU as needed
numGpus = numel(params.gpus) ;
if numGpus >= 1
  net.move('gpu') ;
  for i = 1:numel(state.solverState)
    s = state.solverState{i} ;
    if isnumeric(s)
      state.solverState{i} = gpuArray(s) ;
    elseif isstruct(s)
      state.solverState{i} = structfun(@gpuArray, s, 'UniformOutput', false) ;
    end
  end
end
if numGpus > 1
  parserv = ParameterServer(params.parameterServer) ;
  net.setParameterServer(parserv) ;
else
  parserv = [] ;
end

% profile
if params.profile
  if numGpus <= 1
    profile clear ;
    profile on ;
  else
    mpiprofile reset ;
    mpiprofile on ;
  end
end

num = 0 ;
epoch = params.epoch ;
adjustTime = 0 ;

stats.num = 0 ; % return something even if subset = []
stats.time = 0 ;

start = tic ;
time_remine = 0;

nbatch = floor(numel(params.db.(mode).qidxs)/params.batchSize); % floor so only complete batches
for batch=1:nbatch

  % #queries done in this lab and this batch
  bqnum = numel(labindex:numlabs:params.batchSize);

  for subbatch=1:params.numSubBatches
    % #queries done in this lab and this subbatch
    sbqnum = numel(subbatch:params.numSubBatches:bqnum);
    num = num + sbqnum;

    % get inputs and latest negatives
    [inputs, params.db.(mode).nidxs, time_r] = params.getBatch(getbatchopts, params.db, net, batch, subbatch, mode, epoch) ;
    time_remine = time_remine + time_r;

    if params.prefetch
      disp('Prefetch not implemented!!! Keyboard...\n');
      keyboard
    end

    if strcmp(mode, 'train')
      net.mode = 'normal' ;
      net.accumulateParamDers = (subbatch ~= 1) ;
      net.eval(inputs, params.derOutputs, 'holdOn', subbatch < params.numSubBatches) ;
    else
      net.mode = 'test' ;
      net.eval(inputs) ;
    end
  end

  % Accumulate gradient.
  if strcmp(mode, 'train')
    if ~isempty(parserv), parserv.sync() ; end
    posnegNum = size(params.db.(mode).pidxs,1) + size(params.db.(mode).nidxs,1);
    pairNum = params.batchSize * posnegNum; % number of pairs
    imNum   = params.batchSize * (1 + posnegNum); % number of images (for batchNorm)
    state = accumulateGradients(net, state, params, pairNum, imNum, parserv) ;
  end

  % Get statistics.
  time = toc(start) + adjustTime ;
  batchTime = time - stats.time ;
  stats.num = num ;
  stats.time = time ;
  stats = params.extractStatsFn(stats,net) ;
  batchSpeed = batch / (time - time_remine);
  % if t == 3*params.batchSize + 1
  %   % compensate for the first three iterations, which are outliers
  %   adjustTime = 4*batchTime - time ;
  %   stats.time = time + adjustTime ;
  % end

  fprintf('%s: ep %02d: bch %4d/%4d:', mode, epoch, batch, nbatch) ;

  fprintf(' %.1f bch/s:', batchSpeed) ;
  for f = setdiff(fieldnames(stats)', {'num', 'time'})
    f = char(f) ;
    fprintf(' %s %.3f:', f(1:3), stats.(f)) ;
  end
  fprintf('\n') ;
end

% Save back to state.
state.stats.(mode) = stats ;
if params.profile
  if numGpus <= 1
    state.prof.(mode) = profile('info') ;
    profile off ;
  else
    state.prof.(mode) = mpiprofile('info');
    mpiprofile off ;
  end
end
if ~params.saveSolverState
  state.solverState = [] ;
else
  for i = 1:numel(state.solverState)
    s = state.solverState{i} ;
    if isnumeric(s)
      state.solverState{i} = gather(s) ;
    elseif isstruct(s)
      state.solverState{i} = structfun(@gather, s, 'UniformOutput', false) ;
    end
  end
end

net.reset() ;
net.move('cpu') ;

% -------------------------------------------------------------------------------
function state = accumulateGradients(net, state, params, pairNum, imNum, parserv)
% pairNum : number of pairs per batch #query x (#pos + #neg)
% imNum   : number of images that pass per batch #query x (1 + #pos + #neg)
% -------------------------------------------------------------------------------

numGpus = numel(params.gpus) ;
otherGpus = setdiff(1:numGpus, labindex) ;

for p=1:numel(net.params)

  if ~isempty(parserv)
    parDer = parserv.pullWithIndex(p) ;
  else
    parDer = net.params(p).der ;
  end

  if isempty(parDer) % for GOOGLENET part that is not used
    continue;
  end

  switch net.params(p).trainMethod

    case 'average' % mainly for batch normalization
      thisLR = net.params(p).learningRate ;
      net.params(p).value = vl_taccum(...
          1 - thisLR, net.params(p).value, ...
          (thisLR/imNum/net.params(p).fanout),  parDer) ;

    case 'gradient'
      thisDecay = params.weightDecay * net.params(p).weightDecay ;
      thisLR = params.learningRate * net.params(p).learningRate ;

      if thisLR>0 || thisDecay>0
        % Normalize gradient and incorporate weight decay.
        parDer = vl_taccum(1/pairNum, parDer, ...
                           thisDecay, net.params(p).value) ;

        if isempty(params.solver)
          % Default solver is the optimised SGD.
          % Update momentum.
          state.solverState{p} = vl_taccum(...
            params.momentum, state.solverState{p}, ...
            -1, parDer) ;

          % Nesterov update (aka one step ahead).
          if params.nesterovUpdate
            delta = params.momentum * state.solverState{p} - parDer ;
          else
            delta = state.solverState{p} ;
          end

          % Update parameters.
          net.params(p).value = vl_taccum(...
            1,  net.params(p).value, thisLR, delta) ;

        else
          % call solver function to update weights
          [net.params(p).value, state.solverState{p}] = ...
            params.solver(net.params(p).value, state.solverState{p}, ...
            parDer, params.solverOpts, thisLR) ;
        end
      end
    otherwise
      error('Unknown training method ''%s'' for parameter ''%s''.', ...
        net.params(p).trainMethod, ...
        net.params(p).name) ;
  end
end

% -------------------------------------------------------------------------
function stats = accumulateStats(stats_)
% -------------------------------------------------------------------------

for s = {'train', 'val'}
  s = char(s) ;
  total = 0 ;

  % initialize stats stucture with same fields and same order as
  % stats_{1}
  stats__ = stats_{1} ;
  names = fieldnames(stats__.(s))' ;
  values = zeros(1, numel(names)) ;
  fields = cat(1, names, num2cell(values)) ;
  stats.(s) = struct(fields{:}) ;

  for g = 1:numel(stats_)
    stats__ = stats_{g} ;
    num__ = stats__.(s).num ;
    total = total + num__ ;

    for f = setdiff(fieldnames(stats__.(s))', 'num')
      f = char(f) ;
      stats.(s).(f) = stats.(s).(f) + stats__.(s).(f) * num__ ;

      if g == numel(stats_)
        stats.(s).(f) = stats.(s).(f) / total ;
      end
    end
  end
  stats.(s).num = total ;
end

% -------------------------------------------------------------------------
function stats = extractStats(stats, net)
% -------------------------------------------------------------------------
sel = find(cellfun(@(x) strcmp(x,'objective') || strcmp(x,'error'), {net.layers.name}));
for i = 1:numel(sel)
  % if net.layers(sel(i)).block.ignoreAverage, continue; end;
  stats.(net.layers(sel(i)).outputs{1}) = net.layers(sel(i)).block.average ;
end

% -------------------------------------------------------------------------
function saveState(fileName, net_, state)
% -------------------------------------------------------------------------
net = net_.saveobj() ;
save(fileName, 'net', 'state') ;

% -------------------------------------------------------------------------
function saveStats(fileName, stats)
% -------------------------------------------------------------------------
if exist(fileName)
  save(fileName, 'stats', '-append') ;
else
  save(fileName, 'stats') ;
end

% -------------------------------------------------------------------------
function [net, state, stats] = loadState(fileName)
% -------------------------------------------------------------------------
load(fileName, 'net', 'state', 'stats') ;
net = dagnn.DagNN.loadobj(net) ;
if isempty(whos('stats'))
  error('Epoch ''%s'' was only partially saved. Delete this file and try again.', ...
        fileName) ;
end

% -------------------------------------------------------------------------
function epoch = findLastCheckpoint(modelDir)
% -------------------------------------------------------------------------
list = dir(fullfile(modelDir, 'net-epoch-*.mat')) ;
tokens = regexp({list.name}, 'net-epoch-([\d]+).mat', 'tokens') ;
epoch = cellfun(@(x) sscanf(x{1}{1}, '%d'), tokens) ;
epoch = max([epoch 0]) ;

% -------------------------------------------------------------------------
function switchFigure(n)
% -------------------------------------------------------------------------
if get(0,'CurrentFigure') ~= n
  try
    set(0,'CurrentFigure',n) ;
  catch
    figure(n) ;
  end
end

% -------------------------------------------------------------------------
function clearMex()
% -------------------------------------------------------------------------
clear vl_tmove vl_imreadjpeg ;

% -------------------------------------------------------------------------
function prepareGPUs(opts, cold)
% -------------------------------------------------------------------------
numGpus = numel(opts.gpus) ;
if numGpus > 1
  % check parallel pool integrity as it could have timed out
  pool = gcp('nocreate') ;
  if ~isempty(pool) && pool.NumWorkers ~= numGpus
    delete(pool) ;
  end
  pool = gcp('nocreate') ;
  if isempty(pool)
    parpool('local', numGpus) ;
    cold = true ;
  end

end
if numGpus >= 1 && cold
  clearMex() ;
  if numGpus == 1
    gpuinfo = gpuDevice(opts.gpus);
    fprintf('>> Running on GPU %s with Index %d\n', gpuinfo.Name, gpuinfo.Index);
  else
    spmd
      clearMex() ;
      gpuinfo = gpuDevice(opts.gpus(labindex));
      fprintf('>> Running on GPU %s with Index %d\n', gpuinfo.Name, gpuinfo.Index);
    end
  end
end


%kksampline 'Sample a data object along an arbitrary line'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros ksampline.pane file
%
% Parameters:
% InputFile: i 'Input ', required: 'input data object'
% Integer: n 'Number of samples (including endpoints)', default: 1000: 'number of samples (including endpoints)'
% Integer: nc 'Minimum required neighbor count', default: 0: 'minimum required neighbor count'
% OutputFile: o 'Output', required: 'output data object'
%
% Example: o = kksampline(i, {'i','';'n',1000;'nc',0;'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% ksampline - Sample a data object along an arbitrary line
%
%  DESCRIPTION
% .I ksampline
% is used to sample the data in an object along an arbitrary line and at
% arbitrary intervals. The value at each sample point is obtained by
% an inverse distance weighting scheme.
%
% The first sample point is precisely at the starting coordinate and
% the final sample is precisely at the ending coordinate.
%
% The line may traverse any portion of the 5D data space. If a particular
% sample on the line lies outside the data space then the values will be
% interpolated using a padding value of zero.
%
% The output object will be of the same data type as the input object. If
% a map is present in the input object, then the value data is sent through the
% map before processing. The output data will thus have no map.
%
% Mask data, if present, is used to help control the interpolation.
% Value points with a corresponding mask value of zero will not be included
% in the interpolated value. However, a minimum number of neighboring
% values with a valid mask are required in order to produce a valid output
% value; non-valid output values are marked by a zero mask. If the mask
% segment is not present, then all value points in the source object are assumed
% to be valid.
%
% The actual minimum
% required neighbor count is determined by the setting of the "nc" argument.
% If nc is zero, then the minimum required neighbor count will be computed from
% the dimensionality of the source data set. For nc=0, the minimum required
% neighbor count is 0.5*(2^dim)+1 where dim is the dimensionality of
% the source object (1 for a line, 2 for a plane, 3 for a volume, etc).
% If nc is non-zero, then the minimum required neighbor count is simply nc.
% Beware of non-intuitive results when interpolating across mask wise non-convex
% parts of the data object. The default minimum required neighbor count
% gives "reasonable" answers in these cases. Reducing the minimum required
% neighbor count can provide answers that are less and less meaningful.
%
% Note that ksampline samples the data as if it were using a delta function.
% This implies that you may get significantly different
% results depending on the position of each sample location. You may wish to
% lowpass the source data before sampling with ksampline to avoid aliasing.
% This can be particularly important when dealing with "holey data" or when
% the sampling involves degenerate geometry (such as sampling a plane object
% with a sampling line that does not lie in the plane).
%
% ksampline is implemented using "point\fR data access. A point data access
% is done for each sample in the line. This implies that a large number of samples
% may require quite some time to compute, particularly if operating on a
% higher dimension data set.
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kksampline(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kksampline(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'n', 1000;'nc', 0;'o', '__output'};
maxval={0,0,32,0};
minval={0,0,0,0};
istoggle=[0,1,1,0];
was_set=istoggle * 0;
paramtype={'InputFile','Integer','Integer','OutputFile'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(1,1);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
[varargout{:}]=callKhoros([w 'ksampline"  '],Inputs,narglist);