function InitializeAppData(hfig)
%% Import paths

data_masterdir = GetCurrentDataDir();%'C:\Janelia2014'; %[pwd '\example data']; % 'F:\Janelia2014';%
save_dir = GetOutputDataDir();

global VAR; %#ok<NUSED>
load(fullfile(save_dir,'VAR_new.mat'),'VAR'); % stores all clustering indices

name_MASKs = 'MaskDatabase.mat';
name_ReferenceBrain = 'ReferenceBrain.mat';

setappdata(hfig,'data_masterdir',data_masterdir);% directory for full fish data (.mat)
setappdata(hfig,'save_dir',save_dir);% directory for full fish data (.mat)

%% load ZBrain Atlas
if exist(fullfile(data_masterdir,name_MASKs),'file') ...
        && exist(fullfile(data_masterdir,name_ReferenceBrain),'file'),

    % load masks for ZBrain Atlas
    MASKs = load(fullfile(data_masterdir,name_MASKs));
    setappdata(hfig,'MASKs',MASKs);
    % load reference brain image stack with the 3 projections
    load(fullfile(data_masterdir,name_ReferenceBrain));
    setappdata(hfig,'anat_stack_norm',anat_stack_norm);
    setappdata(hfig,'anat_yx_norm',anat_yx_norm);
    setappdata(hfig,'anat_yz_norm',anat_yz_norm);
    setappdata(hfig,'anat_zx_norm',anat_zx_norm);

    FishOutline = load(fullfile(data_masterdir,'FishOutline.mat'));
    setappdata(hfig,'FishOutline',FishOutline);
end

%% preload
% fish protocol sets (different sets have different parameters)
M_fish_set = GetFishStimset(); % M = Matrix
setappdata(hfig,'M_fish_set',M_fish_set);

% constant
setappdata(hfig,'z_res',19.7); % resoltion in z, um per slice

%% load target fish
% need to reload fish if changed
setappdata(hfig,'i_fish',0);
setappdata(hfig,'isFullData',1);

%% display params
% for general display
setappdata(hfig,'isPopout',1);
setappdata(hfig,'isPlotAnatomyOnly',0);
setappdata(hfig,'clrmap_name','hsv_new');

% for functional display: need to UpdateTimeIndex if changed
setappdata(hfig,'isStimAvr',1); % show average/full stimulus
setappdata(hfig,'isRawtime',0); % show stimulus in original order or sorted
setappdata(hfig,'isZscore',1); % show normalized (z-score) version of fluorescent
setappdata(hfig,'isTrialRes',0); % show trial residuals (subtracting trial average) of fluorescent
% % temp:
setappdata(hfig,'isClusRes',0);

% for functional display: display only
setappdata(hfig,'isCentroid',0);
setappdata(hfig,'isPlotLines',0);
setappdata(hfig,'isPlotBehavior',1);
setappdata(hfig,'isPlotRegWithTS',0);
setappdata(hfig,'rankscore',[]); %
setappdata(hfig,'rankID',0); % whether to plot scores or not, toggled away

% for anat display:
setappdata(hfig,'isRefAnat',0);
setappdata(hfig,'isShowFishOutline',0);
setappdata(hfig,'isShowMasks',1);
setappdata(hfig,'isShowMskOutline',0);
setappdata(hfig,'isWeighAlpha',0); % for regression plots, toggled away

%% for behavior / motor regression:
setappdata(hfig,'isMotorseed',1);

%% all below: associated with specialized functions
% set operations
setappdata(hfig,'opID',0);

% regression
thres_merge = 0.9;
thres_split = 0.7;
thres_reg = 0.7;
thres_size = 10;
thres_ttest = 0.001;
setappdata(hfig,'thres_merge',thres_merge);
setappdata(hfig,'thres_split',thres_split); % for function 'pushbutton_iter_split'
setappdata(hfig,'thres_reg',thres_reg); % regression threshold, ~correlation coeff
setappdata(hfig,'thres_size',thres_size); % min size for clusters

setappdata(hfig,'thres_ttest',thres_ttest); % min size for clusters

setappdata(hfig,'regchoice',{1,1}); % regressor choice; first cell,1=stim,2=motor,3=centroid
setappdata(hfig,'isPlotReg',1); % plot regressor when selecting it
setappdata(hfig,'isPlotCorrHist',0); % option for regression

setappdata(hfig,'isRegIndividualCells',1);
setappdata(hfig,'isRegCurrentCells',1);

setappdata(hfig,'isAutoclusWithAllCells',1);

% clustering
setappdata(hfig,'isWkmeans',1); % in autoclustering, with/without kmeans
setappdata(hfig,'hierinplace',1); % hier. partitioning, no reordering
setappdata(hfig,'isCorrplotWeighted',0);

% Atlas
setappdata(hfig,'isFindMaskNorm',1);
setappdata(hfig,'isPlotMskHist',1);
setappdata(hfig,'isScreenMskFromAllCells',0);

% GUI interface helpers
setappdata(hfig,'clusgroupID_view',1);
setappdata(hfig,'clusID_view',0); % set in UpdateClusGroupGUI, 0 for placeholder '(choose)'

end


function missingStereo = checkForMissingStereo(model, trainingModel)
% USAGE:
%
%    missingStereo = checkForMissingStereo(model, trainingModel)
%
% INPUTS:
%    model:    structure with fields:
%
%                * .mets
%                * .inchi.standard
%                * .inchi.standardWithStereo
%
%    trainingModel:     structure with fields:
%
%                *.inchi.standard
%                *.inchi.standardWithStereo
%
% OUTPUTS:
%    missingStereo:

nistStdBool = false(length(trainingModel.inchi.standard));
for n = 1:length(trainingModel.inchi.standard)
   if ~isempty(trainingModel.inchi.standard{n})
       if ~any(nistStdBool(:,n))
           nistStdBool(n,n) = true;
           nistStdBool(n,strcmp(trainingModel.inchi.standard{n},trainingModel.inchi.standard)) = true;
       end
   end
end

nistStdStereoBool = false(length(trainingModel.inchi.standardWithStereo));
for n = 1:length(trainingModel.inchi.standardWithStereo)
   if ~isempty(trainingModel.inchi.standardWithStereo{n})
       if ~any(nistStdStereoBool(:,n))
           nistStdStereoBool(n,n) = true;
           nistStdStereoBool(n,strcmp(trainingModel.inchi.standardWithStereo{n},trainingModel.inchi.standardWithStereo)) = true;
       end
   end
end

nistStdStereoBool(diag(true(size(nistStdStereoBool,1),1))) = false;
nistBool = nistStdBool & ~nistStdStereoBool;
nistBool = nistBool(sum(nistBool,2)>1,:);

nistStdInchi = trainingModel.inchi.standard(any(nistBool));
modelStdInchi = model.inchi.standard;
modelStdInchi(cellfun(@isempty,modelStdInchi)) = {'N/A'};

modelStdInchiStereo = model.inchi.standardWithStereo(ismember(modelStdInchi,nistStdInchi));
modelMets = model.mets(ismember(modelStdInchi,nistStdInchi));
modelMets = regexprep(modelMets,'\[\w\]','');
[modelMets,crossi] = unique(modelMets);
modelStdInchiStereo = modelStdInchiStereo(crossi);
missingStereo = modelMets(cellfun('isempty',regexp(modelStdInchiStereo,'[tms]')));

end


function run_writelsl(varargin)
% Provide real-time BCI outputs to the lab streaming layer.
% run_writetcp(Model,SourceStream)
%
% This function runs in the background and processes data from some MATLAB stream (created with some
% other background input plugin, e.g., the BioSemi reader). The resulting estimates are offered to
% the lab streaming layer for use by other programs.
%
% In:
%   Model : A model data structure (as obtained from bci_train) based on which the predictor shall be
%           created; typically this is a model struct, but for convenience it can be a file name,
%           variable name in the base workspace, or a cell array of {file name, variable name} to
%           refer to a variable inside a .mat file. The model is not modified by this function.
%           (default: 'lastmodel')
%
%   SourceStreamNames : Optional names of stream data structures in the MATLAB base workspace to
%                       consider as possible data sources (previously created with onl_newstream);
%                       if a stream contains all channels that are needed by the predictor, or
%                       alternatively has the right number and type of channels it will be considered
%                       as a potential source stream unless ambiguous. (default: 'laststream')
%
%   LabStreamName : Name of the output stream in the lab streaming layer (default: 'BCI')
%
%   ChannelNames : labels for each output channel (if this is for classification and the output form
%                  is set to distribution, the channels correspond to the labels of the respective classes
%                  (default: {'class1','class2', ..., 'classN'} depending on the # of classes)
%
%   OutputForm : Output data form, see onl_predict (default: 'distribution')
%
%   UpdateFrequency : The rate at which new outputs will be computed. (default: 10)
%
%   PredictAt : Predict at markers. If nonempty, this is a cell array of online target markers relative
%               to which predictions shall be made. If empty, predictions are always made on the most
%               recently added sample. (default: {})
%
%   Verbose : Verbose output. If false, the console output of the online pipeline will be suppressed.
%             (default: false)
%
%   PredictorName : Name of the predictor to be created; a variable of this name will be created in
%                   the MATLAB base workspace to hold the predictor's state. If a variable with this
%                   name already exists it will be overridden. (default: 'lastpredictor')
%
% Examples:
%   % open a new BCILAB processing stream, using the previously learned predictive model 'mymodel',
%   % and reading from a previously opened input stream named 'mystream'. Name the stream 'BCI' and
%   % name the channels according to the classes whose probabilities they carry (here for some hypothetical
%   % error perception classifier)
%   run_writelsl('mymodel','mystream','BCI',{'error','no_error'})
%
%   % as before, but pass arguments by name
%   run_writelsl('Model','mymodel','SourceStream','mystream','ChannelNames',{'error','no_error'})
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2012-03-21

persistent lib;

% declare the name of this component (shown in the menu)
declare_properties('name','Lab streaming layer');

% define arguments
opts = arg_define(varargin, ...
    arg({'pred_model','Model'}, 'lastmodel', [], 'Predictive model. As obtained via bci_train or the Model Calibration dialog.','type','expression'), ...
    arg({'in_stream','SourceStreamNames','SourceStream'}, 'laststream',[],'Input Matlab stream name(s). Optional names of stream data structures in the MATLAB base workspace to consider as possible data sources (previously created with onl_newstream); if a stream contains all channels that are needed by the predictor, or alternatively has the right number and type of channels it will be considered as a potential source stream unless ambiguous.','typecheck',false,'shapecheck',false), ...
    arg({'out_stream','LabStreamName','Target'},'bci',[],'Name of the lab stream. This is the name under which the stream is provided to the lab streaming layer.'), ...
    arg({'channel_names','ChannelNames'},{'class1','class2'},[],'Output channel labels. These are the labels of the stream''s channels. In a typical classification setting each channel carries the probability for one of the possible classes.'), ...
    arg({'out_form','OutputForm','Form'},'expectation',{'expectation','distribution','mode','raw'},'Output form. Can be the expected value (posterior mean) of the target variable, or the distribution over possible target values (probabilities for each outcome, or parametric distribution), or the mode (most likely value) of the target variable.'), ...
    arg({'update_freq','UpdateFrequency'},10,[0 Inf],'Update frequency. The rate at which new outputs will be computed.'), ...
    arg({'predict_at','PredictAt'}, {},[],'Predict at markers. If nonempty, this is a cell array of online target markers relative to which predictions shall be made. If empty, predictions are always made on the most recently added sample.','type','expression'), ...
    arg({'verbose','Verbose'}, false,[],'Verbose output. If false, the console output of the online pipeline will be suppressed.'), ...
    arg({'source_id','SourceID'}, 'input_data',{'input_data','model'},'Use as source ID. This is the data that determines the source ID of the stream (if the stream is restarted, readers will continue reading from it if it has the same source ID). Can be input_data (use a hash of dataset ID + target markers used for training) or model (use all model parameters).'), ...
    arg({'pred_name','PredictorName'}, 'lastpredictor',[],'Name of new predictor. A variable of this name will be created in the MATLAB base workspace to hold the predictor''s state. If a variable with this name already exists it will be overridden.'));

% load the model
model = utl_loadmodel(opts.pred_model);

% check if channel labels make sense for the model
if strcmp(opts.out_form,'distribution')
    if isfield(model,'classes') && ~isempty(model.classes)
        if length(opts.channel_names) ~= length(model.classes)
            disp('The number of classes provided by the model does not match the number of provided channel names; falling back to default names.');
            opts.channel_names = cellfun(@(k)['class' num2str(k)],num2cell(1:length(model.classes),1),'UniformOutput',false);
        end
    end
else
    if isfield(model,'classes') && ~isempty(model.classes)
        if length(opts.channel_names) ~= 1
            disp('A classification model will produce just one channel if the output is not in distribution form, but a different number of channels was given. Falling back to the default channel label.');
            opts.channel_names = {'class'};
        end
    end
end

% try to calculate a UID for the stream
try
    if strcmp(opts.source_id,'model')
        uid = hlp_cryptohash({rmfield(model,'timestamp'),opts.predict_at,opts.in_stream,opts.out_stream});
    elseif strcmp(opts.source_id,'input_data')
        uid = hlp_cryptohash({model.source_data,opts.predict_at,opts.in_stream,opts.out_stream});
    else
        error('Unsupported SourceID option: %s',hlp_tostring(opts.source_id));
    end
catch e
    disp('Could not generate a unique ID for the predictive model; the BCI stream will not be recovered automatically after the provider system had a crash.');
    hlp_handleerror(e);
    uid = '';
end

% instantiate the library
disp('Opening the library...');
if isempty(lib)
    lib = lsl_loadlib(env_translatepath('dependencies:/liblsl-Matlab/bin')); end

% describe the stream
disp('Creating a new streaminfo...');
info = lsl_streaminfo(lib,opts.out_stream,'MentalState',length(opts.channel_names),opts.update_freq,'cf_float32',uid);
% ... including some meta-data
desc = info.desc();
channels = desc.append_child('channels');
for c=1:length(opts.channel_names)
    newchn = channels.append_child('channel');
    newchn.append_child_value('name',opts.channel_names{c});
    newchn.append_child_value('type',opts.out_form);
end

% create an outlet
outlet = lsl_outlet(info);

% start background writer job
onl_write_background( ...
    'ResultWriter',@(y)send_samples(outlet,y),...
    'MatlabStream',opts.in_stream, ...
    'Model',opts.pred_model, ...
    'OutputFormat',opts.out_form, ...
    'UpdateFrequency',opts.update_freq, ...
    'PredictorName',opts.pred_name, ...
    'PredictAt',opts.predict_at, ...
    'Verbose',opts.verbose, ...
    'StartDelay',0,...
    'EmptyResultValue',[]);

disp('Now writing...');

function send_samples(outlet,y)
if ~isempty(y)
    outlet.push_chunk(y'); end


function y = callback_doubleoperator(x,dir,options)

% callback_doubleoperator - apply two calbacks
%
%   y = callback_doubleoperator(x,dir,options);
%
%   Copyright (c) 2008 Gabriel Peyre

c1 = getoptions(options, 'callback1', 0, 1);
c2 = getoptions(options, 'callback2', 0, 1);

if dir==1
    y = feval(c1, x, dir, options);
    y = feval(c2, y, dir, options);
else
    y = feval(c2, x, dir, options);
    y = feval(c1, y, dir, options);
end


%-----------------------------------------------------------------------
% Job configuration created by cfg_util (rev $Rev: 3355 $)
%-----------------------------------------------------------------------
matlabbatch{1}.cfg_toy{1}.add2{1}.cfg_example_add1.a = '<UNDEFINED>';
matlabbatch{1}.cfg_toy{1}.add2{1}.cfg_example_add1.b = '<UNDEFINED>';
matlabbatch{2}.cfg_toy{1}.cfg_example_div.a = '<UNDEFINED>';
matlabbatch{2}.cfg_toy{1}.cfg_example_div.b(1) = cfg_dep;
matlabbatch{2}.cfg_toy{1}.cfg_example_div.b(1).tname = 'Input b';
matlabbatch{2}.cfg_toy{1}.cfg_example_div.b(1).tgt_spec = {};
matlabbatch{2}.cfg_toy{1}.cfg_example_div.b(1).sname = 'Add1: Add1: a + b';
matlabbatch{2}.cfg_toy{1}.cfg_example_div.b(1).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1});
matlabbatch{2}.cfg_toy{1}.cfg_example_div.b(1).src_output = substruct('()',{1});
matlabbatch{3}.cfg_basicio.cfg_assignin.name = 'div_sum_ab_c';
matlabbatch{3}.cfg_basicio.cfg_assignin.output(1) = cfg_dep;
matlabbatch{3}.cfg_basicio.cfg_assignin.output(1).tname = 'Output Item';
matlabbatch{3}.cfg_basicio.cfg_assignin.output(1).tgt_spec = {};
matlabbatch{3}.cfg_basicio.cfg_assignin.output(1).sname = 'div: a div b: mod';
matlabbatch{3}.cfg_basicio.cfg_assignin.output(1).src_exbranch = substruct('.','val', '{}',{2}, '.','val', '{}',{1});
matlabbatch{3}.cfg_basicio.cfg_assignin.output(1).src_output = substruct('.','mod');


% Calculates DNA-bound protein displacements
%
% Author: Jonathan Karr, jkarr@stanford.edu
% Affilitation: Covert Lab, Department of Bioengineering, Stanford University
% Last updated: 4/6/2012
function runDisplacementCalculation(simBatch, simIdx, outDir)
setWarnings;
setPath;

%import classes
import edu.stanford.covert.cell.sim.analysis.Figures34;
import edu.stanford.covert.cell.sim.util.SimulationDiskUtil;

%parse inputs
if ischar(simIdx)
	simIdx = str2num(simIdx);
end

%run calculation
simBatchDir = [SimulationDiskUtil.getBaseDir() filesep simBatch filesep];
Figures34.calculateDNABoundProteinDisplacements(outDir, simBatchDir, simIdx, 1, 1);


function s4_resave_annot_after_temporal()
%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('tdata.mat')
% merged_annot = struct();
load('merged_annot');
load('checkpoint_improved.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;

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

    merged_annot(v).num_imgs = num_imgs;
    merged_annot(v).name = base_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;
        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_temporal.mat','isgood','inputs','v');
save('merged_annot_temporal.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


% MatrixUser, a multi-dimensional matrix analysis software package
% https://sourceforge.net/projects/matrixuser/
%
% The MatrixUser is a matrix analysis software package developed under Matlab
% Graphical User Interface Developing Environment (GUIDE). It features
% functions that are designed and optimized for working with multi-dimensional
% matrix under Matlab. These functions typically includes functions for
% multi-dimensional matrix display, matrix (image stack) analysis and matrix
% processing.
%
% Author:
%   Fang Liu <leoliuf@gmail.com>
%   University of Wisconsin-Madison
%   Aug-30-2014

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

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

% Last Modified by GUIDE v2.5 22-Sep-2013 01:30:53

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

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

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

handles.main_h=varargin{1};
set(handles.Seg_uitable,'Data',handles.main_h.V.Segs(:,1:3));

set(handles.Edit_pushbutton,'Enable','off');
set(handles.Update_pushbutton,'Enable','off');

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

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes MU_Seg_Edit wait for user response (see UIRESUME)
% uiwait(handles.MU_seg_edit_figure);

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

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

% --- Executes on button press in Edit_pushbutton.
function Edit_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to Edit_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.main_h=guidata(handles.main_h.MU_matrix_display);
if handles.main_h.V.Segs{handles.SegInd,2}~=handles.main_h.V.Slice
    return;
end

set(handles.Update_pushbutton,'Enable','on');
set(handles.Edit_pushbutton,'Enable','off');
MU_enable('off',[],handles.main_h);
handles.main_h=guidata(handles.main_h.MU_matrix_display);

eval(['handles.ROI_h=' handles.main_h.V.Segs{handles.SegInd,1} '(handles.main_h.Matrix_display_axes,handles.main_h.V.Segs{handles.SegInd,4});']);
Temp=handles.main_h.Mask(:,:,handles.main_h.V.Slice);
BW=createMask(handles.ROI_h);
Temp(BW~=0)=0;
handles.main_h.Mask(:,:,handles.main_h.V.Slice)=Temp;

guidata(hObject, handles);
guidata(handles.main_h.MU_matrix_display,handles.main_h);

% --- Executes on button press in Update_pushbutton.
function Update_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to Update_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.main_h=guidata(handles.main_h.MU_matrix_display);
if handles.main_h.V.Segs{handles.SegInd,2}~=handles.main_h.V.Slice
    return;
end

set(handles.Update_pushbutton,'Enable','off');
MU_enable('on',[],handles.main_h);
handles.main_h=guidata(handles.main_h.MU_matrix_display);

Data=get(handles.Seg_uitable,'Data');

%deselect uitable ?? dirty code
set(handles.Seg_uitable, 'Data', []);
set(handles.Seg_uitable, 'Data', Data);

Temp=handles.main_h.Mask(:,:,handles.main_h.V.Slice);
BW=createMask(handles.ROI_h);
handles.main_h.V.Segs{handles.SegInd,3}=max(0,Data{handles.SegInd,3});
handles.main_h.V.Segs{handles.SegInd,4}=getPosition(handles.ROI_h);
Temp(BW~=0)=max(0,Data{handles.SegInd,3});

handles.main_h.Mask(:,:,handles.main_h.V.Slice)=Temp;
handles.main_h=MU_update_image(handles.main_h.Matrix_display_axes,{handles.main_h.TMatrix,handles.main_h.Mask},handles.main_h,0);
guidata(hObject, handles);
guidata(handles.main_h.MU_matrix_display,handles.main_h);

% --- Executes when entered data in editable cell(s) in Seg_uitable.
function Seg_uitable_CellEditCallback(hObject, eventdata, handles)
% hObject    handle to Seg_uitable (see GCBO)
% eventdata  structure with the following fields (see UITABLE)
%	Indices: row and column indices of the cell(s) edited
%	PreviousData: previous data for the cell(s) edited
%	EditData: string(s) entered by the user
%	NewData: EditData or its converted form set on the Data property. Empty if Data was not changed
%	Error: error string when failed to convert EditData to appropriate value for Data
% handles    structure with handles and user data (see GUIDATA)

% --- Executes when selected cell(s) is changed in Seg_uitable.
function Seg_uitable_CellSelectionCallback(hObject, eventdata, handles)
% hObject    handle to Seg_uitable (see GCBO)
% eventdata  structure with the following fields (see UITABLE)
% Indices: row and column indices of the cell(s) currently selecteds
% handles    structure with handles and user data (see GUIDATA)
if isempty(eventdata.Indices)
    return;
end

handles.main_h=guidata(handles.main_h.MU_matrix_display);
handles.SegInd=eventdata.Indices(1);
if handles.main_h.V.Segs{handles.SegInd,2}~=handles.main_h.V.Slice
    guidata(hObject, handles);
    return;
end

if eventdata.Indices(2)==1
    Pos=handles.main_h.V.Segs{handles.SegInd,4};
    axes(handles.main_h.Matrix_display_axes);
    text(Pos(1,1),Pos(1,2),num2str(handles.SegInd),'Color','r','FontSize',18);
end

if strcmp(get(handles.Update_pushbutton,'Enable'),'off')
    set(handles.Edit_pushbutton,'Enable','on');
end

guidata(hObject, handles);

% --- Executes on mouse motion over figure - except title and menu.
function MU_seg_edit_figure_WindowButtonMotionFcn(hObject, eventdata, handles)
% hObject    handle to MU_seg_edit_figure (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
if ~ishandle(handles.main_h.MU_matrix_display);
    close(hObject);
    return;
end

handles.main_h=guidata(handles.main_h.MU_matrix_display);
Data=get(handles.Seg_uitable,'Data');
if length(handles.main_h.V.Segs(:,3)) > length(Data(:,3))
    Data(end+1,3)={1};
end
set(handles.Seg_uitable,'Data',[handles.main_h.V.Segs(:,1:2) Data(:,3)]);
guidata(hObject, handles);


%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% /**
%  * Copyright (C) 2016 CoDyCo
%  * @author: Daniele Pucci, Gabriele Nava
%  * Permission is granted to copy, distribute, and/or modify this program
%  * under the terms of the GNU General Public License, version 2 or any
%  * later version published by the Free Software Foundation.
%  *
%  * A copy of the license can be found at
%  * http://www.robotcub.org/icub/license/gpl.txt
%  *
%  * 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
%  */
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% NOTE: THIS SCRIPT IS RUN AUTOMATICALLY WHEN THE USER STARTS THE ASSOCIATED
% SIMULINK MODEL. NO NEED TO RUN THIS SCRIPT EVERY TIME.
clearvars -except sl_synch_handles simulinkStaticGUI
clc

% Add path to local source code
addpath('./src/')

%% GENERAL SIMULATION INFO
%
% If you are simulating the robot with Gazebo, remember that it is required
% to launch Gazebo as follows:
%
%     gazebo -slibgazebo_yarp_clock.so
%
% and properly set the environmental variable YARP_ROBOT_NAME in the .bashrc.

% Simulation time in seconds. For long simulations, put an high number
% (not inf) for allowing automatic code generation
Config.SIMULATION_TIME = 70;

% Controller period [s]
Config.tStep           = 0.01;

%% PRELIMINARY CONFIGURATION
%
% DEMO_TYPE: defines the kind of demo that will be performed.
%
% 'YOGA': the robot will perform the YOGA++ demo (highly dynamic movements
%         while balancing on one foot and two feet)
%
% 'COORDINATOR': the robot can either balance on two feet or move from left
%                to right follwing a desired center-of-mass trajectory.
%
DEMO_TYPE                     = 'YOGA';

% Config.SCOPES: debugging scopes activation
Config.SCOPES_WRENCHES        = true;
Config.SCOPES_GAIN_SCHE_INFO  = true;
Config.SCOPES_MAIN            = true;
Config.SCOPES_QP              = true;

% DATA PROCESSING
%
% Save the Matlab workspace after stopping the simulation
Config.SAVE_WORKSPACE         = false;

% Verify that the integration time has been respected during the simulation
Config.CHECK_INTEGRATION_TIME = true;
Config.PLOT_INTEGRATION_TIME  = false;

% Run robot-specific configuration parameters
run(strcat('app/robots/',getenv('YARP_ROBOT_NAME'),'/configRobot.m'));
run(strcat('app/robots/',getenv('YARP_ROBOT_NAME'),'/configStateMachine.m'));
run(strcat('app/robots/',getenv('YARP_ROBOT_NAME'),'/gainsAndReferences.m'));

% Deactivate/activate the internal coordinator
if strcmpi(DEMO_TYPE, 'COORDINATOR')

    Config.COORDINATOR_DEMO = true;

elseif strcmpi(DEMO_TYPE, 'YOGA')

    Config.COORDINATOR_DEMO = false;
end


% --------- DeepMIMO: A Generic Dataset for mmWave and massive MIMO ------%
% Authors: Ahmed Alkhateeb, Umut Demirhan, Abdelrahman Taha
% Date: March 17, 2022
% Goal: Encouraging research on ML/DL for MIMO applications and
% providing a benchmarking tool for the developed algorithms
% ---------------------------------------------------------------------- %

function params = read_params(filename)
    run(filename)
end


function initializeDateListBox( dates, hdls )
%INITIALIZEDATELISTBOX Initialize date list box:
%   dateListBox: a list of dates in format yyyymmdd for the user to select
%   generateDataButton: a button to generate data
%   forward/backward buttons: buttons to move forward/backward in time
%   Detailed explanation goes here

% Create list box for choosing date to display eddies
date_list = arrayfun(@num2str, dates, 'UniformOutput', false);

dateListBox = uicontrol(hdls.fig, ...
    'Style', 'listbox', ...
    'Units', 'normalized', ...
    'String', date_list, ...
    'Position', [0.875 .6 .1 .4], ...
    'Callback', {@dateListBoxCallback, hdls});

% Forward button
uicontrol(hdls.fig, ...
    'Style', 'pushbutton', ...
    'Units', 'normalized', ...
    'String', 'Forward', ...
    'Callback', {@forward_button_Callback, dateListBox, hdls}, ...
    'position', [0.925 0.33 .05 .05]);

% backward button
uicontrol(hdls.fig, ...
    'Style', 'pushbutton', ...
    'Units', 'normalized', ...
    'String', 'Backward', ...
    'Callback', {@backward_button_Callback, dateListBox, hdls}, ...
    'position', [0.875 0.33 .05 .05]);

hdls.eddyInfoText = uicontrol(hdls.fig, ...
    'Style', 'text', ...
    'Units', 'normalized', ...
    'String', 'Eddy Information', ...
    'position', [0.875 0 0.1 .3]);
end

function dateListBoxCallback(hObject, ~, hdls)

old_pointer = start_busy_pointer(hdls);

hdls.currentDateIndex = get(hObject, 'Value');
hdls.generate_data();

end_busy_pointer(hdls, old_pointer);

end

function forward_button_Callback(~, ~, dateListBox, hdls)

old_pointer = start_busy_pointer(hdls);

curr_date_index = get(dateListBox, 'Value');
if(curr_date_index == length(get(dateListBox, 'String')))
    return;
end
set(dateListBox, 'Value', curr_date_index + 1);
hdls.currentDateIndex = hdls.currentDateIndex + 1;
hdls.generate_data();

end_busy_pointer(hdls, old_pointer);

end

function backward_button_Callback(~, ~, dateListBox, hdls)

old_pointer = start_busy_pointer(hdls);

if hdls.currentDateIndex == 1
    return;
end
hdls.currentDateIndex = hdls.currentDateIndex - 1;
set(dateListBox, 'Value', hdls.currentDateIndex);
hdls.generate_data();

end_busy_pointer(hdls, old_pointer);

end


function mv = mv_glmPanel(mv)
%
% Attach a uipanel to a MultiVoxelUI with controls for visualizing
% GLMs. This initializes the panel to 'off', not visible. The panel is
% made visible when the visualize GLM option is selected.
%
%
% ras, 10/06
if notDefined('mv'), mv = get(gcf, 'UserData'); end
if ishandle(mv), mv = get(mv, 'UserData'); end

mv.ui.glmPanel = mrvPanel('right',  .2);
set(mv.ui.glmPanel,  'BackgroundColor',  'w');

% voxel slider
nVoxels = size(mv.tSeries,  2);
mv.ui.glmVoxel = mrvSlider([.1 .8 .8 .1], 'Voxel', 'Parent', mv.ui.glmPanel,  ...
                           'Range',  [1 nVoxels], 'IntFlag', 1, ...
                           'MaxLabelFlag', 1, ...
                           'Callback', 'mv_visualizeGlm(gcf,  round(val));');

% buttons to grab the current voxel time course, multi voxel
cb = ['tmp = get(gcf, ''UserData''); ' ...
      'iTmp = get(tmp.ui.glmVoxel.sliderHandle, ''Value''); ' ...
      'mv_selectSubset(tmp, iTmp, ''voxels'', 2); ' ...
      'clear tmp iTmp'];
uicontrol('Parent', mv.ui.glmPanel, 'Style', 'pushbutton', ...
          'Units', 'norm', 'Position', [.1 .6 .8 .06], ...
          'String', 'Cur Voxel Timecourse', 'FontSize', 9, ...
          'BackgroundColor', 'w', 'HorizontalAlignment', 'center', ...
          'Callback', cb);

cb = ['tmp = get(gcf, ''UserData''); ' ...
      'iTmp = get(tmp.ui.glmVoxel.sliderHandle, ''Value''); ' ...
      'mv_selectSubset(tmp, iTmp, ''voxels'', 1); ' ...
      'clear tmp iTmp'];
uicontrol('Parent', mv.ui.glmPanel, 'Style', 'pushbutton', ...
          'Units', 'norm', 'Position', [.1 .54 .8 .06], ...
          'String', 'Cur Voxel MVUI', 'FontSize', 9, ...
          'BackgroundColor', 'w', 'HorizontalAlignment', 'center', ...
          'Callback', cb);

% text describing voxel location
mv.ui.glmVoxCoords = uicontrol('Parent', mv.ui.glmPanel, 'Style', 'text', ...
          'Units', 'Normalized', 'Position', [.1 .4 .8 .06], ...
          'String', '', 'BackgroundColor', 'w');

% toggle buttons for time course traces
cb = ['tmp = {''off'' ''on''}; val = get(gcbo, ''Value'')+1; ' ...
      'set(get(gcbo,''UserData''), ''Visible'', tmp{val}); ' ...
      'clear tmp val '];

h1 = uicontrol('Parent', mv.ui.glmPanel, 'Style', 'checkbox', ...
               'Units', 'normalized', ...
               'Position', [.1 .2 .8 .05], 'String', 'Time Course', ...
               'BackgroundColor', 'w', 'Value', 1, 'Callback', cb);
h2 = uicontrol('Parent', mv.ui.glmPanel, 'Style', 'checkbox', ...
               'Units', 'normalized', ...
               'Position', [.1 .15 .8 .05], 'String', 'Predictors', ...
               'BackgroundColor', 'w', 'Value', 0, 'Callback', cb);
h3 = uicontrol('Parent', mv.ui.glmPanel, 'Style', 'checkbox', ...
               'Units', 'normalized', ...
               'Position', [.1 .1 .8 .05], 'String', 'Best Fit', ...
               'BackgroundColor', 'w', 'Value', 1, 'Callback', cb);
h4 = uicontrol('Parent', mv.ui.glmPanel, 'Style', 'checkbox', ...
               'Units', 'normalized', ...
               'Position', [.1 .05 .8 .05], 'String', 'Residual', ...
               'BackgroundColor', 'w', 'Value', 0, 'Callback', cb);

mv.ui.glmToggles = [h1 h2 h3 h4];

set( get(mv.ui.glmPanel, 'Children'), 'Units', 'normalized' );

mrvPanelToggle(mv.ui.glmPanel,  'off');

return


function labels_plot(expdirs,jabs,nframesplot,varargin)
% Labelgram

% AL 20150128: This is looking more like ethogram_plot
% AL 20150202: even worse, xlsExport

if ~exist('expdirs','var')
  expdirs = {};
end
assert(iscellstr(expdirs));
if ~exist('jabs','var')
  jabs = [];
end
if isempty(jabs)
  [tfsuccess,jabs] = ExpPP.uiGetJabFiles;
  if ~tfsuccess
    return;
  end
end
if ~exist('nframesplot','var')
  nframesplot = [];
elseif ~isempty(nframesplot)
  assert(isnumeric(nframesplot));
  assert(isscalar(nframesplot) || numel(nframesplot)==2,'Invalid nframesplot');
end

[xlsexport,xlsfile,ethcoreargexport] = myparse(varargin,...
  'xlsexport',false,...
  'xlsfile',[],...
  'ethcoreargexport',false);

assert(isscalar(jabs),'Currently expect single jab/macguffin.');
if iscellstr(jabs)
  jabfiles = jabs;
  jabs = loadAnonymous(jabs{1});
elseif isa(jabs,'Macguffin');
  jabfiles = {[]};
else
  assert(false,'''jabs'' argument must be either a jab filename or object.');
end

if isempty(expdirs)
  expdirs = jabs.expDirNames;
end
Nexp = numel(expdirs);

jab = jabs;
jab.modernize();

% Special case for AH exps. Call ExpPP.loadexps on all experiments now.
% Any experiments that do not load are excluded.
behs = Labels.verifyBehaviorNames(jab.behaviors.names);
doautomarks = ExpPP.doNamesSpanAllBasicBehaviors(behs);
if doautomarks
  % guess in this case require jabfiles to be nonempty, ie jabs cannot have
  % been obj
  dPP = ExpPP.loadexps(expdirs,jabfiles,'includelabels',true);
  if isempty(dPP)
    error('labels_plot:noExps','ExpPP failed to load any experiments.');
  end
  expsLoaded = {dPP.expfull}';
  tfloaded = ismember(expdirs,expsLoaded);
  if ~all(tfloaded)
    tmpstr = expdirs(~tfloaded);
    tmpstr = sprintf('%s\n',tmpstr{:});
    warningNoTrace('labels_plot:expsExcluded','Excluding %d incomplete experiments from labelgram: %s.',...
      nnz(~tfloaded),tmpstr);
  end
  expdirs = expsLoaded;
  Nexp = numel(expdirs);
end

% get the labels for expdirs
assert(numel(jab.expDirNames)==numel(jab.labels));
[tf,loc] = ismember(expdirs,jab.expDirNames);
lbls = Labels.labels(Nexp);
lbls(tf) = jab.labels(loc(tf));

% Trx/T0/T1/nframesplot
trxfname = jab.file.trxfilename;
trxstarts = nan(Nexp,1);
trxends = nan(Nexp,1);
for i = 1:Nexp
  trxfile = fullfile(expdirs{i},trxfname);
  tmp = load(trxfile,'trx');
  trxstarts(i) = min([tmp.trx.firstframe]);
  trxends(i) = max([tmp.trx.endframe]);
end
T0 = min(trxstarts);
T1 = max(trxends)-1;
if ~isempty(nframesplot)
  if numel(nframesplot)==1,
    T1 = min(T1,T0+nframesplot-1);
  else
    assert(numel(nframesplot)==2);
    T0 = nframesplot(1);
    T1 = min(T1,nframesplot(2));
  end
end

if doautomarks
  % in this case:
  % - use exptags from jab if possible

  dPP = ExpPP.ensureCustomGroupInit(dPP);
  assert(isequal({dPP.expfull}',expdirs));
  [tfExpInJab,loc] = ismember(expdirs,jab.expDirNames);
  if all(tfExpInJab)
    if isstruct(jab) && isfield(jab,'expDirTags') || ...
       isobject(jab) && isprop(jab,'expDirTags')
      exptags = jab.expDirTags(loc);
      exptags = ExperimentTags.cleanLegacyNotTags(exptags);
    else
      exptags = [];
    end
    if isempty(exptags)
      exptags = ExperimentTags.expTags(expdirs);
    end

    allUniqueTags = ExperimentTags.allUniqueTags(exptags);
    allUniqueTagsValid = matlab.lang.makeValidName(allUniqueTags);
    if numel(unique(allUniqueTagsValid))~=numel(allUniqueTagsValid)
      error('ethogram_plot:tag','Repeated tags.'); % very rare
    end
    Ntag = numel(allUniqueTags);
    for iTag = 1:Ntag
      tagRaw = allUniqueTags{iTag};
      cgrpname = allUniqueTagsValid{iTag};
      tfTag = ExperimentTags.findTag(exptags,tagRaw);
      dPP = ExpPP.createCustomGroup(dPP,tfTag,cgrpname);
    end
  end

  ethplotcoreargs = {'doautomarks',true,'automarkdata',dPP,'expppstatprefix','labl','expppcontrolargs',{'labelgram' true}};
else
  ethplotcoreargs = cell(1,0);
end

% go
m = Labels.labelMatrix(lbls,T0,T1,behs);
ethplotcoreargs = [{figure,m,T0,T1,expdirs,behs,repmat(jabfiles,numel(behs),1)} ethplotcoreargs];
if ethcoreargexport
  fname = sprintf('ethcoreargs.%s.mat',datestr(now,'yyyymmddTHHMMSS'));
  save(fname,'ethplotcoreargs');
end
[boutmat,line_names] = ethogram_plot_core(ethplotcoreargs{:});

if xlsexport
  if isempty(xlsfile)
    [xlsfile,xlspath] = uiputfile('bouts.txt','Export to file');
    if isequal(xlsfile,0)
      xlsfile = [];
    else
      xlsfile = fullfile(xlspath,xlsfile);
    end
  elseif exist(xlsfile,'file')
    warning('ethogram_plot:fileExists','Overwriting file ''%s''.',xlsfile);
  end

  if ~isempty(xlsfile)
    Ethogram.boutExport(xlsfile,boutmat,line_names,behs);
    fprintf(1,'Exported to tab-delimited file ''%s''.\n',xlsfile);
  end
end


function test_suite=BatchExample_qmt_bssfp_test
try % assignment of 'localfunctions' is necessary in Matlab >= 2016
    test_functions=localfunctions();
catch % no problem; early Matlab versions can use initTestSuite fine
end
initTestSuite;

function TestSetup
setenv('ISCITEST','1') % go faster! Fit only 2 voxels in FitData.m

function test_batch
curdir = pwd;

tmpDir = tempdir;
mkdir(tmpDir);
cd(tmpDir);

Modellist = {'b1_afi'};

for iModel = 1:length(Modellist)
    disp('===============================================================')
    disp(['Testing: ' Modellist{iModel} ' BATCH...'])
    disp('===============================================================')

    eval(['Model = ' Modellist{iModel}]);

    qMRgenBatch(Model,pwd)

    % Test if any dataset exist
    isdata = true;
    try
        Model.onlineData_url;
    catch
        isdata = false;
    end

    % Run Batch
    if isdata
        starttime = tic;
        eval([Modellist{iModel} '_batch'])
        toc(starttime)
    end
    close all
    cd ..

end
cd(curdir)

function TestTeardown
setenv('ISCITEST','0')


% This file is part of TREEQSM.
%
% TREEQSM 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.
%
% TREEQSM 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 TREEQSM.  If not, see <http://www.gnu.org/licenses/>.

function plot_models_segmentations(P,cover,segment,cylinder,trunk,triangulation)

% ---------------------------------------------------------------------
% PLOT_MODELS_SEGMENTATION.M   Plots the segmented point clouds and
%                               cylinder/triangulation models
%
% Version 1.1.0
% Latest update     13 July 2020
%
% Copyright (C) 2013-2020 Pasi Raumonen
% ---------------------------------------------------------------------

% Inputs:
% P             Point cloud
% cover         cover-structure array
% segment       segment-structure array
% cylinder      cylinder-structure array
% trunk         point cloud of the trunk
% triangulation triangulation-structure array

% Changes from version 1.0.0 to 1.1.0, 13 July 2020:
% 1) plots now figure 1 and 2 with two subplots; in the first the colors
%    are based on branching order and in the second they are based on
%    branch

%% figure 1: branch-segmented point cloud
% colors denote the branching order and branches
figure(1)
subplot(1,2,1)
plot_branch_segmentation(P,cover,segment,'order')
subplot(1,2,2)
plot_branch_segmentation(P,cover,segment,'branch')

%% figure 2: cylinder model
% colors denote the branching order and branches
Sta = cylinder.start;
P = P-Sta(1,:);
if nargin > 5
    trunk = trunk-Sta(1,:);
    Vert = double(triangulation.vert);
    Vert = Vert-Sta(1,:);
end
Sta = Sta-Sta(1,:);
cylinder.start = Sta;
figure(2)
subplot(1,2,1)
plot_cylinder_model(cylinder,'order',2,10)
subplot(1,2,2)
plot_cylinder_model(cylinder,'branch',2,10)

%% figure 3, segmented point cloud and cylinder model
plot_branch_segmentation(P,cover,segment,'order',3,1)
hold on
plot_cylinder_model(cylinder,'order',3,10,0.7)
hold off

if nargin > 4
    %% figure 4, triangulation model (bottom) and cylinder model (top)
    % of the stem
    Facets = double(triangulation.facet);
    CylInd = triangulation.cylind;
    fvd = triangulation.fvd;
    if max(size(Vert)) > 5
        Bran = cylinder.branch;
        nc = size(Bran,1);
        ind = (1:1:nc)';
        C = ind(Bran == 1);
        n = size(trunk,1);
        I = logical(round(0.55*rand(n,1)));
        figure(4)
        point_cloud_plotting(trunk(I,:),4,3)
        patch('Vertices',Vert,'Faces',Facets,'FaceVertexCData',fvd,...
            'FaceColor','flat')
        alpha(1)
        hold on
        plot_cylinder_model(cylinder,'order',4,20,1,(CylInd:C(end)))
        axis equal
        hold off
    else
        disp('No triangulation model generated!')
    end
end


function [mri] = ft_read_mri(filename)

% FT_READ_MRI reads anatomical and functional MRI data from different
% file formats. The output data is structured in such a way that it is
% comparable to a FieldTrip source reconstruction.
%
% Use as
%   [mri] = ft_read_mri(filename)
%
% The output MRI may have a homogenous transformation matrix that converts
% the coordinates of each voxel (in xgrid/ygrid/zgrid) into head
% coordinates.
%
% See also FT_READ_DATA, FT_READ_HEADER, FT_READ_EVENT

% Copyright (C) 2008-2010 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: ft_read_mri.m 2973 2011-02-26 13:54:24Z jansch $

% test for the presence of some external functions from other toolboxes
hasmri  = ft_hastoolbox('mri');     % from Darren Weber, see http://eeg.sourceforge.net/
hasspm2 = ft_hastoolbox('SPM2');    % see http://www.fil.ion.ucl.ac.uk/spm/
hasspm5 = ft_hastoolbox('SPM5');    % see http://www.fil.ion.ucl.ac.uk/spm/
hasspm8 = ft_hastoolbox('SPM8');    % see http://www.fil.ion.ucl.ac.uk/spm/
hasspm = (hasspm2 || hasspm5 || hasspm8);
hasafni = ft_hastoolbox('afni');    % see http://afni.nimh.nih.gov/

% test whether the file exists
if ~exist(filename)
  error(sprintf('file ''%s'' does not exist', filename));
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if ft_filetype(filename, 'ctf_mri')
  [img, hdr] = read_ctf_mri(filename);
  transform = hdr.transformMRI2Head;

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif ft_filetype(filename, 'ctf_mri4')
  [img, hdr] = read_ctf_mri4(filename);
  transform = hdr.transformMRI2Head;

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif ft_filetype(filename, 'ctf_svl')
  [img, hdr] = read_ctf_svl(filename);
  transform = hdr.transform;

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif ft_filetype(filename, 'asa_mri')
  [img, seg, hdr] = read_asa_mri(filename);
  transform = hdr.transformMRI2Head;

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif ft_filetype(filename, 'minc')
  if ~(hasspm2 || hasspm5)
    error('the SPM2 or SPM5 toolbox is required to read *.mnc files');
  end
  % use the functions from SPM
  hdr = spm_vol_minc(filename);
  img = spm_read_vols(hdr);
  transform = hdr.mat;

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif ft_filetype(filename, 'nifti')
  if ~(hasspm5 || hasspm8)
    error('the SPM5 or SPM8 toolbox is required to read *.nii files');
  end
  % use the functions from SPM
  hdr = spm_vol_nifti(filename);
  img = spm_read_vols(hdr);
  transform = hdr.mat;

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif (ft_filetype(filename, 'analyze_img') || ft_filetype(filename, 'analyze_hdr')) && hasspm
  % use the image file instead of the header
  filename((end-2):end) = 'img';
  % use the functions from SPM to read the Analyze MRI
  hdr = spm_vol(filename);
  img = spm_read_vols(hdr);
  transform = hdr.mat;

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif (ft_filetype(filename, 'analyze_hdr') || ft_filetype(filename, 'analyze_img')) && hasmri
  % use the functions from Darren Weber's mri_toolbox to read the Analyze MRI
  avw = avw_img_read(filename, 0); % returned volume is LAS*
  img = avw.img;
  hdr = avw.hdr;
  % The default Analyze orientation is axial unflipped (LAS*), which means
  % that the resulting volume is according to the radiological convention.
  % Most other fMRI and EEG/MEG software (except Mayo/Analyze) uses
  % neurological conventions and a right-handed coordinate system, hence
  % the first axis of the 3D volume (right-left) should be flipped to make
  % the coordinate system comparable to SPM
  warning('flipping 1st dimension (L-R) to obtain volume in neurological convention');
  img = flipdim(img, 1);
  % FIXME: here I should also implement a homogenous transformation matrix,
  % using the voxel dimensions that are specified in hdr.dime.pixdim

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif (ft_filetype(filename, 'afni_brik') || ft_filetype(filename, 'afni_head')) && hasafni
  [err, img, hdr, ErrMessage] = BrikLoad(filename);
  if err
    error('could not read AFNI file');
  end

  % FIXME: this should be checked, but I only have a single BRIK file
  % construct the homogenous transformation matrix that defines the axes
  warning('homogenous transformation might be incorrect for AFNI file');
  transform        = eye(4);
  transform(1:3,4) = hdr.ORIGIN(:);
  transform(1,1)   = hdr.DELTA(1);
  transform(2,2)   = hdr.DELTA(2);
  transform(3,3)   = hdr.DELTA(3);

  % FIXME: I am not sure about the "RAI" image orientation
  img = flipdim(img,1);
  img = flipdim(img,2);
  dim = size(img);
  transform(1,4) = -dim(1) - transform(1,4);
  transform(2,4) = -dim(2) - transform(2,4);

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif ft_filetype(filename, 'neuromag_fif') && ft_hastoolbox('mne')
  % use the mne functions to read the Neuromag MRI
  hdr = fiff_read_mri(filename);
  img = cat(3, hdr.slices.data);
  hdr.slices = rmfield(hdr.slices, 'data'); % remove the image data to save memory
  % hmm, which transformation matrix should I use?
  if isfield(hdr, 'voxel_trans') && issubfield(hdr.voxel_trans, 'trans')
    transform = hdr.voxel_trans.trans;
  elseif isfield(hdr, 'trans') && issubfield(hdr.trans, 'trans')
    transform = hdr.trans.trans;
  end

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif ft_filetype(filename, 'neuromag_fif') && ft_hastoolbox('meg_pd')
  % use the meg_pd functions to read the Neuromag MRI
  [img,coords] = loadmri(filename);
  dev = loadtrans(filename,'MRI','HEAD');
  transform  = dev*coords;
  hdr.coords = coords;
  hdr.dev    = dev;

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif ft_filetype(filename, 'neuromag_fif')
  error('reading MRI data from a fif file requires either the MNE toolbox or the meg_pd toolbox to be installed');

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif ft_filetype(filename, 'dicom')
  % this uses the Image processing toolbox
  % the DICOM file probably represents a stack of slices, possibly even multiple volumes
  orig = dicominfo(filename);
  dim(1) = orig.Rows;
  dim(2) = orig.Columns;

  [p, f] = fileparts(filename);

  % this works for the Siemens scanners at the FCDC
  tok = tokenize(f, '.');
  for i=5:length(tok)
    tok{i} = '*';
  end
  filename = sprintf('%s.', tok{:});  % reconstruct the filename with wildcards and '.' between the segments
  filename = filename(1:end-1);       % remove the last '.'
  dirlist  = dir(fullfile(p, filename));
  dirlist  = {dirlist.name};

  if length(dirlist)==1
    % try something else to get a list of all the slices
    dirlist = dir(fullfile(p, '*'));
    dirlist = {dirlist(~[dirlist.isdir]).name};
  end

  keep = false(1, length(dirlist));
  for i=1:length(dirlist)
    filename = char(fullfile(p, dirlist{i}));
    if ~ft_filetype(filename, 'dicom')
      keep(i) = false;
      fprintf('skipping ''%s'' because of incorrect filetype\n', filename);
    end
    % read the header information
    info     = dicominfo(filename);
    if info.SeriesNumber~=orig.SeriesNumber
      keep(i) = false;
      fprintf('skipping ''%s'' because of different SeriesNumber\n', filename);
    else
      keep(i) = true;
      hdr(i)  = info;
    end
  end
  % remove the files that were skipped
  hdr     = hdr(keep);
  dirlist = dirlist(keep);

  % pre-allocate enough space for the subsequent slices
  dim(3) = length(dirlist);
  img    = zeros(dim(1), dim(2), dim(3));
  for i=1:length(dirlist)
    filename = char(fullfile(p, dirlist{i}));
    fprintf('reading image data from ''%s''\n', filename);
    img(:,:,i) = dicomread(hdr(i));
  end

  % reorder the slices
  [z, indx]   = sort(cell2mat({hdr.SliceLocation}));
  hdr = hdr(indx);
  img = img(:,:,indx);

  try
    % construct a homgeneous transformation matrix that performs the scaling from voxels to mm
    dx = hdr(1).PixelSpacing(1);
    dy = hdr(1).PixelSpacing(2);
    dz = hdr(2).SliceLocation - hdr(1).SliceLocation;
    transform = eye(4);
    transform(1,1) = dx;
    transform(2,2) = dy;
    transform(3,3) = dz;
  end
elseif ft_filetype(filename, 'freesurfer_mgz')
  ft_hastoolbox('freesurfer', 1);
  tmp = MRIread(filename);
  img = permute(tmp.vol, [2 1 3]); %FIXME although this is probably correct
  %see the help of MRIread, anecdotally columns and rows seem to need a swap
  %in order to match the transform matrix (alternatively a row switch of the
  %latter can be done)
  hdr = rmfield(tmp, 'vol');
  transform = tmp.vox2ras1;
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
else
  error(sprintf('unrecognized filetype of ''%s''', filename));
end

% set up the axes of the volume in voxel coordinates
nx = size(img,1);
ny = size(img,2);
nz = size(img,3);
mri.dim = [nx ny nz];
% store the anatomical data
mri.anatomy = img;
% store the header with all fileformat specific details
mri.hdr = hdr;
try
  % if present, store the homogenous transformation matrix
  mri.transform = transform;
end
try
  % try to add units
  mri = ft_convert_units(mri);
end


%{
 * Copyright (C) 2020-2030, The Regents of The University of Michigan.
 * All rights reserved.
 * This software was developed in the Biped Lab (https://www.biped.solutions/)
 * under the direction of Jessy Grizzle, grizzle@umich.edu. This software may
 * be available under alternative licensing terms; contact the address above.
 * 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 OWNER 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.
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the Regents of The University of Michigan.
 *
 * AUTHOR: Bruce JK Huang (bjhuang[at]umich.edu)
 * WEBSITE: https://www.brucerobot.com/
%}

function data = splitPointsBasedOnRing(opts, point_cloud)
    data(opts.num_beams) = struct();
    data(opts.num_beams).points = [];
    data(opts.num_beams).point_with_I = [];
    for i = opts.pc_iter : opts.pc_iter+opts.num_scan
        total = 0;
        points = point_cloud(i, :, :);
        points = (reshape(points, size(points, 2),[]))';
        points = removeZeros(points);
        original_size = size(points,2);
        for n = 0:opts.num_beams-1
            if ~any(points(5,:)==n)
    %             disp("n")
    %             disp(n)
    %             disp("points")
    %             disp(points(:, points(5,:)==n))
    %             pause;
                continue
            end
            ring_point = points(:, points(5,:)==n);
            if size(ring_point,2) < opts.min_points
                original_size = original_size - size(ring_point,2);
                continue;
            end
            m = n+1;
            ring_point_homogeneous = [ring_point(1:3,:); ones(1,size(ring_point,2))];
            data(m).points = [data(m).points ring_point_homogeneous];
            data(m).point_with_I = [data(m).point_with_I ring_point];
            total= total+size(ring_point,2);
        end
        if total ~= original_size
            warning("inconsistent number of poins in splitPointsBasedOnRing.m");
            warning("split total: %i", total)
            warning("original total %i", size(points,2))
        end
    end
end


function results = PTKMultipleRegionAnalysis(slice_bins, roi, context_mask, context_no_airways, distance_label, reporting)
    % PTKMultipleRegionAnalysis. Calculates metrics based on bins
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2014.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.

    results = PTKMetrics.empty;

    if isempty(context_mask) || ~context_mask.ImageExists
        return;
    end

    bin_image = slice_bins.BinImage;
    bin_regions = slice_bins.BinRegions;

    % Reduce all images to a consistent size
    bin_image.CropToFit;
    roi.ResizeToMatch(bin_image);
    context_mask.ResizeToMatch(bin_image);
    context_no_airways.ResizeToMatch(bin_image);

    reporting.UpdateProgressAndMessage(0, 'Calculating metrics for each bin');

    % Iterate over each bin
    for bin_index = 1 : numel(bin_regions)
        reporting.UpdateProgressStage(bin_index, numel(bin_regions));
        region = bin_regions(bin_index);
        bin_number = region.RegionNumber;
        bin_colour_index = region.ColormapIndex;
        distance_from_origin = region.DistanceFromOrigin;
        coordinates = region.Coordinates;

        % Create a mask for this bin
        mask = bin_image.BlankCopy;
        mask.ChangeRawImage(bin_image.RawImage == bin_colour_index & context_mask.RawImage);
        mask.CropToFit;

        % Create a mask for this bin excluding the airways
        no_airways_mask = bin_image.BlankCopy;
        no_airways_mask.ChangeRawImage(bin_image.RawImage == bin_colour_index & context_no_airways.RawImage);
        no_airways_mask.ResizeToMatch(mask);

        roi_reduced = roi.Copy;
        roi_reduced.ResizeToMatch(mask);
        bin_results = PTKComputeAirTissueFraction(roi_reduced, mask, reporting);
        [emphysema_results, ~] = PTKComputeEmphysemaFromMask(roi_reduced, no_airways_mask);
        bin_results.Merge(emphysema_results);
        bin_results.AddMetric('RegionNumber', bin_number, 'Region Number');
        bin_results.AddMetric('DistanceFromLungBaseMm', distance_from_origin, distance_label);
        bin_results.AddMetric('RegionCoordinateX', coordinates.CoordX, 'Region Coordinates X (mm)');
        bin_results.AddMetric('RegionCoordinateY', coordinates.CoordY, 'Region Coordinates Y (mm)');
        bin_results.AddMetric('RegionCoordinateZ', coordinates.CoordZ, 'Region Coordinates Z (mm)');

        results(end + 1) = bin_results;
    end
end


function y = base64decode(x)
%BASE64DECODE Perform base64 decoding on a string.
%
%   BASE64DECODE(STR) decodes the given base64 string STR.
%
%   Any character not part of the 65-character base64 subset set is silently
%   ignored.  Characters occuring after a '=' padding character are never
%   decoded.
%
%   STR doesn't have to be a string.  The only requirement is that it is a
%   vector containing values in the range 0-255.
%
%   If the length of the string to decode (after ignoring non-base64 chars) is
%   not a multiple of 4, then a warning is generated.
%
%   This function is used to decode strings from the Base64 encoding specified
%   in RFC 2045 - MIME (Multipurpose Internet Mail Extensions).  The Base64
%   encoding is designed to represent arbitrary sequences of octets in a form
%   that need not be humanly readable.  A 65-character subset ([A-Za-z0-9+/=])
%   of US-ASCII is used, enabling 6 bits to be represented per printable
%   character.
%
%   See also BASE64ENCODE.

%   Author:      Peter John Acklam
%   Time-stamp:  2004-09-20 08:20:50 +0200
%   E-mail:      pjacklam@online.no
%   URL:         http://home.online.no/~pjacklam

   % check number of input arguments
   error(nargchk(1, 1, nargin));

   % remove non-base64 chars
   x = x (   ( 'A' <= x & x <= 'Z' ) ...
           | ( 'a' <= x & x <= 'z' ) ...
           | ( '0' <= x & x <= '9' ) ...
           | ( x == '+' ) | ( x == '=' ) | ( x == '/' ) );

   if rem(length(x), 4)
      warning('Length of base64 data not a multiple of 4; padding input.');
   end

   k = find(x == '=');
   if ~isempty(k)
      x = x(1:k(1)-1);
   end

   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % Now perform the following mapping
   %
   %   A-Z  ->  0  - 25
   %   a-z  ->  26 - 51
   %   0-9  ->  52 - 61
   %   +    ->  62
   %   /    ->  63

   y = repmat(uint8(0), size(x));
   i = 'A' <= x & x <= 'Z'; y(i) =    - 'A' + x(i);
   i = 'a' <= x & x <= 'z'; y(i) = 26 - 'a' + x(i);
   i = '0' <= x & x <= '9'; y(i) = 52 - '0' + x(i);
   i =            x == '+'; y(i) = 62 - '+' + x(i);
   i =            x == '/'; y(i) = 63 - '/' + x(i);
   x = y;

   nebytes = length(x);         % number of encoded bytes
   nchunks = ceil(nebytes/4);   % number of chunks/groups

   % add padding if necessary
   if rem(nebytes, 4)
      x(end+1 : 4*nchunks) = 0;
   end

   x = reshape(uint8(x), 4, nchunks);
   y = repmat(uint8(0), 3, nchunks);            % for the decoded data

   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % Rearrange every 4 bytes into 3 bytes
   %
   %    00aaaaaa 00bbbbbb 00cccccc 00dddddd
   %
   % to form
   %
   %    aaaaaabb bbbbcccc ccdddddd

   y(1,:) = bitshift(x(1,:), 2);                    % 6 highest bits of y(1,:)
   y(1,:) = bitor(y(1,:), bitshift(x(2,:), -4));    % 2 lowest bits of y(1,:)

   y(2,:) = bitshift(x(2,:), 4);                    % 4 highest bits of y(2,:)
   y(2,:) = bitor(y(2,:), bitshift(x(3,:), -2));    % 4 lowest bits of y(2,:)

   y(3,:) = bitshift(x(3,:), 6);                    % 2 highest bits of y(3,:)
   y(3,:) = bitor(y(3,:), x(4,:));                  % 6 lowest bits of y(3,:)

   % remove padding
   switch rem(nebytes, 4)
      case 2
         y = y(1:end-2);
      case 3
         y = y(1:end-1);
   end

   % reshape to a row vector and make it a character array
   y = char(reshape(y, 1, numel(y)));


function r = not(p)
%UMINUS: this function applies a unary minus to the x, y, and z values of the structures that I use in
% the FVtool.
%
% SYNOPSIS:
%
%
% PARAMETERS:
%
%
% RETURNS:
%
%
% EXAMPLE:
%
% SEE ALSO:
%

% Copyright (c) 2012-2016 Ali Akbar Eftekhari
% See the license file

r=p;
r.xvalue = ~p.xvalue;
r.yvalue = ~p.yvalue;
r.zvalue = ~p.zvalue;


function out = eval_chance( imdb, labelspath )
% RETRIEVAL_EVAL_CHANCE

% Read the files
labels = utls.readfile(labelspath);
poolSignatures = strsplit(labels{1}, ',');
% Compare the headers
numQueries = numel(labels) - 1;
imRetAps = zeros(1, numQueries); patchRetAps = zeros(1, numQueries);
numAllFeats = sum(cellfun(@(sign) imdb.getNumPatches(sign), poolSignatures));
for lni = 2:numel(labels)
  query_cluster_descs = strsplit(labels{lni}, ',');
  query_cluster_ims = remove_patchnum(query_cluster_descs);
  query_cluster_nfeats = sum(cellfun(@(sign) imdb.getNumPatches(sign), query_cluster_ims));

  imRetAps(lni) = (query_cluster_nfeats - 1) ./ (numAllFeats - 1);
  patchRetAps(lni) = (numel(query_cluster_descs) - 1) ./ (numAllFeats - 1);
end
out = struct('image_retr_ap', imRetAps, 'patch_retr_ap', patchRetAps);
end

function signs = remove_patchnum(signs)
% Get a sequence.imagename part of a signature
for si = 1:numel(signs)
  parts = strsplit(signs{si}, '.');
  assert(numel(parts) == 3, 'Invalid patch signature.');
  signs{si} = strjoin(parts(1:2), '.');
end
end


function result = t_most_3b_3_1_2(quiet)
%T_MOST_3B_1_1_2  Tests for MOST.

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

if nargin < 1
    quiet = 0;
end

n_tests = 51;

t_begin(n_tests, quiet);

casename = 't_case3_most';
fudging = struct( ...       %% paramters for fudging reserve contract for sopf2
    'fudge',    0.05, ...   %% initial value (MW)
    'step',     0.01, ...   %% if necessary, increase by this amount and retry (MW)
    'lim',      0.1);       %% upper limit (MW), give up if no convergence
                            %% with fudge equal to this limit

%% options
algs.dc     = {'MIPS'}; %% opf.dc.solver sequence to try for c3sopf (DC run)
algs.ac     = {'MIPS'}; %% opf.ac.solver sequence to try for c3sopf (AC run)
mpopt = mpoption('verbose', 0, 'out.all', 0);
mpopt = mpoption(mpopt, 'opf.violation', 5e-7, 'mips.comptol', 5e-8);
mpopt = mpoption(mpopt, 'sopf.force_Pc_eq_P0', 0);  %% don't constrain contracted == base case dispatch
mpoptac = mpoption(mpopt, 'model', 'AC');
mpoptdc = mpoption(mpopt, 'model', 'DC');
mpopt = mpoption(mpopt, 'most.solver', algs.dc{1});
if have_feature('octave') && have_feature('octave', 'vnum') > 7
    mpopt = mpoption(mpopt, 'mips.linsolver', 'LU');
end

%% turn off warnings
if have_feature('octave')
    s = warning('query', 'Octave:nearly-singular-matrix');
    warning('off', 'Octave:nearly-singular-matrix');
else
    s7 = warning('query', 'MATLAB:nearlySingularMatrix');
    s6 = warning('query', 'MATLAB:nearlySingularMatrixUMFPACK');
    warning('off', 'MATLAB:nearlySingularMatrix');
    warning('off', 'MATLAB:nearlySingularMatrixUMFPACK');
end

%% define named indices into data matrices
[GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
    MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
    QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
[F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
    TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
    ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
[CT_LABEL, CT_PROB, CT_TABLE, CT_TBUS, CT_TGEN, CT_TBRCH, CT_TAREABUS, ...
    CT_TAREAGEN, CT_TAREABRCH, CT_ROW, CT_COL, CT_CHGTYPE, CT_REP, ...
    CT_REL, CT_ADD, CT_NEWVAL, CT_TLOAD, CT_TAREALOAD, CT_LOAD_ALL_PQ, ...
    CT_LOAD_FIX_PQ, CT_LOAD_DIS_PQ, CT_LOAD_ALL_P, CT_LOAD_FIX_P, ...
    CT_LOAD_DIS_P, CT_TGENCOST, CT_TAREAGENCOST, CT_MODCOST_F, ...
    CT_MODCOST_X] = idx_ct;

%% reserve and delta offers
xgd_table.colnames = {
    'PositiveActiveReservePrice', ...
            'PositiveActiveReserveQuantity', ...
                    'NegativeActiveReservePrice', ...
                            'NegativeActiveReserveQuantity', ...
                                    'PositiveActiveDeltaPrice', ...
                                            'NegativeActiveDeltaPrice', ...
};
xgd_table.data = [
    1       400     2       400     0.01    0.01;
    3       300     4       300     0.01    0.01;
    0.001   450     0.002   450     0       0;
];

%% contingency table
% label probty  type        row column      chgtype newvalue
contab = [
    1   0.01    CT_TBRCH    1   BR_STATUS   CT_REP  0;      %% line 1-2
    2   0.01    CT_TGEN     1   GEN_STATUS  CT_REP  0;      %% gen 1 at bus 1
%   2   0.00049621965   CT_TGEN     1   GEN_STATUS  CT_REP  0;      %% gen 1 at bus 1
];
clist = unique(contab(:, CT_LABEL));
nc = length(clist);

%% load the case
mpc = loadcase(casename);
gbus = mpc.gen(:, GEN_BUS);

%%-----  get c3sopf results  -----
rdc = c3sopf_retry(algs.dc, mpc, xgd_table.data, contab, mpoptdc);
% rac = c3sopf_retry(algs.ac, mpc, xgd_table.data, contab, mpoptac);
% save t_most3_soln rdc rac -v6
% s = load('t_most3_soln');
s.rdc = rdc;
% s.rac = rac;

%%-----  set up data for DC run (most)  -----
ng = size(mpc.gen, 1);      %% number of gens
nt = 3;
xgd = loadxgendata(xgd_table, mpc);
md = loadmd(mpc, nt, xgd, [], contab);

%%-----  do DC run (most)  -----
r = most(md, mpopt);

%%-----  test the results  -----
t = 'success1';
t_ok(s.rdc.opf_results.success, t);
t = 'success2';
t_is(r.QP.exitflag, 1, 12, t);

t = 'f';
t_is(r.results.f/sum(r.StepProb), s.rdc.opf_results.f, 4, t);

for tt = 1:nt

t = sprintf('(t=%d) Pg : base', tt);
t_is(r.flow(tt,1,1).mpc.gen(:, PG), s.rdc.base.gen(:, PG), 5, t);
t = sprintf('(t=%d) Pg : cont ', tt);
for k = 1:nc
    t_is(r.flow(tt,1,k+1).mpc.gen(:, PG), s.rdc.cont(k).gen(:, PG), 5, sprintf('%s %d', t, k));
end

% t = sprintf('(t=%d) gen : base', tt);
% t_is(r.flow(tt,1,1).mpc.gen(:,1:MU_PMIN), s.rdc.base.gen(:,1:MU_PMIN), 3, t);
% t = sprintf('(t=%d) gen : cont ', tt);
% for k = 1:nc
%     t_is(r.flow(tt,1,k+1).mpc.gen(:,1:MU_PMIN), s.rdc.cont(k).gen(:,1:MU_PMIN), 3, sprintf('%s %d', t, k));
% end

t = sprintf('(t=%d) energy prices', tt);
t_is(r.results.GenPrices(:,tt)/r.StepProb(tt), s.rdc.energy.prc.sum_bus_lam_p(gbus), 6, t);

t = sprintf('(t=%d) Pc', tt);
t_is(r.results.Pc(:,tt), s.rdc.energy.Pc, 4, t);

t = sprintf('(t=%d) Gmin', tt);
t_is(r.results.Pc(:,tt) - r.results.Rpm(:,tt), s.rdc.energy.Gmin, 4, t);

t = sprintf('(t=%d) Gmax', tt);
t_is(r.results.Pc(:,tt) + r.results.Rpp(:,tt), s.rdc.energy.Gmax, 4, t);

t = sprintf('(t=%d) upward contingency reserve quantities', tt);
t_is(r.results.Rpp(:,tt), s.rdc.reserve.qty.Rp_pos, 4, t);

t = sprintf('(t=%d) downward contingency reserve quantities', tt);
t_is(r.results.Rpm(:,tt), s.rdc.reserve.qty.Rp_neg, 4, t);

t = sprintf('(t=%d) upward contingency reserve prices', tt);
t_is(r.results.RppPrices(:,tt)/r.StepProb(tt), s.rdc.reserve.prc.Rp_pos, 6, t);

t = sprintf('(t=%d) downward contingency reserve prices', tt);
t_is(r.results.RpmPrices(:,tt)/r.StepProb(tt), s.rdc.reserve.prc.Rp_neg, 6, t);

t = sprintf('(t=%d) contingency physical ramp price', tt);
[vv, ll] = r.om.get_idx();
Ramp_P_max = zeros(ng, nc);
sum_muPmax = zeros(ng, 1);
sum_muPmin = zeros(ng, 1);
for k = 1:nc+1
    ii = find(r.flow(tt,1,k).mpc.gen(:, GEN_STATUS) > 0);
    if k > 1
        Ramp_P_max(ii,k-1) = (r.QP.lambda.mu_u(ll.i1.rampcont(tt,1,k):ll.iN.rampcont(tt,1,k)) - r.QP.lambda.mu_l(ll.i1.rampcont(tt,1,k):ll.iN.rampcont(tt,1,k))) / mpc.baseMVA;
    end
    sum_muPmax(ii) = sum_muPmax(ii) + r.flow(tt,1,k).mpc.gen(ii, MU_PMAX);
    sum_muPmin(ii) = sum_muPmin(ii) + r.flow(tt,1,k).mpc.gen(ii, MU_PMIN);
end
t_is(Ramp_P_max/r.StepProb(tt), s.rdc.energy.mu.Ramp_P_max, 6, t);

t = sprintf('(t=%d) sum_muPmax', tt);
t_is(sum_muPmax/r.StepProb(tt), s.rdc.energy.sum_muPmax, 2, t);

t = sprintf('(t=%d) sum_muPmin', tt);
t_is(sum_muPmin/r.StepProb(tt), s.rdc.energy.sum_muPmin, 2, t);

t = sprintf('(t=%d) Rpmax_pos', tt);
Rpmax_pos = (r.QP.lambda.upper(vv.i1.Rpp(1):vv.iN.Rpp(1)) - r.QP.lambda.lower(vv.i1.Rpp(1):vv.iN.Rpp(1))) / mpc.baseMVA;
t_is(Rpmax_pos, s.rdc.reserve.mu.Rpmax_pos, 6, t);

t = sprintf('(t=%d) Rpmax_neg', tt);
Rpmax_neg = (r.QP.lambda.upper(vv.i1.Rpm(1):vv.iN.Rpm(1)) - r.QP.lambda.lower(vv.i1.Rpm(1):vv.iN.Rpm(1))) / mpc.baseMVA;
t_is(Rpmax_neg, s.rdc.reserve.mu.Rpmax_neg, 6, t);

end

% g1 = s.rdc.base.gen(:, PG);
% g2 = r.flow(1,1,1).mpc.gen(:, PG);
% for k = 1:nc
%     g1 = [ g1 s.rdc.cont(k).gen(:, PG) ];
%     g2 = [ g2 r.flow(1,1,k+1).mpc.gen(:, PG) ];
% end
% [m,n] = size(g1);
% for j = 1:n
%     fprintf('\n');
%     for i = 1:m
%         fprintf('%9.2f  %9.2f\n', g1(i,j), g2(i,j));
%     end
% end

%%-----  do AC run (most)  -----
%mostac;

%% turn warnings back on
if have_feature('octave')
    warning(s.state, 'Octave:nearly-singular-matrix');
else
    warning(s7.state, 'MATLAB:nearlySingularMatrix');
    warning(s6.state, 'MATLAB:nearlySingularMatrixUMFPACK');
end

t_end;

if nargout
    result = r;
end


% [psi] = dai_readfg (filename)
%
%    INPUT:  filename   = filename of a .fg file
%
%    OUTPUT: psi        = linear cell array containing the factors
%                         (psi{i} is a structure with a Member field
%                         and a P field, like a CPTAB).


function scr = read_mat(infilename)
% Creates a Scores object from the information in a mat file.
% Inputs:
%   infilename: A mat file containing scores.
% Outputs:
%   scr: A Scores object encoding the scores in the input mat
%     file.

assert(nargin==1)
assert(isa(infilename,'char'))

load(infilename,'scr');
scr = Scores(scr);

assert(scr.validate())


function val = IRget(options,name,value,flag)
%IRget Get options for IR Tools functions
%
% val = IRget(options,'name',value,flag)
%
% val = IRget(options,'name')
%   extracts the value of the named parameter from the options structure,
%   returning an empty matrix if the parameter value is not specified in
%   options.  It is sufficient to type only the leading characters that
%   uniquely identify the parameter, and case is ignored for parameter names.
%   [] is a valid options argument.
%
% val = IRget(options,'name',value)
%   extracts the named parameter as above, but returns VALUE if the named
%   parameter is not specified in options.
%
% val = IRget(options,'name',value,flag)
%   with flag = 'fast' no error checking is performed.
%
% See also: IRset, PRget, PRset

% Silvia Gazzola, University of Bath
% Per Christian Hansen, Technical University of Denmark
% James G. Nagy, Emory University
% April, 2018.

% This file is part of the IR Tools package and is distributed under the
% 3-Clause BSD Licence. A separate license file should be provided as part
% of the package.

% Fast access with no error checking.
if (nargin == 4) && isequal(flag,'fast')
    val = IRgetfast(options,name,value);
    return
end

if nargin < 2
    error('Not enough input arguments.');
end
if nargin < 3
    value = [];
end

if ~isempty(options) && ~isa(options,'struct')
    error('First argument must be an options structure created with IRset.');
end

if isempty(options)
    val = value;
    return;
end
allfields = IRoption_fields;

Names = allfields;

name = deblank(name(:)'); % Force this to be a row vector.
j = find(strncmpi(name,Names,length(name)));
if isempty(j)             % If no matches.
    error(['Unrecognized property name ''%s''.  ' ...
           'See IRset for possibilities.'], name);
elseif length(j) > 1      % If more than one match.
    % Check for any exact matches (in case any names are subsets of others).
    k = find(strcmpi(name,Names));
    if length(k) == 1
        j = k;
    else
        error('Ambiguous property name ''%s'' ', name);
    end
end

if any(strcmp(Names,Names{j,:}))
    val = options.(Names{j,:});
    if isempty(val)
        val = value;
    end
else
    val = value;
end

%------------------------------------------------------------------
function value = IRgetfast(options,name,defaultopt)
%IRGETFAST- Get IR OPTIONS parameter with no error checking.
%   VAL = IRGETFAST(OPTIONS,FIELDNAME,DEFAULTOPTIONS) will get the
%   value of the FIELDNAME from OPTIONS with no error checking or
%   fieldname completion. If the value is [], it gets the value of the
%   FIELDNAME from DEFAULTOPTIONS, another OPTIONS structure which is
%   probably a subset of the options in OPTIONS.

if isempty(options)
     value = defaultopt.(name);
     return;
end
% We need to know if name is a valid field of options, but it is faster
% to use a try-catch than to test if the field exists and if the field name
% is correct.
try
    value = options.(name);
catch
    value = [];
end

if isempty(value)
    value = defaultopt.(name);
end


function exp = exp_releasehold(exp)
% Peel off a layer of hold expressions from some expression.
% [Out-Expression] = exp_releasehold(In-Expression)
%
% In:
%   In-Expression      : some expression
%
% Out:
%   Out-Expression     : In-Expression with the first level of Hold's peeled off
%
% Notes:
%   Descends into cell arrays.
%
% See also:
%   exp_hold
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2010-05-19

if ~exp_beginfun('symbolic') return; end

exp = utl_releasehold(exp);

exp_endfun;


matlabbatch{1}.spm.tools.physio.save_dir = {'physio_out'};
matlabbatch{1}.spm.tools.physio.log_files.vendor = 'Siemens';
matlabbatch{1}.spm.tools.physio.log_files.cardiac = {'siemens_PAV.ecg'};
matlabbatch{1}.spm.tools.physio.log_files.respiration = {''};
matlabbatch{1}.spm.tools.physio.log_files.scan_timing = {''};
matlabbatch{1}.spm.tools.physio.log_files.sampling_interval = 0.0025;
matlabbatch{1}.spm.tools.physio.log_files.relative_start_acquisition = 0;
matlabbatch{1}.spm.tools.physio.log_files.align_scan = 'last';
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.Nslices = 20;
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.NslicesPerBeat = [];
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.TR = 2.41;
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.Ndummies = 5;
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.Nscans = 400;
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.onset_slice = 11;
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.time_slice_to_slice = [];
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.Nprep = [];
matlabbatch{1}.spm.tools.physio.scan_timing.sync.nominal = struct([]);
matlabbatch{1}.spm.tools.physio.preproc.cardiac.modality = 'ECG';
matlabbatch{1}.spm.tools.physio.preproc.cardiac.filter.no = struct([]);
matlabbatch{1}.spm.tools.physio.preproc.cardiac.initial_cpulse_select.auto_matched.min = 0.4;
matlabbatch{1}.spm.tools.physio.preproc.cardiac.initial_cpulse_select.auto_matched.file = 'initial_cpulse_kRpeakfile.mat';
matlabbatch{1}.spm.tools.physio.preproc.cardiac.initial_cpulse_select.auto_matched.max_heart_rate_bpm = 90;
matlabbatch{1}.spm.tools.physio.preproc.cardiac.posthoc_cpulse_select.off = struct([]);
matlabbatch{1}.spm.tools.physio.preproc.respiratory.filter.passband = [0.01 2];
matlabbatch{1}.spm.tools.physio.preproc.respiratory.despike = false;
matlabbatch{1}.spm.tools.physio.model.output_multiple_regressors = 'multiple_regressors.txt';
matlabbatch{1}.spm.tools.physio.model.output_physio = 'physio.mat';
matlabbatch{1}.spm.tools.physio.model.orthogonalise = 'none';
matlabbatch{1}.spm.tools.physio.model.censor_unreliable_recording_intervals = false;
matlabbatch{1}.spm.tools.physio.model.retroicor.yes.order.c = 3;
matlabbatch{1}.spm.tools.physio.model.retroicor.yes.order.r = 4;
matlabbatch{1}.spm.tools.physio.model.retroicor.yes.order.cr = 1;
matlabbatch{1}.spm.tools.physio.model.rvt.no = struct([]);
matlabbatch{1}.spm.tools.physio.model.hrv.no = struct([]);
matlabbatch{1}.spm.tools.physio.model.noise_rois.no = struct([]);
matlabbatch{1}.spm.tools.physio.model.movement.no = struct([]);
matlabbatch{1}.spm.tools.physio.model.other.no = struct([]);
matlabbatch{1}.spm.tools.physio.verbose.level = 2;
matlabbatch{1}.spm.tools.physio.verbose.fig_output_file = 'physio.fig';
matlabbatch{1}.spm.tools.physio.verbose.use_tabs = false;