function pw_prob = visualise_pairwise_probabilities(expidx,firstidx,nImgs, cidx1, cidx2, bVis)

if (ischar(expidx))
    expidx = str2num(expidx);
end

if (nargin < 2)
    firstidx = 1;
end

if (ischar(firstidx))
    firstidx = str2num(firstidx);
end

if (nargin < 3)
    nImgs = 1;
elseif ischar(nImgs)
    nImgs = str2num(nImgs);
end

if (nargin < 6)
    bVis = true;
end

fprintf('cidxs: %d,%d\n', cidx1, cidx2);

image_set = 'test';
p = exp_params(expidx);
exp_dir = fullfile(p.expDir, p.shortName);
load(p.testGT,'annolist');

pidxs = p.pidxs;
num_joints = length(pidxs);
[~,parts] = util_get_parts24();

multicutDir = p.multicutDir;
mkdir_if_missing(multicutDir);
fprintf('multicutDir: %s\n',multicutDir);
visDir = fullfile(multicutDir, 'vis');
mkdir_if_missing(visDir);

num_images = size(annolist, 2);

lastidx = firstidx + nImgs - 1;
if (lastidx > num_images)
    lastidx = num_images;
end

if (firstidx > lastidx)
    return;
end

% computation parameters
pairwiseDir = p.pairwiseDir;
rotOffset = 0.5*pi;
if isfield(p, 'cidxs')
    cidxs = p.cidxs;
else
    cidxs = p.cidxs_full;
end
pad_orig = p.([image_set 'Pad']);
stride = 8;
scale_mul = sqrt(53);
scale_factor = p.scale_factor;
inv_scale_factor = 1/p.scale_factor;
locref = p.locref;

pwIdxsAllrel1 = cell(0);
n = 0;
for img_idx = 1:length(cidxs)-1
  for j = img_idx+1:length(cidxs)
    n = n + 1;
    pwIdxsAllrel1{n} = [cidxs(img_idx) cidxs(j)];
  end
end

fprintf('Loading spatial model from %s\n', pairwiseDir);
for sidx1 = 1:length(pwIdxsAllrel1)
    modelName  = [pairwiseDir '/spatial_model_cidx_' num2str(pwIdxsAllrel1{sidx1}(1)) '_' num2str(pwIdxsAllrel1{sidx1}(2))];
    %fprintf('%d %s\n', sidx1, modelName);
    try
        m = load(modelName,'spatial_model');
        spatial_model.diff(sidx1).log_reg = m.spatial_model.log_reg;
        spatial_model.diff(sidx1).training_opts = m.spatial_model.training_opts;
    catch
    end
end

nextreg = isfield(p, 'nextreg') && p.nextreg;
bidirect = isfield(p, 'bidirect') && p.bidirect;
neighbour_locref = isfield(p, 'neighbor_locref') && p.neighbor_locref;
allpairs = isfield(p, 'allpairs') && p.allpairs;

load(p.pairwise_relations, 'means', 'std_devs', 'graph');

pw_prob = [];

for img_idx = firstidx:lastidx
    fprintf('imgidx: %d\n',img_idx);

    tic
    fprintf('loading features... ');
    im_fn = annolist(img_idx).image.name;
    [~,im_name,~] = fileparts(im_fn);
    fprintf('displaying image %s\n', im_name);
    load(fullfile(p.pairwise_scoremap_dir, im_name), 'scoremaps');
    load(fullfile(p.pairwise_scoremap_dir, [im_name '_locreg']), 'locreg_pred');
    if nextreg
        load(fullfile(p.pairwise_scoremap_dir, [im_name '_nextreg']), 'nextreg_pred');
        nextreg_pred = nextreg_pred/scale_factor;
    end
    fprintf('done!\n');

    one_sm = squeeze(scoremaps(:,:,1));
    height = size(one_sm, 1);
    width  = size(one_sm, 2);

    num_proposals = height*width;
    idxsAll = 1:num_proposals;
    unPos = zeros(num_proposals, 2);
    if locref
        locationRefine = zeros(num_proposals, num_joints, 2);
    else
        locationRefine = 0;
    end
    num_scores = size(scoremaps, 3);
    unProb = zeros(num_proposals, num_scores);
    if nextreg
        nextReg = zeros(num_proposals, size(nextreg_pred, 3), size(nextreg_pred, 4));
    end
    for k = 1:num_proposals
        idx = idxsAll(k);
        [row, col] = ind2sub(size(one_sm), idx);
        % transform heatmap to image coordinates
        im_y = (row-1)*stride;
        im_x = (col-1)*stride;
        unPos(k, :) = [pad_orig, pad_orig] + [im_x, im_y]*inv_scale_factor;
        unProb(k, :) = scoremaps(row,col,:);
        if nextreg
            nextReg(k, :, :) = squeeze(nextreg_pred(row, col, :, :));
        end
        if locref
            locationRefine(k, :, :) = squeeze(locreg_pred(row, col, :, :))*scale_mul*inv_scale_factor;
        end
    end

    [is_neighbor, forward_edge, backward_edge] = search_in_graph(graph, cidx1, cidx2);

    person_id = 2;
    rect = annolist(img_idx).annorect(person_id);
    joints = get_anno_joints( rect, pidxs, parts);

    origin_joint = cidx1;
    gt_joint = joints(origin_joint, :);
    if isnan(gt_joint(1,1))
        continue;
    end

    sm_size = size(one_sm);
    gt_sm_coord = image2scoremap_coord(gt_joint, pad_orig, scale_factor, stride);

    if (gt_sm_coord(1) > sm_size(2)) || (gt_sm_coord(1) < 1)
        continue;
    end
    if (gt_sm_coord(2) > sm_size(1)) || (gt_sm_coord(2) < 1)
        continue;
    end

    gt_loc = sub2ind(sm_size, gt_sm_coord(2), gt_sm_coord(1));

    [q1,q2] = meshgrid(gt_loc,1:num_proposals);
    idxsAll = [q1(:) q2(:)];
    if origin_joint == cidx2
        idxsAll = [idxsAll(:,2) idxsAll(:,1)];
    end

    for sidx1 = 1:length(pwIdxsAllrel1)
        if (pwIdxsAllrel1{sidx1}(1)== cidx1 && pwIdxsAllrel1{sidx1}(2)== cidx2)
            break;
        end
    end
    assert(sidx1 <= length(pwIdxsAllrel1));

    adhoc_features = false;

    if ~is_neighbor
        [featDiff,~,cb1Diff,cb2Diff] = get_spatial_features_diff_img_dx_dy_dense(unPos,idxsAll,rotOffset,unProb);
        featDiff = get_augm_spatial_features_diff_dx_dy(featDiff,spatial_model.diff(sidx1).training_opts.X_pos_mean, p);
        feat_norm = getFeatNorm(featDiff,spatial_model.diff(sidx1).training_opts.X_min,spatial_model.diff(sidx1).training_opts.X_max);
    elseif adhoc_features
        featDiff = get_spatial_features_neighbour_img(unPos,idxsAll,squeeze(nextReg(:,[forward_edge backward_edge],:)));
        featDiff = get_augm_spatial_features_diff_neighbour(featDiff);
        dists = featDiff(:, 1);
        prob = 1./(1+exp(0.2*dists-7.5));
        dists = featDiff(:, 3);
        prob2 = 1./(1+exp(0.2*dists-7.5));
        prob = prob .* prob2;
    else
        if neighbour_locref

            featDiff = get_spatial_features_neighbour_locref(unPos,idxsAll, ...
                                                             squeeze(nextReg(:,[forward_edge backward_edge],:)), ...
                                                             squeeze(locationRefine(:,[cidx1 cidx2],:)));
            featDiff = get_augm_spatial_features_diff_neighbour_locref(featDiff);
            feat_norm = getFeatNorm(featDiff,spatial_model.diff(sidx1).training_opts.X_min,spatial_model.diff(sidx1).training_opts.X_max);

            ex = sparse(double(feat_norm));
            model = spatial_model.diff(sidx1).log_reg;
            [~,acc,prob] = predict(zeros(size(ex,1),1), ex, model, '-b 1');
            prob = prob(:, 1);

            %{
            feat_norm1 = feat_norm;
            feat_norm1(:,[1 2 5 6]) = 0;
            ex = sparse(double(feat_norm1));
            model = spatial_model.diff(sidx1).log_reg;
            [~,acc,prob] = predict(zeros(size(ex,1),1), ex, model, '-b 1');
            prob1 = prob(:, 1);

            feat_norm2 = feat_norm;
            feat_norm2(:,[3 4 7 8]) = 0;
            ex = sparse(double(feat_norm2));
            model = spatial_model.diff(sidx1).log_reg;
            [~,acc,prob] = predict(zeros(size(ex,1),1), ex, model, '-b 1');
            prob2 = prob(:, 1);

            prob = prob1 .* prob2;
            %}

        else
            featDiff = get_spatial_features_neighbour_img(unPos,idxsAll,squeeze(nextReg(:,[forward_edge backward_edge],:)));
            featDiff = get_augm_spatial_features_diff_neighbour(featDiff, p);
            feat_norm = getFeatNorm(featDiff,spatial_model.diff(sidx1).training_opts.X_min,spatial_model.diff(sidx1).training_opts.X_max);
        end
    end

    if adhoc_features || neighbour_locref
    else
        ex = sparse(double(feat_norm));
        model = spatial_model.diff(sidx1).log_reg;
        [~,acc,prob] = predict(zeros(size(ex,1),1), ex, model, '-b 1');
        prob = prob(:, 1);
    end

    %histogram(prob);
    im = imread(im_fn);
    im = im(pad_orig+1:end-pad_orig, pad_orig+1:end-pad_orig, :);

    %figure(1);
    %clf;
    %imagesc(im);

    pw_prob = reshape(prob, height, width);

    enhance_contrast = false;
    if enhance_contrast
        zr = zeros(size(pw_prob));
        thr = 0.65;
        pw_prob = max((pw_prob-thr)/(1-thr), zr);
    end

    %imagesc(pw_prob);
    scmap = visualise_scoremap( pw_prob, 1 );

    scmap = imresize(scmap, [size(im, 1), size(im, 2)], 'bicubic');
    pw_prob_img = imresize(pw_prob, [size(im, 1), size(im, 2)], 'bicubic');

    %figure(100);
    %imshow(scmap);

    %hold on;
    %figure(2);
    %imagesc(pw_prob_img);
    %colorbar;

    color1 = [1 0 1];
    colors = [1 0 1; 1 1 0; 0 1 1; 1 0 0; 0 1 0; 0 0 1; 1 1 1; 1 1 0; 1 0 1; 0 1 1; 1 0 0; 0 1 0; 0 0 1; 1 1 1];
    c = reshape(colors(cidx1, :), 1, 1, 3);
    color_rep = repmat(c, size(im, 1), size(im, 2), 1);
    color_rep = color_rep*255;

    pw_prob_img = repmat(pw_prob_img, 1, 1, 3);
    %figure(4);
    %imagesc(pw_prob_img);

    %scmap = uint8(scmap*255);
    %limm = uint8(ones(size(im))*255);
    %im_sc = min(im+scmap, limm);

    if bVis
        figure(3);
        final_img = (pw_prob_img) .* double(color_rep) + (1-pw_prob_img) .* double(im);
        final_img = uint8(final_img);
        imshow(final_img);

        axis off;
        set(gca, 'LooseInset', get(gca, 'TightInset'));
        %fname = fullfile('/BS/eldar/work/pose/misc/pairwise-scoremaps/lsp-test', [num2str(img_idx) '_cidxs_' num2str(cidx1) '_' num2str(cidx2) '.png']);
        %print(gcf,'-dpng', fname);
    end

    if img_idx ~= lastidx
        pause;
    end
    continue;
    %{
    for row = 1:2:height
        for col = 1:2:width
            % transform heatmap to image coordinates
            im_y = (row-1)*stride;
            im_x = (col-1)*stride;
            s = [im_x, im_y]*inv_scale_factor;
            e = s + squeeze(nextreg_pred(row, col, forward_edge, :))';
            line([s(1) e(1)], [s(2) e(2)], 'Color', 'r');
        end
    end
    %}

    gt_joint1 = joints(cidx1, :);
    gt_sm_coord1 = image2scoremap_coord(gt_joint1, pad_orig, scale_factor, stride);
    gt_loc1 = sub2ind(sm_size, gt_sm_coord1(2), gt_sm_coord1(1));

    gt_joint2 = joints(cidx2, :);
    gt_sm_coord2 = image2scoremap_coord(gt_joint2, pad_orig, scale_factor, stride);
    gt_loc2 = sub2ind(sm_size, gt_sm_coord2(2), gt_sm_coord2(1));

    s = gt_joint1 - [pad_orig, pad_orig];
    e = s + squeeze(nextreg_pred(gt_sm_coord1(2), gt_sm_coord1(1), forward_edge, :))';
    line([s(1) e(1)], [s(2) e(2)], 'Color', 'r');
    plot(s(1), s(2), 'go', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'k', 'MarkerSize', 5);

    s = gt_joint2 - [pad_orig, pad_orig];
    e = s + squeeze(nextreg_pred(gt_sm_coord2(2), gt_sm_coord2(1), backward_edge, :))';
    line([s(1) e(1)], [s(2) e(2)], 'Color', 'b');
    plot(s(1), s(2), 'go', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'k', 'MarkerSize', 5);

    if origin_joint == cidx1
        val_at_gt = prob(gt_loc2);
    else
        val_at_gt = prob(gt_loc1);
    end
    fprintf('pairwise probability is %f\n', val_at_gt);

    pause;
end

fprintf('done\n');

if (isdeployed)
    close all;
end

end

function coord = image2scoremap_coord(joint, pad_orig, scale_factor, stride)
coord = round((joint - [pad_orig, pad_orig])*scale_factor/stride + [1, 1]);
end


function response = Waffely(n,p)

persistent oscyflag
if n==1; oscyflag=1; end
if oscyflag
    response = 'cooperate';
    oscyflag=0;
else
    response = 'defect';
    oscyflag=1;
end


function [curr_dat_sz, curr_lab_sz] = store2hdf5(filename, data, labels, create, startloc, chunksz)
  % *data* is W*H*C*N matrix of images should be normalized (e.g. to lie between 0 and 1) beforehand
  % *label* is D*N matrix of labels (D labels per sample)
  % *create* [0/1] specifies whether to create file newly or to append to previously created file, useful to store information in batches when a dataset is too big to be held in memory  (default: 1)
  % *startloc* (point at which to start writing data). By default,
  % if create=1 (create mode), startloc.data=[1 1 1 1], and startloc.lab=[1 1];
  % if create=0 (append mode), startloc.data=[1 1 1 K+1], and startloc.lab = [1 K+1]; where K is the current number of samples stored in the HDF
  % chunksz (used only in create mode), specifies number of samples to be stored per chunk (see HDF5 documentation on chunking) for creating HDF5 files with unbounded maximum size - TLDR; higher chunk sizes allow faster read-write operations

  % verify that format is right
  dat_dims=size(data);
  lab_dims=size(labels);
  num_samples=dat_dims(end);

  assert(lab_dims(end)==num_samples, 'Number of samples should be matched between data and labels');

  if ~exist('create','var')
    create=true;
  end

  if create
    %fprintf('Creating dataset with %d samples\n', num_samples);
    if ~exist('chunksz', 'var')
      chunksz=1000;
    end
    if exist(filename, 'file')
      fprintf('Warning: replacing existing file %s \n', filename);
      delete(filename);
    end
    h5create(filename, '/data', [dat_dims(1:end-1) Inf], 'Datatype', 'single', 'ChunkSize', [dat_dims(1:end-1) chunksz]); % width, height, channels, number
    h5create(filename, '/label', [lab_dims(1:end-1) Inf], 'Datatype', 'single', 'ChunkSize', [lab_dims(1:end-1) chunksz]); % width, height, channels, number
    if ~exist('startloc','var')
      startloc.dat=[ones(1,length(dat_dims)-1), 1];
      startloc.lab=[ones(1,length(lab_dims)-1), 1];
    end
  else  % append mode
    if ~exist('startloc','var')
      info=h5info(filename);
      prev_dat_sz=info.Datasets(1).Dataspace.Size;
      prev_lab_sz=info.Datasets(2).Dataspace.Size;
      assert(all(prev_dat_sz(1:end-1)==dat_dims(1:end-1)), 'Data dimensions must match existing dimensions in dataset');
      assert(all(prev_lab_sz(1:end-1)==lab_dims(1:end-1)), 'Label dimensions must match existing dimensions in dataset');
      startloc.dat=[ones(1,length(dat_dims)-1), prev_dat_sz(end)+1];
      startloc.lab=[ones(1,length(lab_dims)-1), prev_lab_sz(end)+1];
    end
  end

  if ~isempty(data)
    h5write(filename, '/data', single(data), startloc.dat, size(data));
    h5write(filename, '/label', single(labels), startloc.lab, size(labels));
  end

  if nargout
    info=h5info(filename);
    curr_dat_sz=info.Datasets(1).Dataspace.Size;
    curr_lab_sz=info.Datasets(2).Dataspace.Size;
  end
end


function [merged_timestamps, merged_signal] = ...
    merge_samples4(timestamps1, samples1, timestamps2, samples2, ...
                   timestamps3, samples3, timestamps4, samples4)
    % Merge samples given their timestamps

    [merged_timestamps, ix] = sort([timestamps1(:); timestamps2(:); ...
        timestamps3(:); timestamps4(:)]);
    merged_signal = [samples1(:); samples2(:); samples3(:); samples4(:)];
    labels = [ones(length(samples1), 1); ones(length(samples2), 1) * 2; ...
              ones(length(samples3), 1) * 3; ones(length(samples4), 1) * 4];
    merged_signal = merged_signal(ix);
end


function pyra = demo_deep_pyramid(im)
% Demonstrate basic usage and visualize features.
%
%
% AUTORIGHTS
% ---------------------------------------------------------
% Copyright (c) 2014, Ross Girshick
%
% This file is part of the DeepPyramid code and is available
% under the terms of the Simplified BSD License provided in
% LICENSE. Please retain this notice and LICENSE if you use
% this file (or any portion of it) in your project.
% ---------------------------------------------------------

if exist('caffe') ~= 3
  error('You must add matcaffe to your path.');
end

if ~exist('data/caffe_nets/ilsvrc_2012_train_iter_310k')
  error(['You need the CNN model in %s. ' ...
         'You can get this model by following ' ...
         'the R-CNN installation instructions.'], ...
        'data/caffe_nets/ilsvrc_2012_train_iter_310k');
end

if 1
  % real use settings (compute features using the GPU)
  USE_GPU = true;
  USE_CACHE = false;
  USE_CAFFE = true;
else
  % fast demo settings
  USE_GPU = false;
  USE_CACHE = true;
  USE_CAFFE = false;
end

if ~exist('im', 'var') || isempty(im)
  im = imread('000084.jpg');
end
bbox = [263 145 381 225];

cnn = init_cnn_model('use_gpu', USE_GPU, 'use_caffe', USE_CAFFE);

if USE_CACHE
  cache_opts.cache_file = './cached_pyra.mat';
  cache_opts.debug = true;
  cache_opts.write_on_miss = true;
  th = tic;
  pyra = deep_pyramid_cache_wrapper(im, cnn, cache_opts);
  fprintf('deep_pyramid_cache_wrapper took %.3fs\n', toc(th));
else
  th = tic;
  pyra = deep_pyramid(im, cnn);
  fprintf('deep_pyramid took %.3fs\n', toc(th));
end
padx = 0;
pady = 0;

pyra = deep_pyramid_add_padding(pyra, padx, pady);

fprintf(['Press almost any key (with fig focused) to loop through ' ...
         'feature channels (or esc to exit).\n']);
for channel = 1:256
  vis_pyramid(im, pyra, bbox, channel);
  [~, ~, key_code] = ginput(1);
  if key_code == 27
    break;
  end
end

% ------------------------------------------------------------------------
function vis_pyramid(im, pyra, bbox, channel)
% ------------------------------------------------------------------------

pyra_boxes = im_to_pyra_coords(pyra, bbox);

clf;

rows = 2;
cols = 4;
subplot(rows, cols, 1);
imagesc(im);
axis image;
rectangle('Position', bbox_to_xywh(bbox), 'EdgeColor', 'g');
title(sprintf('input image feature %d', channel));

max_val = 0;
for level = 1:pyra.num_levels
  f = pyra.feat{level}(:,:,channel);
  max_val = max(max_val, max(f(:)));
end

ld = load('green_colormap');
colormap(ld.map); clear ld;

for level = 1:pyra.num_levels
  subplot(rows, cols, level+1);
  imagesc(pyra.feat{level}(:,:,channel), [0 max_val]);
  axis image;
  rectangle('Position', bbox_to_xywh(pyra_boxes{level}), 'EdgeColor', 'r');
  title(sprintf('level %d; scale = %.2fx', level, pyra.scales(level)));

  % project pyramid box back to image and display as red
  im_bbox = pyra_to_im_coords(pyra, [pyra_boxes{level} level]);
  subplot(rows, cols, 1);
  rectangle('Position', bbox_to_xywh(im_bbox), 'EdgeColor', 'r');
  %text(im_bbox(1), im_bbox(2), sprintf('%d', level));
end

function xywh = bbox_to_xywh(bbox)
xywh = [bbox(1) bbox(2) bbox(3)-bbox(1)+1 bbox(4)-bbox(2)+1];


%
% Visualize a MotorProgram
%
% additional arguments 'motor' plots the motor trace,
% and the arguments 'image' and 'pmap' can select
% betwen the image and the probability map
%
%  Other parameters
%  'size_start' : where 0 if we don't want to plot the start points
%  'lw' : line width for strokes
function vizMP(M,varargin)

    assert(isa(M,'MotorProgram'));

    n = length(varargin);
    use_pimg = any(strcmp('pmap',varargin)) || any(strcmp('pimg',varargin));
    use_img = any(strcmp('image',varargin));
    assert(~(use_pimg && use_img));
    use_motor = any(strcmp('motor',varargin));

    % what is the size of the start marker?
    fstart = find(strcmp('size_start',varargin));
    size_start = [];
    if ~isempty(fstart)
        size_start = varargin{fstart+1};
    end
    assert(isnumeric(size_start));

    % what is the line width?
    flw = find(strcmp('lw',varargin));
    lw = [];
    if ~isempty(flw)
       lw = varargin{flw+1};
    end

    if use_motor
        if use_pimg
            plot_motor_to_image(M.pimg,M.motor_warped,size_start,lw);
        else
            plot_motor_to_image(M.I,M.motor_warped,size_start,lw);
        end
    else
        if use_pimg
            plot_image_only(M.pimg);
        else
            plot_image_only(M.I);
        end
    end

end


function h = mgaussianNoisePointPlot(noise, X, y, fontName, fontSize, markerSize, lineWidth)

% MGAUSSIANNOISEPOINTPLOT Plot the data-points for the MGAUSSIAN noise model.
% FORMAT
% DESC plots the data point locations for the multiple output Gaussian
%  noise structure.
% ARG noise : the noise structure which is to be plotted.
% ARG X : input locations to be plotted.
% ARG y : target locations to be plotted.
% ARG fontName : name of any fonts to be used.
% ARG fontSize : size of any fonts to be used.
% ARG markerSize : size of the makers to be used.
% ARG lineWidth : size of any lines to be plotted.
%
% SEEALSO : mgaussianNoiseParamInit, noisePointPlot
%
% COPYRIGHT : Neil D. Lawrence, 2004, 2005

% NOISE


function UpdateSliceOMatic(X,hSlico)
% This should get the data you want:

% Copyright 2004-2010 The MathWorks, Inc.

if nargin<2
  hSlico=gcf;
else                %%RAB%%
  figure(hSlico)    %%RAB%%
end

D = getappdata(hSlico,'sliceomatic');
D.data = X;
setappdata(hSlico,'sliceomatic',D)

% Get axes children objects that are surfaces
ch = findobj('Type','Surface');

% If no slice then no need to update data in the image

if isempty(ch)
    return
end

% Loop thorugh slices
for i=1:length(ch)
    mySlice = ch(i);

    % Get the X, Y, Z Data
    XData = get(mySlice,'XData');
    YData = get(mySlice,'YData');
    ZData = get(mySlice,'ZData');

    % Find out which one doesn't change by finding the differene in X,Y,Z values
    diffxyz = [all(diff(XData(:))==0) all(diff(YData(:))==0) all(diff(ZData(:))==0)];
    [nodiff, i] = max(diffxyz);

    % Make updates to appropriate slice
    switch i
        case 1
            slice = round(XData(1));
            set(mySlice,'CData',squeeze(X(:,slice,:)))
        case 2
            slice = round(YData(1));
            set(mySlice,'CData',squeeze(X(slice,:,:)))
        case 3
            slice = round(ZData(1));
            set(mySlice,'CData',squeeze(X(:,:,slice)))
    end

end

% % The subroutine is attached. It takes the 3D image matrix as its input. So
% % if using sliceomatic you would do the following:
% %
% % 1. Read Images
% % 2. Manipulate
% % 3. Call sliceomatic(ImageData)
% % 4. Make some changes (i.e. ImageData(ImageData<100)=0
% % 5. call mySubRoutine(ImageData)
% %
% % Everything should be updated and it runs fast
% %
% % --L--
% %
% % -----Original Message-----
% % From: Robert Bemis
% % Sent: Friday, February 20, 2004 2:26 PM
% % To: Laurens Schalekamp
% % Subject: movtext
% %
% % Please enjoy file: movtext
% % courtesy of rbemis@mathworks.com


function cp_ptp = cat_cp_ptp(cp, ptp)
% Concatenate CP and PTP trajectory
%
% [Inputs]
%	cp			: CP trajectory
%	ptp			: PTP trajectory
% [Outputs]
%	cp_ptp		: CP + PTP trajectory

num_cp = length(cp);
num_ptp = length(ptp);
cp_ptp = cell(1, num_cp + num_ptp);
for n = 1:num_cp
	cp_ptp{2 * n} = cp{n};
	cp_ptp{2 * n - 1} = ptp{n};
end
cp_ptp{end} = ptp{end};


function [varargout]=icolorbar(varargin)

% function [h,hc]=icolorbar(cLim,h)
%-------------------------------------------------------------------------
%
%
% Change log:
% 2018/05/10 Fixed bug in relation to older matlab versions which do not
% support h.Colormap=c for axis specific color maps. Older versions use
% colormap(h,c) instead.
% 2019/08/14 Added colorbar handle output
%-------------------------------------------------------------------------

%% parse input

switch nargin
    case 0
        cLim=caxis;
        h=[];
    case 1
        cLim=varargin{1};
        h=[];
    case 2
        cLim=varargin{1};
        h=varargin{2};
end

if isempty(cLim)
    cLim=caxis;
end

if isempty(h)
    %Get current figure or open a new one
    if isempty(findobj('type','figure'))
        hf=cFigure; %Open a new figure
    else
        hf=gcf; %Get the current figure
    end
   figure(hf);
   if isempty(hf.CurrentAxes) %isempty(get(hf,'CurrentAxes'))
       h=axes;
   else
       h=gca;
   end
else
    switch class(h)
        case {'matlab.ui.Figure'} %A figure handle
            hf=h;
            if isempty(hf.CurrentAxes) %isempty(get(hf,'CurrentAxes'))
                h=axes;
            else
                h=gca;
            end
        case {'matlab.graphics.axis.Axes'} %An axes handle
            hf=h.Parent; %Get figure handle
        otherwise
            error('Handle does not represent an axis or figure handle');
    end
end

%% Get colormap
if isprop(h,'Colormap') %Available in MATLAB 2018
    c=h.Colormap;
    matlabNew=1;
else %Older MATLAB versions
    c=colormap(h);
    matlabNew=0;
end

%% Set limits and tick labels
caxis([cLim(1)-0.5 cLim(2)+0.5]);
hc=colorbar;
hc.Ticks=cLim(1):1:cLim(2);
cn=resampleColormap(c,numel(hc.Ticks));
if matlabNew==1 %axis colormap
    h.Colormap=cn;
else %Figure colormap
    colormap(h,cn);
end

%% Collect output
switch nargout
    case 1
        varargout{1}=h;
    case 2
        varargout{1}=h;
        varargout{2}=hc;
end

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


function planC = fixStructureZVals(planC)
%Compares zVals stored in structure contours to CT zValues.
%Correct by replacing the structure's zVals with those of
%the CT slice it was contoured on.
%
%We have encountered some archives where the two do not match,
%which causes problems with generating 3D datasets.
%
% JRA 10/24/03
%
% TODO: Vectorize.
%
% 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/>.

indexS = planC{end};
ctZVal = [planC{indexS.scan}.scanInfo.zValue];

for structNum=1:length(planC{indexS.structures})
    errorFound = 0;
    errorDiff = [];
    contour = planC{indexS.structures}(structNum).contour;
    for sliceNum=1:length(contour)
        for pointsSet=1:length(contour(sliceNum).segments)
            if ~isempty(contour(sliceNum).segments(pointsSet).points)
                structureZVals = contour(sliceNum).segments(pointsSet).points(:,3);

                uniqStrZvals = unique(structureZVals);
                if length(uniqStrZvals) > 1
                    for uniqInd = 1:length(uniqStrZvals)
                        indZvals = find(structureZVals==uniqStrZvals(uniqInd));
                        numInds(uniqInd) = length(indZvals);
                    end
                    [jnk,maxInd] = max(numInds);

                    uniqStructVal = uniqStrZvals(maxInd);
                    CERRStatusString(['Structure "',planC{indexS.structures}(structNum).structureName,'" has inconsistent contours defined at z = ', num2str(ctZVal(ind)), ' slice location.'])
                    CERRStatusString(['Using the contour points defined at z = ',num2str(uniqStructVal)])
                else
                    uniqStructVal = uniqStrZvals;
                end

                %ind = findnearest(ctZVal, unique(structureZVals));
                ind = findnearest(ctZVal, uniqStructVal);

                wrongZVals = structureZVals ~= ctZVal(ind);

                if find(wrongZVals)
                    errorFound = 1;
                    errorDiff = [errorDiff abs(structureZVals' - ctZVal(ind))];
                    contour(sliceNum).segments(pointsSet).points(find(wrongZVals),3) = ctZVal(ind);
                end
            end
        end
    end
    %Now check for bad rasterSegment zValues, that may have been created in
    %old plans from uncorrected contour data.
    %     for sliceNum=1:length(contour)
    [rasterSegs, planC, isError] = getRasterSegments(structNum, planC);
    %rasterSegs = planC{indexS.structures}(structNum).rasterSegments;
    if ~isempty(rasterSegs)
        if rasterSegs(:,1) ~= [planC{indexS.scan}.scanInfo(rasterSegs(:,6)).zValue]';
            rasterSegs(:,1) = [planC{indexS.scan}.scanInfo(rasterSegs(:,6)).zValue]';
        end
    end
    planC{indexS.structures}(structNum).rasterSegments = rasterSegs;
    %     end

    if errorFound
        CERRStatusString(['Correcting inconsistent zValues in ' planC{indexS.structures}(structNum).structureName '. Median correction is ' num2str(median(errorDiff)) ' cm.']);
        planC{indexS.structures}(structNum).contour = contour;
    end
end
CERRStatusString('');


function z = psdinvjmul(xlab,xfrm, y, K) %#ok
% z = psdinvjmul(xlab,xfrm, y, K)
%
% PSDINVJMUL  solves x jmul z = y, with x = XFRM*diag(xlab)*XFRM'
%
% **********  INTERNAL FUNCTION OF SEDUMI **********
%
% See also sedumi

% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA  (since 1.1)
%
% Copyright (C) 2001 Jos F. Sturm (up to 1.05R5)
%   Dept. Econometrics & O.R., Tilburg University, the Netherlands.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% Affiliation SeDuMi 1.03 and 1.04Beta (2000):
%   Dept. Quantitative Economics, Maastricht University, the Netherlands.
%
% Affiliations up to SeDuMi 1.02 (AUG1998):
%   CRL, McMaster University, Canada.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% 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.,  51 Franklin Street, Fifth Floor, Boston, MA
% 02110-1301, USA

%Indicate to the user Matlab cannot find the SeDuMi binaries
sedumi_binary_error();


function glottal_pulse_GUI25
% Modifiable runGUI file
clc;
clear all;
fileName = 'glottal_pulse.mat';    %USER - ENTER FILENAME
fileData=load(fileName);
temp=fileData(1).temp;

f = figure('Visible','on',...
'Units','normalized',...
'Position',[0,0,1,1],...
'MenuBar','none',...
'NumberTitle','off');

Callbacks_glottal_pulse_GUI25(f,temp);    %USER - ENTER PROPER CALLBACK FILE
%panelAndButtonEdit(f, temp);       % Easy access to Edit Mode

% Note comment PanelandBUttonCallbacks(f,temp) if panelAndButtonEdit is to
% be uncommented and used
end

% glottal_pulse_rev1_gui25 design
% 2 Panels
%   #1 - parameters
%   #2 - graphics
% 2 Graphic Panels
%   #1 - glottal pulse impulse response
%   #2 - glottal pulse frequency response
% 1 TitleBox
% 8 Buttons
%   #1 - editable button - alpha1: rising glottal pulse cycle
%   #2 - editable button - alpha2: falling glottal pulse cycle
%   #3 - editable button - period for periodic excitation
%   #4 - popupmenu - list of vowel sounds for synthesis
%   #5 - pushbutton - Play impulse train
%   #6 - pushbutton - Play glottal pulses
%   #7 - pushbutton - Play vowel sound
%   #8 - pushbutton - Close GUI


classdef WindowData

  methods (Static)

    function wd = windowdata(nCls)
      % Windowdata constructor
      % nCls: number of classifiers
      % wd: struct array, indexed by classifier
      %
      %
      % .labelidx_cur
      % .labelidx_new
      % .labelidx_old: These three arrays take the same values as
      % Labels.labelidx.vals. A 0 value indicates 'unlabeled'; Otherwise
      % the values are label indices 1:nlabels.

      % ALTODO see below, NUA='not used anymore',
      % ALTODO: correct-sized empties (pass windowdataVerify)

      wd = struct(...
        'X',single([]), ...
        'exp',cell(nCls,1), ...
        'flies',[], ...
        't',[], ...
        'labelidx_cur',[], ...
        'labelidx_new',[], ...
        'labelidx_old',[], ...
        'labelidx_imp',[], ...
        'featurenames',{{}}, ...
        'predicted',[], ... % NUA
        'predicted_probs',[], ... % NUA
        'isvalidprediction',[], ... % NUA
        'distNdx',[], ...
        'scores',[], ... % NUA
        'scoreNorm',[], ...
        'binVals',[], ...
        'scores_old',[], ... % NUA
        'scores_validated',[], ...
        'postprocessed',[],... % NUA?
        'bins',[]);
    end

    function windowdataVerify(wd)
      for iCls = 1:numel(wd)
        w = wd(iCls);
        [n,nftr] = size(w.X);

        assert(isequal([n 1],size(w.exp),size(w.flies),size(w.t),...
          size(w.labelidx_cur),size(w.labelidx_new),size(w.labelidx_old),...
          size(w.labelidx_imp)) || ...
          isempty(w.exp) && isempty(w.flies) && isempty(w.t) && ... % AL: alternate condition here for legacy compat
          isempty(w.labelidx_cur) && isempty(w.labelidx_new) && ...
          isempty(w.labelidx_old) && isempty(w.labelidx_imp));

        assert(numel(w.featurenames)==nftr);
        if ~isempty(w.binVals),
          assert(size(w.bins,1) == nftr && size(w.bins,2) == n);
        end

        % scoreNorm?
        % binVals?
      end
    end

    function wd = windowdataClear(wd)
      for iCls = 1:numel(wd)
        wd(iCls).X = single([]);
        wd(iCls).exp = [];
        wd(iCls).flies = [];
        wd(iCls).t = [];
        wd(iCls).labelidx_cur = [];
        wd(iCls).labelidx_new = [];
        wd(iCls).labelidx_imp = [];
        wd(iCls).labelidx_old = [];
        wd(iCls).featurenames = {{}};

        wd(iCls).predicted = [];
        wd(iCls).predicted_probs = [];
        wd(iCls).isvalidprediction = [];
        wd(iCls).distNdx = [];
        wd(iCls).scores = [];
        wd(iCls).scoreNorm = [];
        wd(iCls).binVals = [];
        wd(iCls).bins = uint8([]);
        wd(iCls).scores_old = [];
        wd(iCls).scores_validated = [];
        wd(iCls).postprocessed  = [];
      end
    end

    function wd = windowdataTrim(wd,predFcn)
      assert(isa(predFcn,'function_handle'));

%       sizeLimit = obj.cacheSize*1e6;
%       classSize = 4;
%       ratioLimit = 0.2;
%
%       numUnlabeled = nnz(obj.windowdata.labelidx_new==0);
%       numLabeled = nnz(obj.windowdata.labelidx_new);
%
%       if (nargin < 2 || ~doforce) && (numel(obj.windowdata.X)*classSize < sizeLimit || numUnlabeled/numLabeled<ratioLimit);
%         return;
%       end
%
%       idx2remove = obj.windowdata.labelidx_new==0 & ...
%         ~obj.FlyNdx(obj.expi,obj.flies);

      for i = 1:numel(wd)
        n = size(wd(i).X,1);
        % MAYANK_JAN16_2015: Don't trim if there is no windowdata.
        if n == 0, continue ; end
        tfRm = predFcn(wd(i));
        assert(islogical(tfRm)&&isvector(tfRm)&&numel(tfRm)==n);
        % MAYANK MAY9 2016  don't trim if there is nothing to trim.
        if nnz(tfRm)<1, continue ;end
        wd(i).X(tfRm,:) = [];
        wd(i).exp(tfRm,:) = [];
        wd(i).flies(tfRm,:) = [];
        wd(i).t(tfRm,:) = [];
        wd(i).bins(:,tfRm) = [];
        wd(i).labelidx_cur(tfRm,:) = [];
        wd(i).labelidx_new(tfRm,:) = [];
        wd(i).labelidx_imp(tfRm,:) = [];
        wd(i).labelidx_old(tfRm,:) = [];
        wd(i).distNdx = [];
%        wd(i).binVals = [];
        wd(i).scores_validated(tfRm,:) = [];

%         wd(i).isvalidprediction(idxcurr(1:numel(wd(i).isvalidprediction))) = [];
%         wd(i).predicted(idxcurr(1:numel(wd(i).predicted))) = [];
%         wd(i).predicted_probs(idxcurr(1:numel(wd(i).predicted_probs))) = [];
%         wd(i).scores(idxcurr(1:numel(wd(i).scores))) = [];
%         wd(i).scores_old(idxcurr(1:numel(wd(i).scores_old))) = [];
%         wd(i).postprocessed(idxcurr(1:numel(wd(i).postprocessed)),:) = [];
      end
    end

    function wd = windowdataSetFeaturenames(wd,featurenames)
      assert(iscell(featurenames)&&numel(featurenames)==numel(wd));
      for i = 1:numel(wd)
        nFtr = numel(featurenames{i});
        if isequal(wd(i).X,[])
          wd(i).X = zeros(0,nFtr);
        else
          nCol = size(wd(i).X,2);
          assert(nCol==nFtr,...
            'Number of featurenames (%d) does not match number of cols in feature matrix (%d).',...
            nFtr,nCol);
        end
        wd(i).featurenames = featurenames{i};
      end
    end

    function wd = windowdataRemapLabelIdxs(wd,oldIdx2NewIdx)
      % oldIdx2NewIdx: vector of length number-of-old-labels.
      % oldIdx2NewIdx(i) contains the new label index corresponding to i.

      LABEL_FIELDS = {'labelidx_cur' 'labelidx_new' 'labelidx_old'};
      for iCls = 1:numel(wd)
        w = wd(iCls);
        for fld = LABEL_FIELDS, fld=fld{1}; %#ok<FXSET>
          tfnz = w.(fld)~=0;
          newNZVals = oldIdx2NewIdx(w.(fld)(tfnz));
          assert(all(newNZVals>0));
          w.(fld)(tfnz) = newNZVals;
        end
        wd(iCls) = w;
      end
    end

    % MK: Add thresholded bins to window data. May 10 2016
    function [wd,wdmodified ] = modernize(wd)
      wdmodified = false;
      if ~isfield(wd,'bins'),
        if numel(wd)>0,
          for ndx = 1:numel(wd),
            if ~isempty(wd(ndx).binVals),
              wd(ndx).bins = findThresholdBins(wd(ndx).X,wd(ndx).binVals);
            else
              wd(ndx).bins = uint8([]);
            end
          end
        else
          tmp=cell(size(wd)); [wd(:).bins]=deal(tmp{:});
        end
        wdmodified = true;
      end

    end

  end

end


function imdb = getTIDDatabase_train(Dir)

fileID = fopen(fullfile(Dir,'\mos_with_names.txt'));
mos_name = textscan(fileID,'%f %s');
mos = mos_name{1,1};
name = mos_name{1,2};

path = cell(1,3000);
for i = 1:3000
    namet = name{i,1};
%     path{1,i} = fullfile(Dir,'distorted_images',namet);
    path{1,i} = fullfile('distorted_images',namet);
end

imdb.mos = mos';
imdb.label = imdb.mos;
imdb.name = name;
imdb.imgpath = path;
imdb.filenum = 3000;
imdb.refnum = 25;
imdb.dataset = 'TID2013';

refpath = fullfile(Dir,'reference_images');
refpath = strcat(refpath,'\');
dir_rf = dir([refpath '*.BMP']);
imdb.refname = cell(1,25);
for i = 1:25
    file_name = dir_rf(i).name;
    %imdb.refname{i} = string(file_name);
    imdb.refname{i} = file_name;
end

imdb.refnames_all = cell(1,3000);
for i = 1:25
    for j = 1:120
        imdb.refnames_all{1,(i-1)*120+j} = imdb.refname{i};
    end
end

sel = randperm(25);
train_path = [];
train_mos = [];
for i = 1:20
    train_sel = strcmpi(imdb.refname(sel(i)),imdb.refnames_all );
    train_sel = find(train_sel == 1);
    train_path = [train_path, imdb.imgpath(train_sel)];
    train_mos = [train_mos,imdb.label(train_sel)];
end

test_path = [];
test_mos = [];
for i = 21:25
    test_sel = strcmpi(imdb.refname(sel(i)),imdb.refnames_all );
    test_sel = find(test_sel == 1);
    test_path = [test_path, imdb.imgpath(test_sel)];
    test_mos = [test_mos,imdb.label(test_sel)];
end

imdb.images.id = 1:3000 ;
imdb.images.set = [ones(1,size(train_path,2)),2*ones(1,size(test_path,2))];
imdb.images.label = [train_mos,test_mos];
imdb.images.label = imdb.images.label * 100/9 ;
imdb.classes.description = {'TID2013'};
imdb.images.name = [train_path,test_path] ;
imdb.imageDir = Dir ;
fclose(fileID);


classdef ShapesPrinter < CompositeResultsPrinter

    properties (Access = private)
        allShapes
        printableIndex
    end

    methods (Access = public)

        function obj = ShapesPrinter(d)
            obj.simulationStr = 'ShapePrinters';
            obj.obtainAllShapes(d);
            obj.obtainPrintableIndex();
            obj.init(d);
        end

    end

    methods (Access = protected)

        function createPrinters(obj,d)
            pI = obj.printableIndex;
            aS = obj.allShapes;
            nShapes = numel(pI);
            obj.printers = cell(nShapes,1);
            for ishape = 1:nShapes
                index = obj.printableIndex(ishape);
                shape = aS{index};
                d.fieldToPrint = shape.createPrintVariables();
                p = ShapePrinter(d);
                obj.printers{ishape} = p;
            end
        end

        function storeFieldsToPrint(obj,d)
            obj.obtainAllShapes(d);
            obj.obtainPrintableIndex();
            for iprinter = 1:numel(obj.printers)
                index = obj.printableIndex(iprinter);
                shape = obj.allShapes{index};
                fP = shape.addPrintableVariables();
                d.fieldToPrint = fP;
                p = obj.printers{iprinter};
                p.storeFieldsToPrint(d);
            end
        end

        function createHeadPrinter(obj,d,dh)
            for iprinter = 1:numel(obj.printers)
                index = obj.printableIndex(iprinter);
                shape = obj.allShapes{index};
                if obj.getHasGaussData()
                  if ~isfield(d,'quad')
                      d.quad = shape.getQuad();
                  else
                      if isempty(d.quad)
                        d.quad = shape.getQuad();
                      end
                  end
                else
                    d.quad = [];
                end
                p = obj.printers{iprinter};
                p.createHeadPrinter(d,dh);
                if p.getHasGaussData()
                    h = p.getHeadPrinter();
                    obj.headPrinter = h;
                    return
                else
                    h = p.getHeadPrinter();
                    obj.headPrinter = h;
                end
            end
        end

    end

    methods (Access = private)

        function obtainAllShapes(obj,d)
            obj.obtainCostShapes(d);
            obj.obtainConstraintShapes(d);
        end

        function obtainCostShapes(obj,d)
            nShape = numel(d.cost.shapeFunctions);
            for ishape = 1:nShape
                obj.allShapes{ishape} = d.cost.shapeFunctions{ishape};
            end
        end

        function obtainConstraintShapes(obj,d)
            nShape = numel(d.constraint.shapeFunctions);
            for ishape = 1:nShape
                obj.allShapes{end + ishape} = d.constraint.shapeFunctions{ishape};
            end
        end

        function obtainPrintableIndex(obj)
            aShapes = obj.allShapes;
            nAllShapes = numel(aShapes);
            iprint = 0;
            for ishape = 1:nAllShapes
                shape = aShapes{ishape};
                if obj.isShapePrintable(shape)
                    iprint = iprint + 1;
                    obj.printableIndex(iprint) = ishape;
                end
            end
        end

        function itIs = isShapePrintable(obj,shapeFunc)
            shapeName = class(shapeFunc);
            printingShapes = {'ShFunc_NonSelfAdjoint_Compliance',...
                'ShFunc_Compliance', 'ShFunc_Compliance',...
                'ShFunc_Chomog_alphabeta','ShFunc_Chomog_EnforceCh_CCstar_L2',...
                'ShFunc_Chomog_fraction','ShFunc_Perimeter',...
                'ShFunc_StressNorm','ShFunc_StressNorm2',...
                'ShFunc_StressNorm3'};
            itIs = any(strcmp(printingShapes,shapeName));
        end

    end

end


function [AddedRxnsExtended] = postProcessGapFillSolutions(AddedRxns, model, BlockedRxns, IdentifyPW)
% This function uses the output from `fastGapFill` and signs generalized
% function to the identified solutions from the universal database (e.g.,
% 'Metabolic reaction', 'Transport reaction', 'Exchange reaction'). It also
% provides basic statistics for the solution. One can use the option
% 'IdentifyPW' to compute for each solved blocked reaction a flux vector,
% such that the flux through this reaction is maximized while the sum of
% all fluxes is minimized. This analysis can be helpful to put the solution
% reactions into the network context.
%
% USAGE:
%
%    [AddedRxnsExtended] = postProcessGapFillSolutions(AddedRxns, model, BlockedRxns, IdentifyPW)
%
% INPUTS:
%    AddedRxns:            Output from `fastGapFill.m`
%    model:                Model structure. Original model given as input into `prepareFastGapFill`
%    IdentifyPW:           Optional: identifies reactions that are need from
%                          consistent model and added reactions to have flux through previously
%                          blocked reaction, default: false
%
% OUTPUT:
%    AddedRxnsExtended:    Structure containing the information present in
%                          `AddedRxns` along with the statistics and if desired pathways containing
%                          the flux vectors.
%
% .. Author: - Ines Thiele, June 2013, http://thielelab.eu

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

% postprocess solutions
if length(AddedRxns.rxns) > 0
    [a,b] = strtok(AddedRxns.rxns,'\[');
    b = regexprep(b,'\]r','');
    b = regexprep(b,'\[','');
    Metabolic = 0;
    Transport = 0;
    Exchange = 0;
    for i = 1 : length(b)
        if isempty(char(b(i)))
            AddedRxns.subSystem{i}={'Metabolic reaction'};
            Metabolic = Metabolic + 1;
        elseif strcmp('e]',b(i))
            AddedRxns.subSystem{i}={'Exchange reaction'};
            Exchange = Exchange + 1;
        elseif strcmp('n',b(i))
            AddedRxns.subSystem{i}={'Nucleus <=> cytosol transport'};
            Transport = Transport + 1;
        elseif strcmp('g',b(i))
            AddedRxns.subSystem{i}={'Golgi <=> cytosol transport'};
            Transport = Transport + 1;
        elseif strcmp('m',b(i))
            AddedRxns.subSystem{i}={'Mitochondrion <=> cytosol transport'};
            Transport = Transport + 1;
        elseif strcmp('l',b(i))
            AddedRxns.subSystem{i}={'Lysosome <=> cytosol transport'};
            Transport = Transport + 1;
        elseif strcmp('r',b(i))
            AddedRxns.subSystem{i}={'ER <=> cytosol transport'};
            Transport = Transport + 1;
        elseif strcmp('e',b(i))
            AddedRxns.subSystem{i}={'Extracellular space <=> cytosol transport'};
            Transport = Transport + 1;
        elseif strcmp('x',b(i))
            AddedRxns.subSystem{i}={'Peroxisome <=> cytosol transport'};
            Transport = Transport + 1;
        elseif strcmp('p',b(i))
            AddedRxns.subSystem{i}={'Periplasm <=> cytosol transport'};
            Transport = Transport + 1;
        else
            AddedRxns.subSystem{i}={strcat(b{i},' <=> cytosol transport')};
            Transport = Transport + 1;
        end
    end
    AddedRxns.subSystem = AddedRxns.subSystem';
    AddedRxns.Stats.metabolicSol = Metabolic;
    AddedRxns.Stats.transportSol = Transport;
    AddedRxns.Stats.exchangeSol = Exchange;

    if IdentifyPW
        % model
        modelFilled = model;
        % Index = length(model.rxns)+1;
        % add found solutions to model
        for i = 1 : length(AddedRxns.rxns)
            modelFilled = addReaction(modelFilled,char(AddedRxns.rxns(i)),char(AddedRxns.rxnFormula(i)));
        end

        % find blocked reactions in modelFilled
        Rxns = find(ismember(modelFilled.rxns,BlockedRxns.solvableRxns));

        for i = 1 : length(BlockedRxns.solvableRxns)
            modelFilled.c = zeros(length(modelFilled.c),1);
            % set blocked reaction as objective
            modelFilled.c(Rxns(i)) = 1;
            % perform LP to reconstitute pathway
            % I am using taxi cab (Manhattan norm) as the shortest possible
            % solution
            FBA = optimizeCbModel(modelFilled,'max','one');
            if FBA.f == 0
                % minimize flux through reaction
                % perform LP to reconstitute pathway
                FBA = optimizeCbModel(modelFilled,'min','one');
            end
            % find reactions in FBA solution
            name= modelFilled.rxns{Rxns(i)};
            name = regexprep(name,'\(e\)','');
            name = regexprep(name,'^\d','x');
            if ~isempty(FBA.x)
                FBA.x(FBA.x>=-1e-8&FBA.x<=1e-8)=0;
                if ~isempty(find(FBA.x)~=0)
                    AddedRxns.solvableRxnsSol.(name).solution(:,1) = modelFilled.rxns(FBA.x~=0);
                    AddedRxns.solvableRxnsSol.(name).solution(:,2) = printRxnFormula(modelFilled,AddedRxns.solvableRxnsSol.(name).solution(:,1),false);
                    tmp = FBA.x(FBA.x~=0);
                    for k = 1 : length(tmp)
                        AddedRxns.solvableRxnsSol.(name).solution{k,3}=num2str(tmp(k));
                    end
                    clear tmp
                    % highlight which reaction have not been part of flux consistent
                    % network
                    tmp2 = find(ismember(AddedRxns.solvableRxnsSol.(name).solution(:,1),AddedRxns.rxns));
                    AddedRxns.solvableRxnsSol.(name).solution(tmp2,4)={'added'};
                    clear tmp2
                    tmp2 = find(ismember(AddedRxns.solvableRxnsSol.(name).solution(:,1),BlockedRxns.solvableRxns));
                    AddedRxns.solvableRxnsSol.(name).solution(tmp2,4)={'previously blocked'};

                    clear tmp2
                else
                    AddedRxns.Problem.(name) = BlockedRxns.solvableFormula(i);
                end
            else
                AddedRxns.Problem.(name) = BlockedRxns.solvableFormula(i);
            end
            clear FBA name
        end
    end
    AddedRxnsExtended = AddedRxns;
else
    AddedRxnsExtended = [];
end


function [genes,rxnGeneMat] = getGenesFromGrRules(grRules, originalGenes)
%getGenesFromGrRules  Extract gene list and rxnGeneMat from grRules array.
%
% USAGE:
%
%   [genes,rxnGeneMat] = getGenesFromGrRules(grRules, originalGenes);
%
% INPUTS:
%
%   grRules     A cell array of model grRules, from which a list of genes
%               are to be extracted.
%               NOTE: Boolean operators can be text ("and", "or") or
%                     symbolic ("&", "|"), but there must be a space
%                     between operators and gene names/IDs.
%   originalGenes     The original gene list from the model as reference
%
% OUTPUTS:
%
%   genes       A unique list of all gene IDs that appear in grRules.
%
%   rxnGeneMat  (Optional) A binary matrix indicating which genes
%               participate in each reaction, where rows correspond to
%               reactions (entries in grRules) and columns correspond to
%               genes.
%

% handle input arguments
if nargin < 2
    originalGenes = [];
end

% check if the grRules use written or symbolic boolean operators
if any(contains(grRules,{'&','|'}))
    % fix some potential missing spaces between parentheses and &/|
    grRules = regexprep(grRules,'\)&',') &');   % ")&"  ->  ") &"
    grRules = regexprep(grRules,'&\(','& (');   % "&("  ->  "& ("
    grRules = regexprep(grRules,'\)\|',') |');  % ")|"  ->  ") |"
    grRules = regexprep(grRules,'\|\(','| (');  % "|("  ->  "| ("
else
    % fix some potential missing spaces between parentheses and AND/OR
    grRules = regexprep(grRules,'\)and',') and');  % ")and" ->  ") and"
    grRules = regexprep(grRules,'and\(','and (');  % "and(" ->  "and ("
    grRules = regexprep(grRules,'\)or',') or');    % ")or"  ->  ") or"
    grRules = regexprep(grRules,'or\(','or (');    % "or("  ->  "or ("

    % convert "and" to "&" and "or" to "|" (easier to work with symbols)
    grRules = regexprep(grRules, ' or ', ' | ');
    grRules = regexprep(grRules, ' and ', ' & ');
end

% extract list of genes from each reaction
rxnGenes = cellfun(@(r) unique(regexp(r,'[^&|\(\) ]+','match')),grRules,'UniformOutput',false);

% construct new gene list
nonEmpty = ~cellfun(@isempty,rxnGenes);
genes = unique([rxnGenes{nonEmpty}]');

if ~isempty(originalGenes)
    if ~isequal(sort(originalGenes), sort(genes))
        error('The grRules and original gene list are inconsistent!');
    else
        genes = originalGenes;
    end
end

% construct new rxnGeneMat (if requested)
if nargout > 1
    rxnGeneCell = cellfun(@(rg) ismember(genes,rg),rxnGenes,'UniformOutput',false);
    rxnGeneMat = sparse(double(horzcat(rxnGeneCell{:})'));
end


function [grandavg] = ft_freqgrandaverage(cfg, varargin)

% FT_FREQGRANDAVERAGE computes the average powerspectrum or time-frequency spectrum
% over multiple subjects
%
% Use as
%   [grandavg] = ft_freqgrandaverage(cfg, freq1, freq2, freq3...)
%
% The input data freq1..N are obtained from either FT_FREQANALYSIS with
% keeptrials=no or from FT_FREQDESCRIPTIVES. The configuration structure
% can contain
%   cfg.keepindividual = 'yes' or 'no' (default = 'no')
%   cfg.foilim         = [fmin fmax] or 'all', to specify a subset of frequencies (default = 'all')
%   cfg.toilim         = [tmin tmax] or 'all', to specify a subset of latencies (default = 'all')
%   cfg.channel        = Nx1 cell-array with selection of channels (default = 'all'),
%                        see FT_CHANNELSELECTION for details
%   cfg.parameter      = string or cell-array of strings indicating which
%                        parameter(s) to average. default is set to
%                        'powspctrm', if it is present in the data.
%
% To facilitate data-handling and distributed computing you can use
%   cfg.inputfile   =  ...
%   cfg.outputfile  =  ...
% If you specify one of these (or both) the input data will be read from a *.mat
% file on disk and/or the output data will be written to a *.mat file. These mat
% files should contain only a single variable, corresponding with the
% input/output structure. For this particular function, the input should be
% specified as a cell-array.
%
% See also FT_TIMELOCKGRANDAVERAGE, FT_FREQANALYSIS, FT_FREQDESCRIPTIVES,
% FT_FREQBASELINE

% FIXME averaging coherence is not possible if inputs contain different amounts of data (i.e. chan/freq/time)

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

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

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

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

% check if the input data is valid for this function
for i=1:length(varargin)
  varargin{i} = ft_checkdata(varargin{i}, 'datatype', 'freq', 'feedback', 'no');
end

% check if the input cfg is valid for this function
cfg = ft_checkconfig(cfg, 'forbidden',  {'channels'}); % prevent accidental typos, see issue 1729

% set the defaults
cfg.keepindividual = ft_getopt(cfg, 'keepindividual', 'no');
cfg.channel        = ft_getopt(cfg, 'channel',    'all');
cfg.foilim         = ft_getopt(cfg, 'foilim',     'all');
cfg.toilim         = ft_getopt(cfg, 'toilim',     'all');
cfg.parameter      = ft_getopt(cfg, 'parameter',  []);

if isempty(cfg.parameter) && isfield(varargin{1}, 'powspctrm')
  cfg.parameter = 'powspctrm';
elseif isempty(cfg.parameter)
  ft_error('you should specify a valid parameter to average');
end

if ischar(cfg.parameter)
  cfg.parameter = {cfg.parameter};
end

Nsubj    = length(varargin);
dimord   = varargin{1}.dimord;
hasfreq  = ~isempty(strfind(varargin{i}.dimord, 'freq')); % this should always be true
hastime  = ~isempty(strfind(varargin{i}.dimord, 'time'));
hasrpt   = ~isempty(strfind(varargin{i}.dimord, 'rpt'));
hastap   = ~isempty(strfind(varargin{i}.dimord, 'tap'));

% check whether the input data is suitable
if hasrpt
  ft_error('the input data of each subject should be an average, use FT_FREQDESCRIPTIVES first');
end
if hastap
  ft_error('multiple tapers in the input are not supported');
end

if ischar(cfg.foilim) && strcmp(cfg.foilim, 'all')
  fbeg = -inf;
  fend =  inf;
else
  fbeg = cfg.foilim(1);
  fend = cfg.foilim(2);
end

if ischar(cfg.toilim) && strcmp(cfg.toilim, 'all')
  tbeg = -inf;
  tend =  inf;
else
  tbeg = cfg.toilim(1);
  tend = cfg.toilim(2);
end

% select the data in all inputs
for k=1:numel(cfg.parameter)

  % determine which channels, frequencies and latencies are available for all inputs
  for i=1:Nsubj
    cfg.channel = ft_channelselection(cfg.channel, varargin{i}.label);
    if hasfreq
      fbeg = max(fbeg, varargin{i}.freq(1  ));
      fend = min(fend, varargin{i}.freq(end));
    end
    if hastime
      tbeg = max(tbeg, varargin{i}.time(1  ));
      tend = min(tend, varargin{i}.time(end));
    end
  end
  cfg.foilim = [fbeg fend];
  cfg.toilim = [tbeg tend];

  % pick the selections
  for i=1:Nsubj
    if ~isfield(varargin{i}, cfg.parameter{k})
      ft_error('the field %s is not present in data structure %d', cfg.parameter{k}, i);
    end
    [dum, chansel] = match_str(cfg.channel, varargin{i}.label);
    varargin{i}.label = varargin{i}.label(chansel);

    if hasfreq
      freqsel = nearest(varargin{i}.freq, fbeg):nearest(varargin{i}.freq, fend);
      varargin{i}.freq = varargin{i}.freq(freqsel);
    end
    if hastime
      timesel = nearest(varargin{i}.time, tbeg):nearest(varargin{i}.time, tend);
      varargin{i}.time = varargin{i}.time(timesel);
    end
    % select the overlapping samples in the power spectrum
    switch dimord
      case 'chan_freq'
        varargin{i}.(cfg.parameter{k}) = varargin{i}.(cfg.parameter{k})(chansel,freqsel);
      case 'chan_freq_time'
        varargin{i}.(cfg.parameter{k}) = varargin{i}.(cfg.parameter{k})(chansel,freqsel,timesel);
      case {'rpt_chan_freq' 'rpttap_chan_freq' 'subj_chan_freq'}
        varargin{i}.(cfg.parameter{k}) = varargin{i}.(cfg.parameter{k})(:,chansel,freqsel);
      case {'rpt_chan_freq_time' 'rpttap_chan_freq_time' 'subj_chan_freq_time'}
        varargin{i}.(cfg.parameter{k}) = varargin{i}.(cfg.parameter{k})(:,chansel,freqsel,timesel);
      otherwise
        ft_error('unsupported dimord');
    end
  end % for i = subject
end % for k = parameter

% determine the size of the data to be averaged
dim = cell(1,numel(cfg.parameter));
for k=1:numel(cfg.parameter)
  dim{k} = size(varargin{1}.(cfg.parameter{k}));
end

% give some feedback on the screen
if strcmp(cfg.keepindividual, 'no')
  for k=1:numel(cfg.parameter)
    ft_info('computing average %s over %d subjects\n', cfg.parameter{k}, Nsubj);
  end
else
  for k=1:numel(cfg.parameter)
    ft_info('not computing average, but keeping individual %s for %d subjects\n', cfg.parameter{k}, Nsubj);
  end
end

% allocate memory to hold the data and collect it
for k=1:numel(cfg.parameter)
  if strcmp(cfg.keepindividual, 'no')
    tmp = zeros(dim{k});
    for s=1:Nsubj
      tmp = tmp + varargin{s}.(cfg.parameter{k})./Nsubj; % do a weighted running sum
    end
  elseif strcmp(cfg.keepindividual, 'yes')
    tmp = zeros([Nsubj dim{k}]);
    for s=1:Nsubj
      tmp(s,:,:,:,:) = varargin{s}.(cfg.parameter{k});
    end
  end
  grandavg.(cfg.parameter{k}) = tmp;
end

% collect the output data
grandavg.label = varargin{1}.label;
grandavg.freq  = varargin{1}.freq;
if isfield(varargin{1}, 'time')
  % remember the time axis
  grandavg.time = varargin{1}.time;
end
if isfield(varargin{1}, 'labelcmb')
  grandavg.labelcmb = varargin{1}.labelcmb;
end
if isfield(varargin{1}, 'grad')
  ft_warning('discarding gradiometer information because it cannot be averaged');
end
if isfield(varargin{1}, 'elec')
  ft_warning('discarding electrode information because it cannot be averaged');
end
if strcmp(cfg.keepindividual, 'yes')
  grandavg.dimord = ['subj_',varargin{1}.dimord];
elseif strcmp(cfg.keepindividual, 'no')
  grandavg.dimord = varargin{1}.dimord;
end

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


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Spherical Harmonic Modeling and Analysis Toolkit (SPHARM-MAT) is a 3D
% shape modeling and analysis toolkit.
% It is a software package developed at Shenlab in Center for Neuroimaging,
% Indiana University (SpharmMat@gmail.com, http://www.iupui.edu/~shenlab/)
% It is available to the scientific community as copyright freeware
% under the terms of the GNU General Public Licence.
%
% Copyright 2009, 2010, ShenLab, Center for Neuroimaging, Indiana University
%
% This file is part of SPHARM-MAT.
%
% SPHARM-MAT 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.
%
% SPHARM-MAT 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 SPHARM-MAT. If not, see <http://www.gnu.org/licenses/>.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function confs = loadOptions(inputFile, confs)

fin = fopen(inputFile, 'rt');

for k = 1:length(confs.vars)
    if confs.args(k) < 10
        [numOut, varargout] = Get_Vals(fin, confs.vars{k}, confs.args(k));
        if numOut > 0
            strVar = sprintf('confs.%s=str2num(varargout);', confs.vars{k});
            eval(strVar);
        end
    else
        [numOut, varargout] = Get_Vals(fin, confs.vars{k}, 1);
        if numOut > 0
            strVar = sprintf('confs.%s=strtrim(varargout);', confs.vars{k});
            eval(strVar);
        end
    end
end

fclose(fin);

return;

function [numOut, vals] = Get_Vals(fInput, Keyword, NumVals)

%global userdata;

numOut = 0;
vals = '';

fseek(fInput, 0, 'bof');
delim = ' ,';

while 1
    tline = fgetl(fInput);
    if ~ischar(tline),   break,   end;
    [key, remain] = strtok(tline, delim);
    if strcmpi(strtrim(key), strtrim(Keyword))
        while numOut < NumVals
           if ~isempty(remain)
               numOut = numOut+1;
               vals = remain;
           end
        end
        break;
    end
end

return;


% std_selectdataset() - select datasets and trials for a given independent
%                       variable with a given set of values.
%
% Usage:
%   >> [STUDY] = std_selectdataset(STUDY, ALLEEG, indvar, indvarvals);
%
% Inputs:
%   STUDY       - EELAB STUDY structure
%   ALLEEG      - EELAB dataset structure
%   indvar      - [string] independent variable name
%   indvarvals  - [cell] cell array of string for selected values for the
%   verboseflag - ['verbose'|'silent'] print info flag
%
%                choosen independent variable
% Output:
%   datind       - [integer array] indices of selected dataset
%   dattrialsind - [cell] trial indices for each dataset (not only the
%                  datasets selected above).
%
% Author: Arnaud Delorme, CERCO, 2010-

% Copyright (C) Arnaud Delorme, 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

function [datind, dattrialselect] = std_selectdataset(STUDY, ALLEEG, indvar, indvarvals, verboseFlag);

if nargin < 3
    help std_selectdataset;
    return;
end;
if nargin < 5
    verboseFlag = 'verbose';
end;

% check for multiple condition selection
if ~iscell(indvarvals),
    pos = strfind(' - ', indvarvals);
    if ~isempty(pos)
        tmpindvar = indvarvals;
        indvarvals = { indvarvals(1:pos(1)-1) };
        pos(end+1) = length(tmpindvar)+1;
        for ind = 1:length(pos)-1
            indvarvals{end+1} = tmpindvar(pos(ind)+3:pos(ind+1)-1);
        end;
    else
        indvarvals = { indvarvals };
    end;
end;

% default dattrialselect = all trials
% -----------------------------------
if isfield(STUDY.datasetinfo, 'trialinfo')
     dattrialselect = cellfun(@(x)([1:length(x)]), { STUDY.datasetinfo.trialinfo }, 'uniformoutput', false);
else for i=1:length(ALLEEG), dattrialselect{i} = [1:ALLEEG(i).trials]; end;
end;

if isempty(indvar)
    datind = [1:length(STUDY.datasetinfo)];
elseif isfield(STUDY.datasetinfo, indvar) && ~isempty(getfield(STUDY.datasetinfo(1), indvar))
    % regular selection of dataset in datasetinfo
    % -------------------------------------------
    if strcmpi(verboseFlag, 'verbose'), fprintf('   Selecting datasets with field ''%s'' equal to %s\n', indvar, vararg2str(indvarvals)); end;
    eval( [ 'myfieldvals = { STUDY.datasetinfo.' indvar '};' ] );
    datind = [];
    for dat = 1:length(indvarvals)
        datind = union_bc(datind, std_indvarmatch(indvarvals{dat}, myfieldvals));
    end;
else
    % selection of trials within datasets
    % -----------------------------------
    if strcmpi(verboseFlag, 'verbose'), fprintf('   Selecting trials with field ''%s'' equal to %s\n', indvar, vararg2str(indvarvals)); end;
    dattrials      = cellfun(@(x)(eval(['{ x.' indvar '}'])),  { STUDY.datasetinfo.trialinfo }, 'uniformoutput', false);
    dattrials      = cellfun(@(x)(eval(['{ x.' indvar '}'])),  { STUDY.datasetinfo.trialinfo }, 'uniformoutput', false); % do not remove duplicate line (or Matlab crashes)
    dattrialselect = cell(1,length(STUDY.datasetinfo));
    for dat = 1:length(indvarvals)
        for tmpi = 1:length(dattrials)
            dattrialselect{tmpi} = union_bc(dattrialselect{tmpi}, std_indvarmatch(indvarvals{dat}, dattrials{tmpi}));
        end;
    end;
    datind = find(~cellfun(@isempty, dattrialselect));
end;


function [kept,added]= ...
  setDifferencesScoreFeatures(scoreFeaturesOld,scoreFeaturesNew)
% Given an old and new scoreFeatures, computes a boolean array that tells
% which elements of the old one are retained in the new one (kept), and a
% boolean array indicating which elements of the new one are not present in
% the old one (added).

% Get the list of (absolute) files names for each scoreFeatures array
fileNameListOld={scoreFeaturesOld(:).classifierfile};
fileNameListNew={scoreFeaturesNew(:).classifierfile};

% define a local function that checks whether a file name is in the new file
% name list
inFileNameListNew=@(fileName)(ismember(fileName,fileNameListNew));

% mark the ones in the old list that are not in the new list (these are
% ones that will be deleted)
kept=cellfun(inFileNameListNew,fileNameListOld);

% define a local function that checks whether a file name is in the old file
% name list
notInFileNameListOld=@(fileName)(~ismember(fileName,fileNameListOld));

% mark the ones in the new list that were not in the old list (added
% ones)
added=cellfun(notInFileNameListOld,fileNameListNew);

end


function [dat] = read_plexon_ddt(filename, begsample, endsample)

% READ_PLEXON_DDT reads header or data from a Plexon *.ddt file,
% which is a Plexon continuous data file optimized for continuous
% (streaming) recording where every channel is continuously recorded
% without gaps and the recording includes any dead time between spikes.
%
% Use as
%   [hdr] = read_plexon_ddt(filename)
%   [dat] = read_plexon_ddt(filename, begsample, endsample)
%
% samples start counting at 1
% returned values are in mV

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

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Version 100: Samples are assumed to be 12 bits.  All channels have the same NIDAQ gain, and preamp
% gain is not saved.
%     int     Version;         // =100
%     int     DataOffset;      // Offset into the file where the data starts
%     double  Freq;            // Digitization frequency
%     int     NChannels;       // Number of channels
%     int     Year;            // Time/date when the data was acquired
%     int     Month;
%     int     Day;
%     int     Hour;
%     int     Minute;
%     int     Second;
%     int     Gain;            // NIDAQ gain (the same gain for all channels
%     char    Comment[128];    // User-supplied comment
%     unsigned char Padding[256];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

dat = [];
fid = fopen(filename, 'rb', 'ieee-le');

Version    = fread(fid, 1, 'int'    );
dat.Version    = Version;

% this is common for all subformats
dat.DataOffset = fread(fid, 1, 'int'    );
dat.Freq       = fread(fid, 1, 'double' );
dat.NChannels  = fread(fid, 1, 'int'    );
dat.Year       = fread(fid, 1, 'int'    );
dat.Month      = fread(fid, 1, 'int'    );
dat.Day        = fread(fid, 1, 'int'    );
dat.Hour       = fread(fid, 1, 'int'    );
dat.Minute     = fread(fid, 1, 'int'    );
dat.Second     = fread(fid, 1, 'int'    );
dat.Gain       = fread(fid, 1, 'int'    );
dat.Comment        = char(fread(fid, 128, 'char')');

if Version==100
  % the remainder of the header contains bytes for padding
  dat.Padding    = fread(fid, 256, 'char' );
elseif Version==101
  % Version 101: A field was added to indicate bits-per-sample (12 or 16).  All channels have the same NIDAQ
  % gain, and preamp gain is not saved.
  dat.BitsPerSample = fread(fid,   1, 'char');
  dat.Padding       = fread(fid, 255, 'char');
elseif Version==102
  % Version 102: A byte array of per-channel NIDAQ gains was added.  The Gain field now indicates the
  % preamp gain,   a value of 1 usually indicating that no preamp gain was specified in the application that
  % recorded the DDT.
  dat.BitsPerSample = fread(fid,   1, 'char');
  dat.ChannelGain   = fread(fid,  64, 'char');
  dat.Padding       = fread(fid, 191, 'char');
elseif Version==103
  % Version 103: A field was added to specify ADC maximal input voltage. The value is integer number in
  % millivolts.
  dat.BitsPerSample  = fread(fid,   1, 'char');
  dat.ChannelGain    = fread(fid,  64, 'char');
  dat.MaxMagnitudeMV = fread(fid,   1, 'short');
  dat.Padding        = fread(fid, 189, 'char');
else
  error('unsupported version of ddt file');
end

% determine the number of samples by looking at the length of the datafile
offset = ftell(fid);
fseek(fid, 0, 'eof');
dat.NSamples = (ftell(fid) - offset) / (2 * dat.NChannels);

if nargin==1
  % do not read any data, only return the header
  fclose(fid);
  return
end

% A DDT file contains a file header followed by an array of A/D samples stored as 16-bit integers regardless
% of whether values are 12 or 16-bits. The samples are multiplexed.

% read the desired samples of the data
offset = dat.DataOffset + (begsample-1)*dat.NChannels;
nsampl = endsample - begsample + 1;
fseek(fid, offset, 'bof');
dat.data = fread(fid, [dat.NChannels nsampl], 'int16');

fclose(fid);

% apply the calibration to obtain the signal in physical units
if Version==100
  PreAmpGain = 1000;
  dat.data = dat.data * 5000 / (2048 * dat.Gain * PreAmpGain);
elseif Version==101
  PreAmpGain = 1000;
  dat.data = dat.data * 5000 / (0.5 * (2^dat.BitsPerSample) * dat.Gain * PreAmpGain);
elseif Version==102
  for i=1:dat.NChannels
    dat.data(i,:) = dat.data(i,:) * 5000 ./ (0.5 * (2^dat.BitsPerSample) * dat.ChannelGain(i));
  end
elseif Version==103
  % I am not sure whether the calibration like this is correct, since the
  % Plexon documentation does not explicitely specify how to do it for the
  % 104 file format. I presume that it is identical to the 103 format.
  for i=1:dat.NChannels
    dat.data(i,:) = dat.data(i,:) * 5000 ./ (0.5 * (2^dat.BitsPerSample) * dat.ChannelGain(i));
  end
end