%{
B_LoopDeLoopCam.m

Animate several camera motions around a surface.

Matt Sheen, mws262@cornell.edu
%}

close all; clear all;
fig = figure;

%% Compound Patch - same from folder 2, example b
pX = [-1 1 0;
    0 0 0]';
pY = [-1/3 -1/3 2/3;
    -1/3 -1/3 2/3]';
pZ = [0 0 0;
    0 0.5 0]';

p1 = patch(pX,pY,pZ,'red');
p1.FaceAlpha = 0.5;

OrigVerts = p1.Vertices;

%% Set initial camera position.
axis(2*[-10 10 -10 10 -10 10])
campos([8,8,8]);
camtarget([0,0,0]);
camva(40);

%Turning the axis grid on to help get perspective of movement
fig.Children.ZGrid = 'on';
fig.Children.YGrid = 'on';
fig.Children.XGrid = 'on';

vel = 0.1*[0 1 0];
rot = angle2dcm(0,0,-0.02);
dt = 0.5;
center = [0 0 0];

totalRot = eye(3,3);

%% Cam mode 1: fixed everything. Camera stays exactly the same throughout.
input('Press enter to see default camera orientation.');
for i = 1:1000
    %Moving the plane is the same as previous example
    totalRot = totalRot*rot;
    center = dt*(totalRot*vel')' + center; %transform the velocity, keep track of the center position.
    p1.Vertices = (totalRot*OrigVerts')' + repmat(center,[size(OrigVerts,1),1]); %Rotate the patch object about its center and add new center point.

    pause(0.01);
end

%% Cam mode 2: let's follow the plane. Camera keeps the plane in the center of view, but does not change orientation.
input('Press enter to see plane-centering camera.');
for i = 1:1000
    %Moving the plane is the same as previous example
    totalRot = totalRot*rot;
    center = dt*(totalRot*vel')' + center; %transform the velocity, keep track of the center position.
    p1.Vertices = (totalRot*OrigVerts')' + repmat(center,[size(OrigVerts,1),1]); %Rotate the patch object about its center and add new center point.

    %CAMERA CHANGES:
    camtarget(center); %make the target be the center of the plane.
    campos(center+[5,5,5]); %make the camera position be a fixed offset from the center of the plane.
    pause(0.01);
end

%% Cam mode 3: let's fly the plane. Camera also changes orientation with the plane.
input('Press enter to see plane-following camera.');
for i = 1:1000
    %Moving the plane is the same as previous example
    totalRot = totalRot*rot;
    center = dt*(totalRot*vel')' + center; %transform the velocity, keep track of the center position.
    p1.Vertices = (totalRot*OrigVerts')' + repmat(center,[size(OrigVerts,1),1]); %Rotate the patch object about its center and add new center point.

    %CAMERA CHANGES:
    camtarget(center); %Camera target is the center of the plane.
    campos(center+5*(totalRot*[0.5 -1 0.5]')'); %Camera position is a little behind, up, and to the right of the plane (helps see what's going on). Note that we have to transform the camera offset from plane frame to world frame.
    camup(totalRot*[0 0 1]'); % The camera should think "up" is the up vector of the plane. So we take the plane's up and transform it into the world frame.

    pause(0.01);
end


% t_meshEdit
% Script (tutorial) to create, edit and visualize a mesh.
%
% See also T_MESHCREATE, MRGSAVECLASSWITHGRAY.
%
% Stanford VISTA
%

%% See t_meshCreate for a little more on creating meshes
dataD = mrvDataRootPath;
fName = fullfile(dataD,'anatomy','anatomyNIFTI','t1_class.nii.gz');

% Run the build code
msh = meshBuildFromClass(fName,[],'left');
msh = meshSmooth(msh);
msh = meshColor(msh);

% Visualize the coarse, unshaded mesh
meshVisualize(msh);

%% Set up parameters, smooth and visualize the mesh
msh = meshSet(msh,'smooth_relaxation',1);
msh = meshSet(msh,'smooth_sinc_method',0);
msh = meshSet(msh,'smooth_iterations',200);
msh2 = meshSmooth(msh);
meshVisualize(msh2);

%% Shade the mesh using local curvature
msh3 = meshColor(msh2,[],.25);

% Visualize the mesh smoothed and colored with the curvature
meshID = 2;
meshVisualize(msh3,meshID);

%% Now, visualize a mesh with some gray matter added to it
% We will add two gray layers
nLayers = 2;

% We use mrgGrowGray to read the WM and create new nodes/edges and white
% matter class data.
[nodes,edges,classData] = mrgGrowGray(fName,nLayers);

% mrgDisplayGrayMatter(nodes,edges,80,[120 140 120 140]);

% Add the gray matter to the white matter prior to creating the mesh.
wm = uint8( (classData.data == classData.type.white) ...
    | (classData.data == classData.type.gray) );

% We should add to meshBuildFromClass function an argument that specifies
% how many gray layers to add.  Then we could skip this step and just start
% below.

%% Now do the same sequence as above
mmPerVox = 0.7*[1,1,1];
msh4 = meshBuildFromClass(wm,mmPerVox);
msh4 = meshSmooth(msh4);
msh4 = meshColor(msh4);
meshVisualize(msh4,2);

%% END


function varargout = ensureManifoldMesh(varargin)
%ENSUREMANIFOLDMESH Apply several simplification to obtain a manifold mesh.
%
%   Try to transform an input mesh into a manifold mesh.
%
%   Not all cases of "non-manifoldity" are checked, so please use with
%   care.
%
%   [V2, F2] = ensureManifoldMesh(V, F);
%   [V2, F2] = ensureManifoldMesh(MESH);
%   MESH2 = ensureManifoldMesh(...);
%
%   Example
%   ensureManifoldMesh
%
%   See also
%    meshes3d, isManifoldMesh

% ------
% Author: David Legland
% E-mail: david.legland@inra.fr
% Created: 2019-02-01, using Matlab 9.5.0.944444 (R2018b)
% Copyright 2019-2022 INRA - Cepia Software Platform

%% Parse input arguments

[vertices, faces] = parseMeshData(varargin{:});
verbose = true;

%% Pre-processing

% remove duplicate faces if any
if verbose
    disp('remove duplicate faces');
end
faces = removeDuplicateFaces(faces);

%% Iterative processing of multiple edges
% Reduces all edges connected to more than two faces, by collapsing second
% vertex onto the first one.

% iter = 0;
% while ~isManifoldMesh(vertices, faces) && iter < 10
%     iter = iter + 1;
    if verbose
        disp('collapse edges with many faces');
    end

    [vertices, faces] = collapseEdgesWithManyFaces(vertices, faces);
% end

%% Format output

varargout = formatMeshOutput(nargout, vertices, faces);


function positions = getFigurePositions(tile, screenBorder)
    numRows   = tile(1);
    numCols   = tile(2);
    figBorder = [20, 60];

    screenSize = get(0,'screensize'); % Determine terminal size in pixels

    % Adjust to actual visible screen size
    screenSize(3:4) = screenSize(3:4) - (nargin == 2) * 2 * screenBorder;

    % Set figure width and height with border
    figWidth  = fix(screenSize(3)/numCols);
    figHeight = fix(screenSize(4)/numRows);

    % Calculate horizontal and vertical position for each figure
    horPos = screenSize(3) - (numCols:-1:1)*figWidth  + figBorder(1);
    verPos = screenSize(4) - (1:numRows)*figHeight    + figBorder(2);
    horPosAll = repmat(horPos', [numRows, 1]);
    verPosAll = repmat(verPos,  [numCols, 1]);

    % Return position
    positions = zeros(prod(tile), 4);
    positions(:,1) = horPosAll;
    positions(:,2) = verPosAll(:);
    positions(:,3) = figWidth  - 2 * figBorder(1);
    positions(:,4) = figHeight - 2 * figBorder(2);
end


 % Right Stance Domain
 %
 % Contact: Right Toe
function domain = DoubleStance(model, load_path)
    % construct the right stance domain of Cassie
    %
    % Parameters:
    % model: the right body model of Cassie robot

    %% first make a copy of the robot model
    %| @note Do not directly assign with the model variable, since it is a
    %handle object.
    domain = copy(model);
    % set the name of the new copy
    domain.setName('DoubleStance');

    if nargin < 2
        load_path = [];
    end

    %% Add contact
    % left foot point contact
    [right_foot, fric_coef,geometry] = sys.frames.RightSole(model);
    right_foot_contact = ToContactFrame(right_foot,...
        'PlanarContactWithFriction');
    domain = addContact(domain,right_foot_contact,fric_coef,geometry,load_path);

    [left_foot, fric_coef,geometry] = sys.frames.LeftSole(model);
    left_foot_contact = ToContactFrame(left_foot,...
        'PlanarContactWithFriction');
    domain = addContact(domain,left_foot_contact,fric_coef,geometry,load_path);

    %% Add event
    % the force on the left sole
    fLeftSole = domain.Inputs.ConstraintWrench.fLeftSole;
    left_lift = UnilateralConstraint(domain,fLeftSole(3),'leftFootLift','fLeftSole');
    domain = addEvent(domain, left_lift);

    fRightSole = domain.Inputs.ConstraintWrench.fRightSole;
    right_lift = UnilateralConstraint(domain,fRightSole(3),'rightFootLift','fRightSole');
    domain = addEvent(domain, right_lift);

    %% Add Virtual Constraints
    %     x = domain.States.x;
    %     dx = domain.States.dx;

    % phase variable: linearized hip position
    %     r_hip_link = domain.Links(getLinkIndices(domain, 'l_uleg'));
    %     r_hip_frame = r_hip_link.Reference;
    %     r_hip_frame = domain.Joints(getJointIndices(domain,'r_leg_hpy'));
    %     r_ankle_frame = domain.Joints(getJointIndices(domain,'r_leg_aky'));
    %     p_rhp = getCartesianPosition(domain, r_hip_frame);
    %     p_rak = getCartesianPosition(domain, r_ankle_frame);
    %     % p_sf = getCartesianPosition(domain, domain.ContactPoints.RightSole);
    %
    %
    %     p_hip = p_rhp(1) - p_rak(1);
    %     deltaPhip = linearize(p_hip,x);

    % @state based phase variable
    %     p = SymVariable('p',[2,1]);
    %     tau = (deltaPhip-p(2))/(p(1)-p(2));

    % @time based phase variable
    %     t = SymVariable('t');
    %     p = SymVariable('p',[2,1]);
    %     tau = (t-p(1))/(p(2)-p(1));
    %
    %
    %
    %     % relative degree two outputs:
    %     y_rap = x('r_leg_aky');
    %     y_rar = x('r_leg_akx');
    %     y_rkp = x('r_leg_kny');
    %     y_rtp = -x('r_leg_aky') - x('r_leg_kny') - x('r_leg_hpy');
    %     y_rtr = -x('r_leg_akx') - x('r_leg_hpx');
    %     y_rhy = x('r_leg_hpz');
    %     y_lkp = x('l_leg_kny');
    %     y_llr = x('r_leg_hpx') - x('l_leg_hpx');
    %
    %     l_hip_frame = domain.Joints(getJointIndices(domain,'l_leg_hpy'));
    %     l_ankle_frame = domain.Joints(getJointIndices(domain,'l_leg_aky'));
    %     p_lhp = getCartesianPosition(domain, l_hip_frame);
    %     p_lak = getCartesianPosition(domain, l_ankle_frame);
    %     % p_lak = getCartesianPosition(domain, l_ankle_frame);
    %     nsl = (p_lak(1) - p_lhp(1))/(p_lak(3) - p_lhp(3));
    %     y_nsl = linearize(nsl,x);
    %
    %
    %     left_sole_inside = sys.frames.LeftSoleInside(model);
    %     left_sole_outside = sys.frames.LeftSoleOutside(model);
    %     left_toe = sys.frames.LeftToe(model);
    %     left_heel = sys.frames.LeftHeel(model);
    %     p_lsi = getCartesianPosition(domain, left_sole_inside);
    %     p_lso = getCartesianPosition(domain, left_sole_outside);
    %     p_ltoe = getCartesianPosition(domain, left_toe);
    %     p_lheel = getCartesianPosition(domain, left_heel);
    %
    %     y_lfr = p_lsi(3) - p_lso(3);
    %     y_lfp = p_lheel(3) - p_ltoe(3);
    %     y_lfy = p_lheel(2) - p_ltoe(2);
    %
    %     ya_2 = [y_rap;
    %         y_rar;
    %         y_rkp;
    %         y_rtp;
    %         y_rtr;
    %         y_rhy;
    %         y_lkp;
    %         y_nsl;
    %         y_llr;
    %         y_lfr;
    %         y_lfp;
    %         y_lfy];
    %
    %     % optional
    %     y2_label = {'RightAnklePitch',...
    %         'RightAnkleRoll',...
    %         'RightKneePitch',...
    %         'RightTorsoPitch',...
    %         'RightTorsoRoll',...
    %         'RightHipYaw',...
    %         'LeftKneePitch',...
    %         'LeftLinNSlopeWithBase',...
    %         'LeftLegRoll',...
    %         'LeftFootCartX',...
    %         'LeftFootCartY',...
    %         'LeftFootCartZ'};
    %
    %     y2 = VirtualConstraint(domain,ya_2,'position','DesiredType','Bezier','PolyDegree',5,...
    %         'RelativeDegree',2,'OutputLabel',{y2_label},'PhaseType','TimeBased',...
    %         'PhaseVariable',tau,'PhaseParams',p,'Holonomic',true,'LoadPath',load_path);
    %
    %
    %     domain = addVirtualConstraint(domain,y2);
end


function [dag, best_score, cache] = learn_struct_gs2(data, nodesizes, seeddag, varargin)
%
% LEARN_STRUCT_GS2(data,seeddag) learns a structure of Bayesian net by Greedy Search.
% dag = learn_struct_gs(data, nodesizes, seeddag)
%
% dag: the final structure matrix
% Data : training data, data(i,m) is the m obsevation of node i
% Nodesizes: the size array of different nodes
% seeddag: given seed Dag for hill climbing, optional
% cache : data structure used to memorize local score computations
%   (cf. SCORE_INIT_CACHE function)
%
% by Gang Li @ Deakin University (gli73@hotmail.com)
% (use mk_nbrs_of_dag_topo, developped by Wei Hu, instead of mk_nbrs_of_dag)
% (Caching implementation : ofrancois.olivier.c.h@gmail.com, philippe.leray@univ-nantes.fr)
%

[N ncases] = size(data);
if (nargin < 3 )
    seeddag = zeros(N,N); % mk_rnd_dag(N); %call BNT function
elseif ~acyclic(seeddag)
    seeddag = mk_rnd_dag(N); %zeros(N,N);
end;

% set default params
scoring_fn = 'bic';
verbose  = 'yes';
cache=[];

% get params
args = varargin;
nargs = length(args);
if length(args) > 0
    if isstr(args{1})
    	for i = 1:2:nargs
    		switch args{i}
    		case 'scoring_fn', scoring_fn = args{i+1};
    		case 'verbose',  verbose  = strcmp(args{i+1},'yes');
    		case 'cache',  cache=args{i+1} ;
    		end;
    	end;
    end;
end;

done = 0;
[best_score cache] = score_dags(data,nodesizes, {seeddag},'scoring_fn',scoring_fn,'cache',cache);
while ~done
    [dags,op,nodes] = mk_nbrs_of_dag_topo(seeddag);
    nbrs = length(dags);
    [scores cache] = score_dags(data, nodesizes, dags,'scoring_fn',scoring_fn,'cache',cache);
    max_score = max(scores);
    new = find(scores == max_score );
    if ~isempty(new) & (max_score > best_score)
        p = sample_discrete(normalise(ones(1, length(new))));
        best_score = max_score;
        seeddag = dags{new(p)};
    else
        done = 1;
    end;
end;

dag = seeddag;

outcount = 0;
[best_score cache] = score_dags(data,nodesizes, {seeddag},'scoring_fn',scoring_fn,'cache',cache);
while outcount < 2
    innercount = 0;
    for i=1:N
        for j=1:N
           if i==j, continue;    end;
           if seeddag(i,j) == 0  % No edge i-->j, then try to add it
               tempdag = seeddag;
               tempdag(i,j) = 1;
               if acyclic(tempdag)
                    [temp_score cache] = score_dags(data,nodesizes, {tempdag},'scoring_fn',scoring_fn,'cache',cache);
                    if temp_score > best_score
                        seeddag = tempdag
                        best_score= temp_score;
                        innercount = innercount +1;
                    end;
               end
           else  % exists edge i--j, then try reverse it or remove it
               tempdag = seeddag;
               tempdag(i,j) = 0; tempdag(j,i) = 1;
               if acyclic(tempdag)
                   [temp_score cache] = score_dags(data,nodesizes, {tempdag},'scoring_fn',scoring_fn,'cache',cache);
                   if temp_score > best_score
                       seeddag = tempdag;
                       best_score = temp_score;
                       innercount = innercount +1;
                   else
                       tempdag = seeddag;
                       tempdag(i,j) = 0;
                       [temp_score cache] = score_dags(data,nodesizes, {tempdag},'scoring_fn',scoring_fn,'cache',cache);
                       if temp_score > best_score
                           seeddag = tempdag;
                           best_score= temp_score;
                           innercount = innercount +1;
                       end;
                   end;
               else
                   tempdag = seeddag;
                   tempdag(i,j)=0;
                   [temp_score cache] = score_dags(data,nodesizes, {tempdag},'scoring_fn',scoring_fn,'cache',cache);
                   if temp_score > best_score
                       seeddag = tempdag
                       best_score= temp_score;
                       innercount = innercount +1;
                   end;
               end;
           end;
        end; % end for j
    end; % end for i
    if innercount == 0
        outcount = outcount +1;
    end;
end;  % end while

dag = seeddag;


function f = fix(f)
%FIX   Round a CLASSICFUN pointwise toward zero.
%   G = FIX(F) returns the CLASSICFUN G such that G(x) = FIX(F(x)) for each x in
%   F.domain.
%
%   If F is complex, then the G = FIX(REAL(F)) + 1i*FIX(IMAG(F)).
%
%   Note that FIX() assumes the output G(X) is a constant. If it is not, then
%   garbage is returned with no warning.
%
% See also ROUND, CEIL, FLOOR.

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

f.onefun = fix(f.onefun);

end


% Matlab Toolbox for Dimensionality Reduction
% Version 0.8 18-APR-2012
%
%
%Main functions
%----------------------
% compute_mapping    Performs dimension reduction using the specified technique
% out_of_sample      Performs out-of-sample extension using trained DR technique
% out_of_sample_est  Performs out-of-sample extension by approximation
% reconstruct_data   Reconstruct data from low-dimensional representation
% intrinsic_dim      Estimates intrinsic dimensionality of the data
%
%Helper functions
%----------------------
% drgui              Shows a GUI that facilitates access to all functions
% generate_data      Generates artificial data manifolds
% prewhiten          Performs whitening of a data set
%
%Installation functions
%----------------------
% mexall             Compiles all C++ code in the toolbox
% test_toolbox       Tests all functionalities of the toolbox
%

% This file is part of the Matlab Toolbox for Dimensionality Reduction.
% The toolbox can be obtained from http://homepage.tudelft.nl/19j49
% You are free to use, change, or redistribute this code in any way you
% want for non-commercial purposes. However, it is appreciated if you
% maintain the name of the original author.
%
% (C) Laurens van der Maaten, Delft University of Technology


function varargout = time_response_localwfs_sbl(X,xs,src,conf)
%TIME_RESPONSE_LOCALWFS_SBL time response for local WFS
%
%   Usage: [s,t] = time_response_localwfs_sbl(X,xs,src,conf)
%
%   Input parameters:
%       X           - listener position / m
%       xs          - position of virtual source / m
%       src         - source type of the virtual source
%                         'pw' -plane wave
%                         'ps' - point source
%                         'fs' - focused source
%       conf        - configuration struct (see SFS_config)
%
%   Output parameters:
%       s           - simulated time response
%       t           - corresponding time axis / s
%
%   TIME_RESPONSE_LOCALWFS_SBL(X,xs,src,conf) simulates the impulse response of
%   a source synthesized by local WFS using spatial bandwidth limitation at the
%   given virtual microphone position X.
%   The length in samples of the impulse response is given by conf.N. The
%   actual calculation is done via sound_field_imp() and a loop over time t. A
%   similar result can be achieved by using ir_localwfs() in combination with
%   dummy_irs().
%
%   See also: ir_localwfs, sound_field_imp, freq_response_localwfs_vss

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

%% ===== Checking of input  parameters ==================================
nargmin = 4;
nargmax = 4;
narginchk(nargmin,nargmax);
isargposition(X);
isargxs(xs);
isargchar(src);
isargstruct(conf);

%% ===== Configuration ==================================================
fs = conf.fs;
N = conf.N;
showprogress = conf.showprogress;
useplot = conf.plot.useplot;
% Select secondary source type
if strcmp('2D',conf.dimension)
    greens_function = 'ls';
else
    greens_function = 'ps';
end

%% ===== Computation ====================================================
% Disable progress bar and plotting for sound_field_imp()
conf.showprogress = false;
conf.plot.useplot = false;
% Get the position of the loudspeakers
x0 = secondary_source_positions(conf);
x0 = secondary_source_selection(x0,xs,src);
x0 = secondary_source_tapering(x0,conf);
% Generate time axis
t = (0:N-1)'/fs;
s = zeros(1,length(t));
d = driving_function_imp_localwfs_vss(x0,xs,src,conf);
for ii = 1:length(t)
    if showprogress, progress_bar(ii,length(t)); end
    % Calculate sound field at the listener position
    p = sound_field_imp(X(1),X(2),X(3),x0,greens_function,d,t(ii),conf);
    s(ii) = real(p);
end

% Return parameter
if nargout>0, varargout{1}=s; end
if nargout>1, varargout{2}=t; end

%% ===== Plotting ========================================================
if nargout==0 || useplot
    figure;
    figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit);
    plot(t*1000,s);
    ylabel('amplitude');
    xlabel('time / ms');
end


%kktextu 'Compute "texture" extracted from the surface surroundings '
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros ktextu.pane file
%
% Parameters:
% InputFile: i1 '3D Data', required: 'Input scene (gray or binary scene)'
% InputFile: i2 'Coordinates', required: 'Coordinates at z-buffer distance (surface)'
% OutputFile: o '"Texture"', required: '"Texture" information which can be incorporated on shading'
% Double: step 'increment step', default: 1: 'Increment step during "texture" computation'
% Toggle: ave_type 'average value', default: 0: 'Meaning of "texture" is the average of voxel values'
% Toggle: wei_type 'weighted average value', default: 0: 'Meaning of "texture" is the weighted average of voxel values'
% Toggle: max_type 'maximum value', default: 0: 'Meaning of "texture" is the maximum voxel value'
% Toggle: min_type 'minimum value', default: 0: 'Meaning of "texture" is the minimum voxel value'
% Toggle: thi_type 'thickness (specify threshold)', default: 0: 'Meaning of "texture" is the length traced while below threshold'
% Toggle: norm_dir 'normal direction', default: 0: 'Follows the normal direction to extract "texture" information'
% InputFile: i3 'Normal Vectors', optional: 'Surface normal vectors'
% Toggle: view_dir 'view direction', default: 0: 'follows the viewer (projection) direction to extract "texture" information'
% Double: alpha 'alpha', default: 0: 'View plane rotation angle around Z axis'
% Double: beta 'beta ', default: 0: 'View plane rotation angle around X axis'
% Double: out_range 'outside surface', default: 0: 'Length of the region outside the surface where to compute "texture"'
% Double: in_range 'inside surface ', default: 10: 'Length of the region inside the surface where to compute "texture"'
% Double: thres_range 'threshold >=', default: 0: 'Threshold value which determines the region inside the surface where to compute "texture"'
%
% Example: o = kktextu({i1, i2, i3}, {'i1','';'i2','';'o','';'step',1;'ave_type',0;'wei_type',0;'max_type',0;'min_type',0;'thi_type',0;'norm_dir',0;'i3','';'view_dir',0;'alpha',0;'beta',0;'out_range',0;'in_range',10;'thres_range',0})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% ktextu - Compute texture information for each point lying on the visible surface
%
%  DESCRIPTION
%
% creates an image file based on volumetric information of a 3D object. This
% information can be of several types and is called here TEXTURE. It can can be
% obtained specifying the walk direction, the range of walking around the object
% surface and the type of texture. The output image is of type KFLOAT.
%
% This operator requires as inputs the volume (3D object) file, and the
% coordinate file, which is an object w x h x 1 x 1 x 3
% that can be generated optionally by the operator kzbuff, containing the
% coordinates X, Y and Z of each point of the object surface.
%
% The "ktextu" simulates that, for each point of the object's surface,
% there is a
% ray going inside the object in the specified direction. Then it walks (visits
% voxels) in that ray in the given range and gets the information according
% to the texture type.
%
% There are two options for the direction of "texture" extraction: Normal
% direction, which
% corresponds to the directions of the normal vectors to the object's surface,
% and View direction, which corresponds to the view direction of the z-buffer.
% The first option requires the input file of normal vectors, which is an
% object w x h x 1 x 1 x 3 that can be generated optionally by the operators
% kvsnorm or kisnorm,
% containing the X, Y and Z components of the vectors, stored with inverted
% signals (vectors pointing to inside the object).  The second option requires
% the angles alpha and beta, used to obtain the z-buffer.
%
% There are two options for the range of "texture" extraction: along a region
% around the
% surface, specified as how many steps to walk backwards (outside the object)
% and forwards (inside the object); and
% along the thickness, which is determined by the specified threshold. The
% later option requires the direction of "texture" extraction to be the normal
% direction.
%
% The increment step can be specified and represents the sampling step while
% extracting the "texture". An increment step equal to 1 visits the voxels one
% by one.
%
% There are five types of texture: 1) the voxels' average value, 2) the voxels'
% weighted average value, 3) the voxels' maximal value, 4) the voxels' minimal
% value and 5) the thickness.
%
% The first option calculates the average value of all the visited voxels. The
% second option is still not implemented. The third option calculates the
% maximal voxel value of all the visited voxels. The forth option calculates
% the minimal voxel value of all the visited voxels. Finally, the last option
% estimate the thickness of the surface based on the length of the ray within
% the object. This last option requires the direction of extraction to be the
% normal direction and the range of extraction to be given by the threshold.
%
% The images generated by "ktextu" are useful for analysis by themselves,
% or can be used as input to the operator
% kshad, to compose a shaded image based not only on the object surface form,
% but also on its volumetric structure information.
%
%
%
%  EXAMPLES
% ktextu -i1 volume.viff -i2 coord.viff -o texture.viff -step 1.0 -norm_dir
%        -i3 normal.viff -out_range 10.0 -in_range 10.0 -max_type
%
% This example will create a texture file texture.viff from the volume file
% volume.viff and the coordinate file coord.viff by walking 10 steps
% backwards (outside the object) and 10 steps forwards (inside the object)
% around the surface, in the normal direction
% (which is defined by the normal vector file normal.viff), with a sampling
% step
% equal to 1. The specified texture type is the voxels' maximal value.
%
% ktextu -i1 volume.viff -i2 coord.viff -o texture.viff -step 2.0 -view_dir
%        -alpha 90.0 -beta 15.0 -out_range 10.0 -in_range 10.0 -ave_type
%
% This example will create a texture file texture.viff from the volume file
% volume.viff and the coodinate file coord.viff by walking 10 steps
% backwards and 10 steps forwards around the surface, in the view direction
% (which is a plane rotated 90 degrees in alpha and 15 degrees in beta), with a
% sampling step equal to 2. The specified texture type is the voxels' average
% value.
%
% ktextu -i1 volume.viff -i2 coord.viff -o texture.viff -step 1.0 -norm_dir
%        -i3 normal.viff -thres 70 -thi_type
%
% This example will create a texture file texture.viff from the volume file
% volume.viff and the coodinate file coord.viff by walking
% in the normal direction (which is defined by the normal vector
% file normal.viff), with a sampling step equal to 1. The specified texture type is the thickness, while the threshold is less than 70.
%
%  "SEE ALSO"
% kzbuff, kshad, kisnorm, kvsnorm, kvoxext
%
%  RESTRICTIONS
% The input objects must have only the value segment.
%
% The
% input object scene can not have dimention e > 1. The input objects coord and
% norm must have dimention e=3.
%
% The input object scene can not be of data types KCOMPLEX and KDCOMPLEX. The
% input object coord can not be of data types KBIT, KFLOAT, KDOUBLE, KCOMPLEX
% and KDCOMPLEX. The input object scene can not be of data types KBIT, KCOMPLEX
% and KDCOMPLEX.
%
% The input objects coord and norm must match in their dimentions w and h.
%
% In case of t > 1 in the input objects, the operator will be applied to the time
% t=0 only.
%
% None of the input and output objects are referenced, therefore some attributes
% may change, as the VALUE_POSITION, for example.
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993, 1994, 1995 UNICAMP, R A Lotufo,  All rights reserved.
%

function varargout = kktextu(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kktextu(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i1', '__input';'i2', '__input';'o', '__output';'step', 1;'ave_type', 0;'wei_type', 0;'max_type', 0;'min_type', 0;'thi_type', 0;'norm_dir', 0;'i3', '__input';'view_dir', 0;'alpha', 0;'beta', 0;'out_range', 0;'in_range', 10;'thres_range', 0};
maxval={0,0,0,2,0,0,0,0,0,0,1,0,0,0,1,1,0};
minval={0,0,0,2,0,0,0,0,0,0,1,0,0,0,1,1,0};
istoggle=[0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1];
was_set=istoggle * 0;
paramtype={'InputFile','InputFile','OutputFile','Double','Toggle','Toggle','Toggle','Toggle','Toggle','Toggle','InputFile','Toggle','Double','Double','Double','Double','Double'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

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


function Tracks = Pops2Tracks(WolfPops, UAV)
%POPS2TRACKS 将狼群转换为航迹

SearchAgents = size(WolfPops.Pos, 1);          % 种群数量
UAVnum = UAV.num;                                      % 无人机个数
dim = UAV.PointDim;                                      % 仿真维度
v = WolfPops.Pos(:, end-UAVnum+1:end);   % 协同无人机速度
P = WolfPops.Pos(:, 1:end-UAVnum);            % 协同无人机航迹 xy

Tracks = cell(SearchAgents, 1);
for agent = 1 : SearchAgents
    a.V = v(agent, :)';
    P_a = P(agent, :);
    a.P = cell(UAVnum, 1);
    for i =1:UAVnum
        PointNum = UAV.PointNum(i);
        % 三维仿真这里得改 PointNum*dim
        P_ai = P_a(1 : PointNum*dim);
        P_ai = reshape(P_ai, dim, PointNum);
        P_a = P_a(PointNum*dim+1 : end);
        a.P(i) =  {P_ai};
    end
    Tracks(agent) = {a};
end

end


function h = mobile_text(varargin)
% MOBILE_TEXT('str1', 'str2', ...) places each string in a random position
% on the current axes.  The strings can be dragged around with the mouse.
% Returns handles to the text objects, for setting colors, etc.

strs = varargin;
n = length(strs);
ax = axis;
% random placement
x = rand(1,n)*(ax(2)-ax(1)) + ax(1);
y = rand(1,n)*(ax(4)-ax(3)) + ax(3);
h = [];
for i = 1:n
  h = [h text(x(i),y(i),strs{i})];
end
set(h,'ButtonDownFcn','move_obj(1)');
if nargout == 0
  clear h
end


% SetValueOfAssignment Sets the value of a variable assignment in a factor.
%
%   F = SetValueOfAssignment(F, A, v) sets the value of a variable assignment,
%   A, in factor F to v. The order of the variables in A are assumed to be the
%   same as the order in F.var.
%
%   F = SetValueOfAssignment(F, A, v, VO) sets the value of a variable
%   assignment, A, in factor F to v. The order of the variables in A are given
%   by the vector VO.
%
%   Note that SetValueOfAssignment *does not modify* the factor F that is
%   passed into the function, but instead returns a modified factor with the
%   new value(s) for the specified assignment(s). This is why we have to
%   reassign F to the result of SetValueOfAssignment in the code snippets
%   shown above.
%
%   See also GetValueOfAssignment.m and SampleFactors.m
%
% Copyright (C) Daphne Koller, Stanford University, 2012

function F = SetValueOfAssignment(F, A, v, VO)

if (nargin == 3),
    indx = AssignmentToIndex(A, F.card);
else
    map = zeros(length(F.var), 1);
    for i = 1:length(F.var),
        map(i) = find(VO == F.var(i));
    end;
    indx = AssignmentToIndex(A(map), F.card);
end;

F.val(indx) = v;

end


3     % problem
3     % cavity type
7     % grid parameter
1     % uniform/stretched grid
1     % discretisation
0.2   % viscosity parameter
1     % Picard/Newton/hybrid linearization
9     % number of Picard iterations
1.d-5 % nonlinear tolerance
2     % uniform/exponential streamlines

%% Data file for driven cavity


%% (Internal) GUI for inspecting and correcting timeseries
%
% Description:
% This function implements a graphical user interface (GUI) to correct annotations
% possibly previous performed by an automatic algorithm. The idea is to
% easily visualize, compare and correct annotations. For this purpose the
% GUI presents several representations of the time evolution of the events
% (possibly but not necessarily heartbeats).
%
% Arguments:
%
%     +ECG: [numeric or cell]
%
%           [numeric]: signal matrix of dimension [sig_length sig_size
%           repetitions_size] where:
%             - sig_length: time length in samples
%             - sig_size: number of ECG leads or number of signals.
%             - repetitions_size: number of repetitions of the same
%             signals. Typically used when time-synchronized events, like
%             heartbeats.
%
%           [cell]: cell array of length repetitions_size, where each cell
%           is (probably a time alligned event) a signal of dimension
%           [sig_length sig_size]
%
%     +QRS_locations: [numeric] OPTIONAL. Default values enclosed in ()
%                 Synchronization sample. In ECG context, this values are
%                 the QRS fiducial point. (empty)
%
%
%     +ECG_header: [struct] OPTIONAL.
%
%             Description of the ECG typically available in the
%             header. Structure with fields:
%
%               -freq: Sampling rate in Hz. (1)
%
%               -nsig: Number of ECG leads. (size(ECG,2))
%
%               -nsamp: Number of ECG samples. (size(ECG,1))
%
%               -adczero: ADC offset (e.g. 2^(adc_res-1) when
%               using unsigned integers). ( repmat(0, ECG_header.nsig , 1) )
%
%               -adcgain: ADC gain in units/adc_sample
%               (typically uV/adc_unit). ( repmat(1, ECG_header.nsig , 1) )
%
%               -units: Measurement units. ( repmat('uV', ECG_header.nsig , 1) )
%
%               -desc: Signal description. ( num2str(colvec(1:ECG_header.nsig)) )
%
%     +QRS_annotations: [cell] OPTIONAL. Default values enclosed in ()
%               Annotations to be included in the mosaic. The funcion
%               accepts 2 type of annotations: points and lines.
%
% Example:
%
%    https://www.youtube.com/watch?v=qgWjvsvafVg&list=PLlD2eDv5CIe9sA2atmnb-DX48FIRG46z7&index=3
%
% See also ECGtask_QRS_corrector
%
% Limits and Known bugs:
%   Probably a lot :( ... but dont panic! send me feedback if you need help.
%
% Author: Mariano Llamedo Soria (llamedom at frba.utn.edu.ar)
% Version: 0.1 beta
% Birthdate  : 16/08/2017
% Last update: 16/08/2017
% Copyright 2008-2017
%
function ts_out = timeseries_explorer(tsc_in)

    tsc_out

    %% Global variables

    fig_hdl = figure();

    title_efimero_hdl = [];

    %%

    set(fig_hdl, 'WindowButtonDownFcn', @WindowButtonDownCallback);
    set(fig_hdl, 'WindowButtonUpFcn',   @WindowButtonUpCallback);
    set(fig_hdl, 'WindowKeyPressFcn',   @WindowKeyPress);

    maximize(fig_hdl);
    maximized_size = get(fig_hdl, 'Position');

    set(fig_hdl, 'Position', [ maximized_size(3:4) maximized_size(3:4) ] .* [ 0.05 0.13 0.95 0.9] );

    set(fig_hdl,'CloseRequestFcn',@my_closefcn)

    user_data.RRserie = colvec(diff(user_data.anns_under_edition));
    user_data.RRserie = [user_data.RRserie(1); user_data.RRserie] * 1/user_data.ECG_struct.header.freq;

    limits = prctile(user_data.RRserie, [5 95]);

    if(limits(1) > 0)
        limits(1) = limits(1) * 0.9;
    else
        limits(1) = limits(1) * 1.1;
    end
    limits(2) = limits(2) * 1.1;

    if( user_data.bLockScatter )
        x_lims_scatter = get(user_data.Scatter_axes_hdl, 'Xlim');
        y_lims_scatter = get(user_data.Scatter_axes_hdl, 'Ylim');
    end

    if( user_data.bLockRRserie )
        x_lims_RRserie = get(user_data.RRserie_axes_hdl, 'Xlim');
        y_lims_RRserie = get(user_data.RRserie_axes_hdl, 'Ylim');
    end

    user_data.fig_hdl = figure(1);
%     set(user_data.fig_hdl, 'Toolbar', 'none');
    clf

    %% Axis de Poincar�

    user_data.Scatter_axes_hdl = axes('Position', [0.55 0.41 0.355 0.52 ]);

    RRscatter_hdl = scatter(user_data.Scatter_axes_hdl, user_data.RRserie, [ user_data.RRserie(2:end); user_data.RRserie(end) ] );

    if( ~isempty(user_data.selected_hb_idx) )
        hold(user_data.Scatter_axes_hdl, 'on')
        RRnext = [user_data.RRserie(2:end); user_data.RRserie(end)];
        user_data.RRscatter_selection_hdl = scatter(user_data.Scatter_axes_hdl, user_data.RRserie(user_data.selected_hb_idx), RRnext(user_data.selected_hb_idx), 'xg' );
        hold(user_data.Scatter_axes_hdl, 'off')
    end

    if( user_data.bLockScatter )
        xlim(user_data.Scatter_axes_hdl, x_lims_scatter);
        ylim(user_data.Scatter_axes_hdl, y_lims_scatter);
    else
        xlim(user_data.Scatter_axes_hdl, limits);
        ylim(user_data.Scatter_axes_hdl, limits);
        zoom reset
    end

    title(user_data.Scatter_axes_hdl, ['Poincar� plot - Registro ' user_data.ECG_struct.header.recname ]);
    xlabel(user_data.Scatter_axes_hdl, 'RR current')
    ylabel(user_data.Scatter_axes_hdl, 'RR next')

    %% Axis de RR serie
    user_data.RRserie_axes_hdl = axes('Position', [0.13 0.709 0.375 0.216 ]);

    RRserie_hdl = plot(user_data.RRserie_axes_hdl, user_data.RRserie, '-xb' );

    if( ~isempty(user_data.selected_hb_idx) )
        hold(user_data.RRserie_axes_hdl, 'on')
        user_data.RRserie_selection_hdl = plot(user_data.RRserie_axes_hdl, user_data.selected_hb_idx, user_data.RRserie(user_data.selected_hb_idx), 'og' );
        hold(user_data.RRserie_axes_hdl, 'off')
    end

    if( user_data.bLockRRserie )
        xlim(user_data.RRserie_axes_hdl, x_lims_RRserie);
        ylim(user_data.RRserie_axes_hdl, y_lims_RRserie);
    else
        ylim(user_data.RRserie_axes_hdl, limits);
        zoom reset
    end

    cant_ticks = 5;
    aux_idx = round(linspace(1, length(user_data.RRserie), cant_ticks));
    set(user_data.RRserie_axes_hdl, 'XTick', rowvec(aux_idx) );
    aux_str = strcat(cellstr(num2str(colvec(aux_idx))), cellstr(repmat(' (',cant_ticks,1)), cellstr(Seconds2HMS(user_data.anns_under_edition(aux_idx)*1/user_data.ECG_struct.header.freq)), cellstr(repmat(')',cant_ticks,1)) );    set(user_data.RRserie_axes_hdl, 'XTickLabel', char(aux_str) );
    set(user_data.RRserie_axes_hdl, 'XTickLabel', char(aux_str) );
    xlabel(user_data.RRserie_axes_hdl, 'heartbeat #')
    ylabel(user_data.RRserie_axes_hdl, 'RR interval')

%% global functions

    function update_title_efimero( strTitle, delay )

        if( ~isempty(title_efimero_hdl) && ~isempty(ancestor(title_efimero_hdl,'figure')) && gcf == ancestor(title_efimero_hdl,'figure') && ishandle(title_efimero_hdl) )
            set(title_efimero_hdl, 'String',strTitle )
            set(title_efimero_hdl, 'Visible', 'on');
        else

            title_efimero_hdl = annotation( 'textbox', [0 0.98 0.3 0.01 ], ...
                                  'String', strTitle, ...
                                  'Tag', 'title_efimero', ...
                                  'FontSize', 8, ...
                                  'Interpreter', 'none', ...
                                  'FitBoxToText', 'on', ...
                                  'HorizontalAlignment', 'left', ...
                                  'EdgeColor', 'none', ...
                                  'BackgroundColor', 'r' );

        end

        if( ~isinf(delay) && strcmpi(my_timer.Running, 'off') )
            my_timer.StartDelay = delay;
            start(my_timer)
        end

    end

    function timer_fcn(obj,event_obj)

        set(title_efimero_hdl, 'Visible', 'off');

    end

%% Window callbacks

    function WindowButtonDownCallback(obj,event_obj)

        if (strcmp(get(fig_hdl,'SelectionType'),'alt'))

            prev_u = get(fig_hdl, 'units');
            set(fig_hdl, 'units','normalized');
            crd = get(fig_hdl, 'CurrentPoint');
            xp = crd(1);
            yp = crd(2);
            set(fig_hdl, 'units', prev_u);

            if( ~isempty([min_y_drag max_x_drag min_y_drag]) && xp <= max_x_drag && yp <= max_y_drag && yp >= min_y_drag)
                DragMouseBegin()
            end
        end

    end

    function WindowButtonUpCallback(obj,event_obj)

        DragMouseEnd()

    end

    function KeyPress(obj,event_obj)

        if (strcmp(event_obj.Key,'c') && strcmp(event_obj.Modifier,'control'))
            % copy selection
            if( ~isempty(selected_hb_idx) )
                copy_paste_buffer = anns_under_edition(selected_hb_idx);
                update_title_efimero('Selection copied', 5 );

            end

        elseif (strcmp(event_obj.Key,'v') && strcmp(event_obj.Modifier,'control'))
            % paste selection
            if( ~isempty(copy_paste_buffer) )
                bAnnsEdited = true;
                bRecEdited = true;
                PushUndoAction();
                anns_under_edition = sort( unique([anns_under_edition; colvec(copy_paste_buffer) ]) );
                selected_hb_idx = [];
                RRserie_filt = {[]};

                Redraw();
            end

        elseif (strcmp(event_obj.Key,'delete'))
            % delete selection
            if( ~isempty(selected_hb_idx) )
                bAnnsEdited = true;
                bRecEdited = true;
                PushUndoAction();

                aux_idx = [find(anns_under_edition < anns_under_edition(anns_under_edition_idx(selected_hb_idx(1))),1, 'last') find( anns_under_edition > anns_under_edition(anns_under_edition_idx(selected_hb_idx(end))), 1, 'first') ];

                if( isempty(aux_idx) )
                    aux_idx = 1;
                else
                    aux_idx = aux_idx(1);
                end

                aux_val = anns_under_edition(aux_idx);

                if( bSeries )
                    anns_under_edition(anns_under_edition_idx(selected_hb_idx)) = nan;
                else
                    anns_under_edition(anns_under_edition_idx(selected_hb_idx)) = [];
                end

                anns_under_edition_idx = find( anns_under_edition >= start_idx &  anns_under_edition <= end_idx );
                hb_idx = find(anns_under_edition(anns_under_edition_idx) == aux_val);
                selected_hb_idx = [];

                aux_rr_filt = RRserie_filt{1};
                aux_rr_filt(anns_under_edition_idx(selected_hb_idx)) = [];
                RRserie_filt{1} = aux_rr_filt;

                Redraw();
            end

        elseif (strcmp(event_obj.Key,'y') && ~isempty(event_obj.Modifier) && strcmp(event_obj.Modifier,'control'))
            % redo last change
            if( undo_buffer_idx < length(undo_buffer) )
                undo_buffer_idx = undo_buffer_idx + 1;
                anns_under_edition = undo_buffer{undo_buffer_idx};
                selected_hb_idx = [];
                RRserie_filt = {[]};
                Redraw();
            end

        elseif (strcmp(event_obj.Key,'z') && strcmp(event_obj.Modifier,'control'))
            % undo last change
            if( undo_buffer_idx > 1 )
                undo_buffer_idx = undo_buffer_idx - 1;
                anns_under_edition = undo_buffer{undo_buffer_idx};
                selected_hb_idx = [];
                RRserie_filt = {[]};

                Redraw();
            end

        elseif (strcmp(event_obj.Key,'rightarrow') && ~isempty(event_obj.Modifier) && strcmp(event_obj.Modifier,'control'))

            if(bRecEdited)

                update_annotations();

                if( bLoadECG )
                    update_title_efimero('Saving data ...', 5 );
                    save(rec_path, '-struct', 'ECG_struct');
                    update_title_efimero(['Saved ' rec_path], 5 );

                    if( rec_idx >= 1 && rec_idx < length(recording_indexes) )
                        rec_idx = rec_idx + 1;
                    else
                        rec_idx = 1;
                    end

                    set(recordings_control, 'Value', rec_idx );

                    DoRecording();

                else

                    if( isfield(ECG_struct, 'series_quality' ) )
                        anns_struct.series_quality = ECG_struct.series_quality;
                    end
                    for ii = 1:size(AnnNames,1)
                        anns_struct.(AnnNames{ii,1}) = ECG_struct.(AnnNames{ii,1});
                    end
                    assignin( 'caller', OutputVarName, anns_struct );
                    update_title_efimero(sprintf('Saving ''%s'' variable in caller workspace', OutputVarName), 5 );

                    bAnnsEdited = false;
                    bRecEdited = false;

                end
            end

        elseif (strcmp(event_obj.Key,'leftarrow') && ~isempty(event_obj.Modifier) && strcmp(event_obj.Modifier,'control'))

            if(bRecEdited)

                update_annotations();

                if( bLoadECG )
                    update_title_efimero('Saving data ...', 5 );
                    save(rec_path, '-struct', 'ECG_struct');
                    update_title_efimero(['Saved ' rec_path], 5 );

                    if( rec_idx > 1 && rec_idx <= length(recording_indexes) )
                        rec_idx = rec_idx - 1;
                    else
                        rec_idx = length(recording_indexes);
                    end

                    set(recordings_control, 'Value', rec_idx );

                    DoRecording();

                else
                    if( isfield(ECG_struct, 'series_quality' ) )
                        anns_struct.series_quality = ECG_struct.series_quality;
                    end
                    for ii = 1:size(AnnNames,1)
                        anns_struct.(AnnNames{ii,1}) = ECG_struct.(AnnNames{ii,1});
                    end
                    assignin( 'caller', OutputVarName, anns_struct );
                    update_title_efimero(sprintf('Saving ''%s'' variable in caller workspace', OutputVarName), 5 );

                    bAnnsEdited = false;
                    bRecEdited = false;

                end
            end

        elseif (strcmp(event_obj.Key, 'l') )
            % lock ECG Y axis

            bLockECG = ~bLockECG;

            if( bLockECG )
                update_title_efimero('ECG Y axis locked', 5 );
            else
                update_title_efimero('ECG Y axis unlocked', 5 );
            end

        elseif (strcmp(event_obj.Key,'p') )

            update_title_efimero('Click and drag the time interval where the pattern is ...', 10 );

            set(fig_hdl, 'WindowButtonDownFcn', []);
            set(ECG_axes_hdl,'ButtonDownFcn', []);

            set(obj,'CurrentAxes', ECG_axes_hdl);
            waitforbuttonpress;

            point1 = get(ECG_axes_hdl,'CurrentPoint');    % button down detected
            rbbox;
            point2 = get(ECG_axes_hdl,'CurrentPoint');    % button up detected

            pattern_match_xlims = round(sort([ point1(1,1) point2(1,1) ]));
            aux_seq = pattern_match_xlims(1):pattern_match_xlims(2);

            update_title_efimero('Filtering ECG ...', 5 );

            if( isempty(filtro) )
                ECG = ECG_struct.signal(:,lead_idx);
            else
                ECG = filter(filtro, flipud(ECG_struct.signal(:,lead_idx)) );
                ECG = filter(filtro, flipud(ECG) );
            end

            if( ishandle(Pattern_hdl) )
                delete(Pattern_hdl)
            end

            hold(ECG_axes_hdl, 'on')
            Pattern_hdl = plot(ECG_axes_hdl, aux_seq, ECG(aux_seq,:), '.g' );
            hold(ECG_axes_hdl, 'off')
            drawnow;

            try
                SearchPattern();
                set(fig_hdl, 'WindowButtonDownFcn', @WindowButtonDownCallback2D);
                set(ECG_axes_hdl,'ButtonDownFcn',@inspect_ECG);

            catch ME

                set(fig_hdl, 'WindowButtonDownFcn', @WindowButtonDownCallback2D);
                set(ECG_axes_hdl,'ButtonDownFcn',@inspect_ECG);
                rethrow(ME);
            end

            % store the axes_hdl created in SearchPattern();
            axes_hdl( RR_global_PM_k, 1:2) = [RR_global_PM_hdl, figPatternMatch_hdl];
            axes_hdl( proximity_k, 1:2) = [proximity_hdl, figPatternMatch_hdl];
            axes_hdl( similarity_hdl_k, 1:2) = [similarity_hdl, figPatternMatch_hdl];
            axes_hdl( pattMatch_hdl_k, 1:2) = [pattMatch_hdl, figPatternMatch_hdl];

        elseif ( ~isempty(event_obj.Modifier) && strcmp(event_obj.Key,'g') && strcmp(event_obj.Modifier,'control'))

            if(bRecEdited)

                update_annotations();

                if( bLoadECG )
                    update_title_efimero('Saving data ...', 5 );
                    save(rec_path, '-struct', 'ECG_struct');
                    update_title_efimero(['Saved ' rec_path], 5 );
                else

                    if( isfield(ECG_struct, 'series_quality' ) )
                        anns_struct.series_quality = ECG_struct.series_quality;
                    end
                    for ii = 1:size(AnnNames,1)
                        anns_struct.(AnnNames{ii,1}) = ECG_struct.(AnnNames{ii,1});
                    end
                    assignin( 'caller', OutputVarName, anns_struct );
                    update_title_efimero(sprintf('Saving ''%s'' variable in caller workspace', OutputVarName), 5 );

                    bAnnsEdited = false;
                    bRecEdited = false;
                end

            end

        elseif (strcmp(event_obj.Key,'t'))
            %% Toggle ECG lead
            if( length(lead_idx) > 1 )
                lead_idx = 1;
            else
                if( lead_idx < ECG_struct.header.nsig )
                    lead_idx = lead_idx + 1;
                else
                    lead_idx = 1:ECG_struct.header.nsig;
                end
            end
            cla(ECG_axes_hdl);

            if( bSeries )
                this_all_anns = all_annotations_selected_serie_location;
                aux_val = this_all_anns{1};
                aux_val(serie_location_mask) = nan;
                this_all_anns{1} = aux_val;
            else
                this_all_anns = all_annotations_selected;
            end

            if( ~bLockECG )
                ECG_limits = [];
            end

            [ECG_hdl, ECG_limits ] = plot_ecg_heartbeat(ECG_struct.signal, lead_idx, this_all_anns, start_idx, anns_under_edition_idx(hb_idx) , hb_detail_window, ECG_struct.header, filtro, ECG_axes_hdl, ECG_limits);

            if( length(lead_idx) > 1 )
                aux_str = rowvec(colvec([repmat(',', length(lead_idx), 1) ECG_struct.header.desc(lead_idx,:) ]'));
                title(ECG_axes_hdl, ['Heartbeat ' num2str(hb_idx) ' : Leads ' aux_str(2:end) ] )
            else
                title(ECG_axes_hdl, ['Heartbeat ' num2str(hb_idx) ' : Lead ' ECG_struct.header.desc(lead_idx,:)] )
            end

    %         zoom reset
            cellfun(@(a)( set(a,'ButtonDownFcn',@inspect_ECG)), ECG_hdl);
            set(ECG_axes_hdl,'ButtonDownFcn',@inspect_ECG);

        elseif (strcmp(event_obj.Key,'rightarrow'))
            %% right arrow

            if(bAnnsEdited)
                update_annotations();
            end

            AnnNames_idx = AnnNames_idx + 1;
            if( AnnNames_idx > length(AnnNames) )
                AnnNames_idx = 1;
            end

            update_title_efimero(['Using ' AnnNames{AnnNames_idx,1} ' annotations (' num2str(ratios(AnnNames_idx)) ')'], 5 );

            undo_buffer_idx = 1;

            anns_under_edition = unique(round(colvec( ECG_struct.(AnnNames{AnnNames_idx,1}).(AnnNames{AnnNames_idx,2}) )));

            bAnnsEdited = false;

            selected_hb_idx = [];

            Redraw();

        elseif (strcmp(event_obj.Key,'leftarrow'))
            %% left arrow

            if(bAnnsEdited)
                update_annotations();
            end

            AnnNames_idx = AnnNames_idx - 1;
            if( AnnNames_idx < 1  )
                AnnNames_idx = length(AnnNames);
            end

            update_title_efimero(['Using ' AnnNames{AnnNames_idx,1} ' annotations (' num2str(ratios(AnnNames_idx)) ')'], 5 );

            undo_buffer_idx = 1;

            anns_under_edition = unique(round(colvec( ECG_struct.(AnnNames{AnnNames_idx,1}).(AnnNames{AnnNames_idx,2}) )));

            bAnnsEdited = false;

            selected_hb_idx = [];

            Redraw();

        else
%             bLockRRserie = false;
%             bLockScatter = false;
%             lead_idx = 1:ECG_struct.header.nsig;
        end

    end

end


% StackExchange Signal Processing Q688
% https://dsp.stackexchange.com/questions/688
% What Is the Algorithm Behind Photoshop's �Black and White� Adjustment Layer?
% References:
%   1.  A
% Remarks:
%   1.  HSL Picker - http://hslpicker.com/.
%   2.  Colorizer Color Picker - http://colorizer.org/.
% TODO:
% 	1.  C
% Release Notes
% - 1.0.000     22/12/2018
%   *   First release.

%% General Parameters

subStreamNumberDefault = 2123;

run('InitScript.m');

figureIdx           = 0; %<! Continue from Question 1
figureCounterSpec   = '%04d';

generateFigures = OFF;
generateImages  = OFF;

%% Simulation Parameters

vPhotoshopValues = randi([0, 100], [6, 1]);
% vPhotoshopValues = [56; 61; 50; 78; 76; 54];
vPhotoshopValues = [30; 98; 51; 73; 5; 53]; %<! This is used in Photoshop

% 11 Colors - [H, 1, 0.5] Where H goes in 30% Steps -> [0, 30, 60, ..., 330]
% Each color is a row.
mBaseColors = [1, 0, 0; 1, 0.5, 0; 1, 1, 0; 0.5, 1, 0; 0, 1, 0; 0, 1, 0.5; 0, 1, 1; 0, 0.5, 1; 0, 0, 1; 0.5, 0, 1; 1, 0, 1; 1, 0, 0.5];

mBaseColors = rand(21, 3);

cellSize    = 50; %<! Pixels

%% Generate Data

numColors = size(mBaseColors, 1);

numRows = cellSize;
numCols = cellSize * numColors;

mI = zeros(numRows, numCols, 3);

for ii = 1:numColors
    vCurrColor = mBaseColors(ii, :);
    firstColIdx = ((ii - 1) * cellSize) + 1;
    lastColIdx  = ii * cellSize;
    mI(:, firstColIdx:lastColIdx, :) = repmat(reshape(vCurrColor, [1, 1, 3]), [cellSize, cellSize 1]);
end

% vCoeffValues = [0.5; 0; 0; 0; 0; 0];
vCoeffValues = (vPhotoshopValues - 50) ./ 50;
mO = ApplyBlackWhiteFilter(mI, vCoeffValues);

% figure;
% imshow(mI);
% figure;
% imshow(mO);
%
% figure;
% imshow(im2uint8(mO));

if(generateImages == ON)
    imwrite(im2uint8(mI), 'ReferenceImage2.png');
end

%% Analysis vs. Photoshop

mORef   = im2single(imread('PhotoshopImage2.png'));
mE      = mORef - mO;

maxAbsDev = max(abs(mE(:)));

%% Display Results

figureIdx = figureIdx + 1;

hFigure = figure('Position', figPosLarge);
hAxes   = subplot(4, 1, 1);
hImgObj = imshow(mI);
set(get(hAxes, 'Title'), 'String', {['Reference Image']}, ...
    'FontSize', fontSizeTitle);

hAxes   = subplot(4, 1, 2);
hImgObj = imshow(mO);
set(get(hAxes, 'Title'), 'String', {['MATLAB Output'], ['Black & White Adjustment Layer Input Values - ', num2str(vPhotoshopValues.')]}, ...
    'FontSize', fontSizeTitle);

hAxes   = subplot(4, 1, 3);
hImgObj = imshow(mORef);
set(get(hAxes, 'Title'), 'String', {['Photoshop Output'], ['Black & White Adjustment Layer Input Values - ', num2str(vPhotoshopValues.')]}, ...
    'FontSize', fontSizeTitle);

hAxes   = subplot(4, 1, 4);
hImgObj = imshow(mE);
set(get(hAxes, 'Title'), 'String', {['Error Image (Absolute Deviation)'], ['Max Absolute Deviation - ', num2str(maxAbsDev)]}, ...
    'FontSize', fontSizeTitle);

if(generateFigures == ON)
    saveas(hFigure,['Figure', num2str(figureIdx, figureCounterSpec), '.png']);
end

%% Restore Defaults

% set(0, 'DefaultFigureWindowStyle', 'normal');
% set(0, 'DefaultAxesLooseInset', defaultLoosInset);


function AIFPScaled = refRegionScale(AIFP,inputS,shiftS,paramFile,headerS,muscleTimeCourse3M,muscleMaskM)
% Function to pull muscle time course from ROI mask & convert to concentration
% Loads average AIF for the study (or individual), runs Tofts fit over range of AIF amplitudes
% to find AIF amplitude that gives Tofts fit ve = 0.1 for Muscle time course data.
% Returns this AIF time course.
%
% Kristen Zakian
% AI 7/06/16
% AI 7/21/16  Updated to write ROI signal shift to parameter file

% Get parameters
T10Muscle_ms = inputS.T10ref;
TRms = headerS.TRms;
tDel = headerS.tDel ;
FA = headerS.FA;
frames = headerS.frames;
r1 = 3.9*(headerS.B0 < 2.0)*strcmp(inputS.cAgent,'gd')+ 3.3*(headerS.B0 > 2.0)*strcmp(inputS.cAgent,'gd') + ...
    8.1*(headerS.B0 < 2.0)*strcmp(inputS.cAgent,'mh') + 6.3*(headerS.B0 > 2.0)*strcmp(inputS.cAgent,'mh');

% Generate vector of sampling times  (1 x frames size)
ind = 0:(frames-1);
tsec = double(ind)*tDel;
tmin = tsec./60.;                      %ktrans, etc. are in /min.  Parker coefs are in min or /min.  Tofts fit will use minutes.

% Generate an average time course for the muscle ROI from the slice
avgROISigV = zeros(1,20);
for t = 1:frames
    muscleMaskSum = sum(muscleTimeCourse3M(:,:,t));
    avgROISigV(t) = sum(muscleMaskSum(:))/nnz(muscleMaskM);         % avg of masked elements
end

%  Display for deciding muscle ROI point shift. Must be shifted to zero for Tofts fit

%Plot the Muscle ROI time course
figTitle = 'Start of muscle time course';
figure ('Name', figTitle);
plot (tmin,avgROISigV,'-d');
pause(2);

%Pass AIFAmp from parameter file if available
%(AIFAmp is the value that gives ve < 0.1)
useValue = 'No';
shiftC = fieldnames(shiftS);
shiftIn = any(strcmp(shiftC,'muscleShift'));
if shiftIn
    if ~isempty(shiftS.muscleShift)
        aShiftIn = shiftS.muscleShift;
        useValue = questdlg(sprintf('Use value from parameter file:\n muscleShift = %g ?',aShiftIn),...
            'AIF scaling','Yes','No','Yes');
    end
end

if strcmp(useValue,'No')
    aShift = input('\nInput the muscle point shift (e.g. 2, to shift left 2 points):   ');
    %Store shift to parameter file
    fid = fopen(paramFile);
    inputC = textscan(fid, '%s %s %n','endofline','\r\n');
    fmt = '\r\n%s\t%s\t%d';
    fclose(fid);
    if shiftIn
        shiftIdx = strcmp (inputC{1},'muscleShift');
        inputC{3}(shiftIdx) = aShift;
        fid = fopen(paramFile,'w+');
        for lineNum = 1:size(inputC{1},1)
            col1 = inputC{1}(lineNum);
            col2 = inputC{2}(lineNum);
            col3 = inputC{3}(lineNum);
            fprintf(fid,fmt,col1{1},col2{1},col3);
        end
        fclose(fid);
    else
        fid = fopen(paramFile,'a');
        newEntryC = {'muscleShift','na',aShift};
        fprintf(fid,fmt,newEntryC{:});
        fclose(fid);
    end
else
    aShift = aShiftIn;
end
close(gcf);
muscleShiftV = circshift(avgROISigV', -aShift);
rawMuscleSigV = muscleShiftV';
shiftRawMuscleSigV = rawMuscleSigV(frames-aShift-8:frames-aShift);
meanRawMuscle = mean(shiftRawMuscleSigV(:));
rawMuscleSigV(frames-aShift+1:frames)= meanRawMuscle;
baseptsMuscle = aShift-1; % set number of baseline points = number of shifted points -1

% Display unshifted and shifted aif curve
figtitle = ['Muscle time course unshifted and shifted. Shift = ',num2str(aShift)];
figure ('Name', figtitle);
plot (tmin,avgROISigV,tmin,rawMuscleSigV,'--');
pause(4);
close(gcf);

% Convert ROI average time course to Concentration
% (need muscle pre-contrast T1 and average baseline value S0)
TR = TRms/1000.;                    %(TR in DICOM header is in ms. Change to s)
T10 = T10Muscle_ms/1000;
base = avgROISigV(1:baseptsMuscle); % baseline signal value obtained from time course BEFORE SHIFT
s0 = mean(base);
pCalcConcMuscle = [r1, TR, FA, T10];
muscleConcTCourseV = calcConc(rawMuscleSigV,pCalcConcMuscle,s0);
figtitle = ('Muscle concentration time course ');
figure ('Name', figtitle);
plot (tmin,muscleConcTCourseV);
pause(1);
close(gcf);

%  Fit muscle time course to Tofts model until ve = 0.1.
%Start with average AIF.
%Vary the amplitude of the average AIF until you get a ve of 0.1.
%That will then be the AIF that you use.

inputsC = fieldnames(inputS);                         %Pass AIFAmp from parameter file if available
if any(strcmp(inputsC,'AIFAmp'))                      %(AIFAmp is the value that gives ve < 0.1)
    if ~isempty(inputS.AIFAmp)
        AIFPScaled = refRegionToftsAIFScale(tmin,AIFP,muscleConcTCourseV,paramFile,inputS.AIFAmp);
    end
else
    AIFPScaled = refRegionToftsAIFScale(tmin,AIFP,muscleConcTCourseV,paramFile);
end
%Display figure
figtitle = 'AIF plasma and AIF scaled ';
figure ('Name', figtitle);
plot (tmin,AIFP,tmin,AIFPScaled,'--');
pause(1);
close(gcf);

end


function [ y2, m2, d2, f2 ] = ymdf_next_republican ( y1, m1, d1, f1 )

%*****************************************************************************80
%
%% YMDF_NEXT_REPUBLICAN returns the Republican YMD date of the next day.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 March 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer Y1, M1, D1, real F1,
%    the YMDF date.
%
%    Output, integer Y2, M2, D2, real F2,
%    tomorrow's YMDF date.
%
  y2 = y1;
  m2 = m1;
  d2 = d1 + 1;
  f2 = f1;

  [ y2, m2, d2 ] = day_carry_republican ( y2, m2, d2 );

  return
end


function [der_loc, der_dir] = msi_file_DER_loc(set_fid)
%function [der_loc, der_dir] = msi_file_DER_loc(set_fid, chans)
%	MSI_FILE_GET_LONG(set_fid, chans)	Skip to a keyword in a file FID
%	and return the single float value
%

key_count = msi_file_find_keyword(set_fid, 'MSI.DerChanCount:');
if (key_count == 1)
    DerChanCount = msi_file_get_long(set_fid, 'MSI.DerChanCount:');
end

frewind(set_fid);
keyword = 'MSI.Der_Position_Information.Begin:';

while feof(set_fid) == 0
    	line = fgetl(set_fid);
	matches = findstr(line, keyword);
	num = length(matches);
	if num > 0
	    fprintf(1, 'I found a %s\n', line);
	    for (ii=1:DerChanCount)
		line = fgetl(set_fid);
		[name, count, errmsg, nextindex] = sscanf(line, '%s\t', 1);
		[token, nextline] = strtok(line, '	');
		[bigresult, count, errmsg, nextindex] = sscanf(nextline, '\t%f\t%f\t%f\t%f\t%f\t%f', 6);
		loc(1) = bigresult(1);
		loc(2) = bigresult(2);
		loc(3) = bigresult(3);
		dir(1) = bigresult(4);
		dir(2) = bigresult(5);
		dir(3) = bigresult(6);
		%fprintf(1, 'chan: %s\n',  name);
		%fprintf(1, '  %f %f %f   ',  loc(1), loc(2), loc(3));
		%fprintf(1, '  %f %f %f \n',  dir(1), dir(2), dir(3));
		%fprintf(1, 'chan: %s (%f,%f,%f) (%f,%f,%f)\n',  name, loc[1], loc[2], loc[3], dir[1], dir[2], dir[3]);
		outloc(ii,1) = loc(1);
		outloc(ii,2) = loc(2);
		outloc(ii,3) = loc(3);

		outdir(ii,1) = dir(1);
		outdir(ii,2) = dir(2);
		outdir(ii,3) = dir(3);
	    end
der_loc = outloc;
der_dir = outdir;
	end
end


function [weight] = sp_kernel(data, weight_o, gamma)
% This program output the final portfolio the SP strategy on data
%
% function [weight] = sp_kernel(data, weight_o, gamma)
%
% weight: final portfolio, used for next rebalance
%
% data: market sequence vectors
% weight_o: last portfolio, also can be last price relative adjusted.
% gamma: switching parameter
%
% Example: [weight] = sp_kernel(data, weight_o, 0.25)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file is part of OLPS: http://OLPS.stevenhoi.org/
% Original authors: Bin LI, Steven C.H. Hoi
% Contributors:
% Change log:
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

weight = sp_expert(data, weight_o, gamma);

end


% Comparing the SPM beta weights and the ones derived from mrVista
%
% We ran SPM version 2 in this directory.  The time series data are stored
% in the imageSlice sub-directory. The data here is a toy set with only one
% slice that allows us to debug the beta weight computations in the mrVista
% GLM and in the SPM analysis.
%
% When we ran the SPM model we created an SPM.mat file that is in this
% directory that contains all of the relevant information for the two types
% of events that take place in the experiment: rhymes and lines.  You can
% view the design matrix by running SPM2 | fMRI-time series | Review (or
% something like that). The design matrix is also just read in below.
%

% We could only run the SPM2 code on slightly older versions of Matlab, say
% Matlab 7.0.4.  This doesn't run properly on Matlab 2007a, for example.

%% The first part is about properly computing the model weights
% This part confirmed that our weights and SPM are the same up to a single
% global scale factor.

% Current directory.
chdir(fullfile(mrvRootPath,'EventRelated','glmTest'))

% This is the original SPM Michal and I created, but I cleared the .xM
% field so that there is no mask.  This makes the data comparable to Rory's
% calculation, point by point.
load('SPM-noMask');

% The spm calculation of the betas is in spm_spm_local
spm_defaults
[SPM,pKX] = spm_spm_local(SPM);

% We set X, the design matrix, to be the one we built using the SPM gui.
% this design matrix has 1 predictor per condition, plus a column of ones.
% it uses the hrf from SPM
X = SPM.xX.X;
% figure(1); plot(X)
% tmp = pinv(pKX); max(abs(X(:) - tmp(:)))

% We created the beta files using the SPM interface (Estimate).  We read
% the files here using the builtin Matlab analyze reader.
% chdir('SPM-UI')
tmp = analyzeRead('beta_0001');  spmBeta(:,1) = tmp(:);
tmp = analyzeRead('beta_0002');  spmBeta(:,2) = tmp(:);
tmp = analyzeRead('beta_0003');  spmBeta(:,3) = tmp(:);
[r,c] = size(tmp);
% imtool(reshape(spmBeta(:,1),r,c))
% figure(1); imagesc(reshape(spmBeta(:,1),r,c)); axis image;

% We convert the time series in analyze format into our own time series.
inFileRoot = ...
    fullfile(mrvRootPath,'EventRelated',...
    'glmTest',...
    'imageFiles',...
    'Scan1-Slice6');
outFileRoot = inFileRoot;
nVols = 78;
firstVolIndex = 0;
doRotate = 0;
scaleFact = [1,1];
flipudFlag = 0;
fliplrFlag = 0;
tSeries = analyze2mrLoadRet3TSeries(inFileRoot,outFileRoot,nVols,...
    firstVolIndex,doRotate,scaleFact,flipudFlag,fliplrFlag);

% figure(1); plot(tSeries)
%   max(abs(KWY(:) - tSeries(:)))

% Compute the beta weights from mrVista
tr = 2; nh = 1;
model    = glm(tSeries, X, tr, nh);
mrvBetas = squeeze(model.betas);

% Compare the beta weights for the different model terms
ii = 1;
mrvB = reshape(mrvBetas(ii,:),r,c);
figure(2); imagesc(mrvB); axis image; colormap(gray(256))
figure(1); hist(mrvB(:),100)

% Compare the values directly.
figure(1); plot(mrvBetas(ii,:),spmBeta(:,ii),'.')
grid on

% We can check the images read through the SPM call and our call based on
% analyze Read. They are the same.
% vName = 'imageFiles\Scan1-Slice6\000.img';
vName = 'C:\u\brian\Matlab\VISTASOFT\mrLoadRet-3.0\EventRelated\glmTest\imageFiles\Scan1-Slice6\077.img';

tmp = analyzeRead(vName);
figure(1); hist(tmp(:),100)
imtool(tmp/max(tmp(:)));
mean(tmp(:))

% V = VY(i)
V.fname = vName;
V.pinfo = [0.0066, 0, 0]';
r = 124; c= 99;
[X,Y] = meshgrid(1:r,1:c);
Z = ones(size(X(:)));
XYZ = [X(:),Y(:),Z(:)]';
spmY = spm_get_data(V,XYZ);
figure(2);hist(spmY(:),100)

spmY = reshape(spmY,c,r)';
imtool(spmY/max(spmY(:)));
mean(spmY(:))

%% We analyze the t-contrast images using mrVista.  We created a
% t-contrast using SPM via its GUI.  These are in SPMT004 and con_004.
chdir(fullfile(mrvRootPath,'EventRelated','glmTest'))

% For the contrasts, we used this SPM
load('SPM');
X = SPM.xX.X;

% Get the time series
inFileRoot = ...
    fullfile(mrvRootPath,'EventRelated',...
    'glmTest',...
    'imageFiles',...
    'Scan1-Slice6');
outFileRoot = inFileRoot;
nVols = 78;
firstVolIndex = 0;
doRotate = 0;
scaleFact = [1,1];
flipudFlag = 0;
fliplrFlag = 0;
tSeries = analyze2mrLoadRet3TSeries(inFileRoot,outFileRoot,nVols,...
    firstVolIndex,doRotate,scaleFact,flipudFlag,fliplrFlag);

% Build the GLM model
tr = 2; nh = 1;
model    = glm(tSeries, X, tr, nh);

active = 1;   % Rhyme condition
control= 2;   % Line condition
[stat, ces, vSig, units] = glm_contrast(model,active,control);
[statT, ces, vSig, units] = glm_contrast(model,active,control,'t');

r = 124; c= 99;
mrvCON = reshape(stat,r,c);
figure(1); imagesc(mrvCON); axis image

spmCON = analyzeRead('con_0004');
spmCON = reshape(spmCON,r,c);
figure(2); imagesc(spmCON); axis image
imtool(spmCON)

plot(spmCON(:),mrvCON(:),'.'); axis equal; grid on

spmT = analyzeRead('SPMT_0004');
spmT = reshape(spmT,r,c);
figure(3); imagesc(spmT); axis image

mrvCONT = reshape(statT,r,c);
figure(1); imagesc(mrvCONT); axis image

% Notice that there are a lot of mrvCONT values that are high were the SPMT
% values are zero.  We think these are from places that SPM masks and mrV
% doesn't.  We need to figure this out.
plot(spmT(:),mrvCONT(:),'.');axis equal; grid on

% hist(mrvCONT(:),20)

l = (spmT(:) == 0);
tmp = zeros(size(spmT));
tmp(l) = 1;
tmp = reshape(tmp,r,c);
figure(4); subplot(1,2,1), imagesc(tmp)
colorbar('vert'); axis image

l = (mrvCONT(:) == 0);
tmp = zeros(size(mrvCONT));
tmp(l) = 1;
tmp = reshape(tmp,r,c);
figure(4); subplot(1,2,2), imagesc(tmp)
colorbar('vert'); axis image


function [pb] = pbHuman(pres,iid,r)
if nargin<3, r=[0.25 0.99]; end
segs = readSegs(pres,iid);
pb = zeros(size(segs{1}));
for i = 1:numel(segs),
  bmap = seg2bmap(segs{i});
  pb = pb + bmap;
end
pb = pb / numel(segs);
pb = (pb~=0) .* (pb * (r(2)-r(1)) + r(1));
pb = min(pb,r(2));


function y=getmondim(mnum)
% y = getmondim(monitornumber)  GET MONitor DIMensions.
%   "y" is the dimensions of the specified monitor represented as
%   [xstart,ystart,width,height] where values are in pixels.
%   (xstart,ystart) are the absolute coordinates of the lower left corner.
%   "monitornumber" is a number associated with each monitor (Default=1).
%       Monitor numbering is defined as the row number of the corresponding
%       monitor in the root property 'MonitorPositions'.
%   Examples:
%       y=getmondim; y=getmondim(2);

%   Copyright 2006 Mirtech, Inc.
%   created 09/26/2006  by Mirko Hrovat on Matlab Ver. 7.2
%   Mirtech, Inc.       email: mhrovat@email.com
%  Notes:
%       The primary monitor is always numbered 1 and always starts at (1,1).
%   'MonitorPositions' returns coordinates corresponding to the upper left
%   corner and the bottom right corner (Windows convention). Matlab 'Help'
%   on this property is incorrect. GETMONDIM converts these coordinates to
%   the Matlab convention where the lower left corner starts at (1,1).
%       There is a bug with the root property 'ScreenSize'. If the primary
%   monitor's resolution is adjusted after Matlab has started, then the
%   size parameters of 'ScreenSize' are not adjusted while the origin is
%   adjusted. GETMONDIM.M fixes this be using the 'ScreenSize' origin to
%   correct for the discrepancy. Note that on restarting Matlab the
%   'ScreenSize' property changes to the correct values!

if nargin==0,       mnum=[];    end
if isempty(mnum),   mnum=1;     end
savedunits=get(0,'Units');
set(0,'Units','pixels')         % make sure unit values are in pixels
mpos=get(0,'MonitorPositions'); % get list of monitor positions
% MonitorPositions are the coordinates for upper left & lower right corners.
primaryhght=mpos(1,4)-mpos(1,2)+1;
if any(mnum==1:size(mpos,1)),
    % need to convert MonitorPositions to Matlab convention.
    height=mpos(mnum,4)-mpos(mnum,2)+1;
    width=mpos(mnum,3)-mpos(mnum,1)+1;
    offset=1;       %#ok
% NOTE!
% Bugfix for the root property 'ScreenSize' in case the primary monitor's
% resolution has changed. If bug is ever fixed then delete these lines.
    screenxy=get(0,'ScreenSize');
    offset=2-screenxy(2);
% end bugfix

    % get lower left corner coordinates
    llpt=[mpos(mnum,1),primaryhght-mpos(mnum,4)+offset];
    y=[llpt,width,height];
else
    warning('  Monitor does not exist!');   %#ok
    y=[];
end
set(0,'Units',savedunits)


function lars_init()

global RESOLUTION_OF_LARS;
global REGULARIZATION_FACTOR;
RESOLUTION_OF_LARS = 1e-12;
REGULARIZATION_FACTOR = 1e-11;
% RESOLUTION_OF_LARS = 1e-10;
% REGULARIZATION_FACTOR = 1e-9;
end


function Script_HOG_SVM_train_dyn()

% Change to your downloaded location
addpath('C:\liblinear\matlab')

%% load shared definitions and AU data
shared_defs;

% Set up the hyperparameters to be validated
hyperparams.c = 10.^(-9:0.5:1);
hyperparams.e = 10.^(-3);

hyperparams.validate_params = {'c', 'e'};

% Set the training function
svm_train = @svm_train_linear;

% Set the test function (the first output will be used for validation)
svm_test = @svm_test_linear;

pca_loc = '../../pca_generation/generic_face_rigid.mat';

%%
for a=1:numel(aus)

    au = aus(a);

    rest_aus = setdiff(all_aus, au);

    % load the training and testing data for the current fold
    [train_samples, train_labels, valid_samples, valid_labels, ~, PC, means, scaling] = Prepare_HOG_AU_data_generic_dynamic(train_recs, devel_recs, au, rest_aus, SEMAINE_dir, hog_data_dir);

    train_samples = sparse(train_samples);
    valid_samples = sparse(valid_samples);

    %% Cross-validate here
    [ best_params, ~ ] = validate_grid_search_no_par(svm_train, svm_test, false, train_samples, train_labels, valid_samples, valid_labels, hyperparams);

    model = svm_train(train_labels, train_samples, best_params);

    [prediction, a, actual_vals] = predict(valid_labels, valid_samples, model);

    % Go from raw data to the prediction
    w = model.w(1:end-1)';
    b = model.w(end);

    svs = bsxfun(@times, PC, 1./scaling') * w;

    name = sprintf('models/AU_%d_dyn.dat', au);

    pos_lbl = model.Label(1);
    neg_lbl = model.Label(2);

    write_lin_dyn_svm(name, means, svs, b, pos_lbl, neg_lbl);

    name = sprintf('results_SEMAINE_devel/AU_%d_dyn.mat', au);

    tp = sum(valid_labels == 1 & prediction == 1);
    fp = sum(valid_labels == 0 & prediction == 1);
    fn = sum(valid_labels == 1 & prediction == 0);
    tn = sum(valid_labels == 0 & prediction == 0);

    precision = tp/(tp+fp);
    recall = tp/(tp+fn);

    f1 = 2 * precision * recall / (precision + recall);

    save(name, 'model', 'f1', 'precision', 'recall', 'best_params', 'valid_labels', 'prediction');

end

end


function mrAnatSetNiftiXform(niftiFile, outFile);
%
% mrAnatSetNiftiXform([niftiFile=uigetfile],[outFile=uiputfile])
%
% Allows you to set the qto xform in a nifti file.
%
% REQUIRES:
%  * Stanford anatomy tools (eg. /usr/local/matlab/toolbox/mri/Anatomy)
%
% HISTORY:
% 2006.10.25 RFD (bob@white.stanford.edu) wrote it.

if (~exist('niftiFile','var') || isempty(niftiFile))
    [f,p] = uigetfile({'*.nii.gz','NIFTI';'*.*', 'All Files (*.*)'}, 'Select NIFTI file...');
    if(isnumeric(f)) disp('User canceled.'); return; end
    niftiFile = fullfile(p,f);
end

ni = niftiRead(niftiFile);
ni = niftiApplyCannonicalXform(ni);
img = mrAnatHistogramClip(double(ni.data), 0.4, 0.98);

nii.img = img;
nii.hdr.dime.pixdim = [1 ni.pixdim 1 1 1 1];
nii.hdr.dime.datatype = 64;
nii.hdr.dime.dim = [3 size(nii.img) 1 1 1 1];
%nii.hdr.hist.originator = [round(ni.qto_ijk(1:3,:)*[0 0 0 1]')'+1 128 0];
nii.hdr.hist.originator = [round(size(nii.img)./2) 128 0];
h = figure('unit','normal','pos', [0.18 0.08 0.5 0.85],'name','Set AC-PC landmarks');
opt.setarea = [0.05 0.15 0.9 0.8];
opt.usecolorbar = 0;
opt.usestretch = 0;
opt.command = 'init';
view_nii(h, nii, opt);
%d = getappdata(h);
hstr = num2str(h);
cb = ['d=getappdata(' hstr ');p=d.nii_view.imgXYZ.vox;setappdata(' hstr ',''ac'',p);set(gcbo,''String'',[''AC=['' num2str(p) '']'']);'];
b1 = uicontrol(h, 'Style','pushbutton','Visible','on','String','Set AC','Position',[20 30 150 30],'Callback',cb);
cb = ['d=getappdata(' hstr ');p=d.nii_view.imgXYZ.vox;setappdata(' hstr ',''pc'',p);set(gcbo,''String'',[''PC=['' num2str(p) '']'']);'];
b2 = uicontrol(h, 'Style','pushbutton','Visible','on','String','Set PC','Position',[190 30 150 30],'Callback',cb);
cb = ['d=getappdata(' hstr ');p=d.nii_view.imgXYZ.vox;setappdata(' hstr ',''ms'',p);set(gcbo,''String'',[''MidSag=['' num2str(p) '']'']);'];
b3 = uicontrol(h, 'Style','pushbutton','Visible','on','String','Set MidSag','Position',[360 30 150 30],'Callback',cb);
cb = ['setappdata(' hstr ',''done'',1);'];
b4 = uicontrol(h, 'Style','pushbutton','Visible','on','String','FINISH','Position',[530 30 80 30],'Callback',cb);
done = false;
while(~done)
    d = getappdata(h);
    if(isfield(d,'ac')&&isfield(d,'pc')&&isfield(d,'ms')&&isfield(d,'done')&&d.done==1)
        done = true;
        %convert matlab 1-based indices to zero-indexed indices
        %alignLandmarks = [d.ac; d.pc; d.ms]-1;
        alignLandmarks = [d.ac; d.pc; d.ms];
    end
    pause(.1);
end
close(h);

%disp(alignLandmarks);
origin = alignLandmarks(1,:);
% Define the current image axes by re-centering on the origin (the AC)
imY = alignLandmarks(2,:)-origin; imY = imY./norm(imY);
imZ = alignLandmarks(3,:)-origin; imZ = imZ./norm(imZ);
imX = cross(imZ,imY);
% Make sure the vectors point right, superior, anterior
if(imX(1)<0) imX = -imX; end
if(imY(2)<0) imY = -imY; end
if(imZ(3)<0) imZ = -imZ; end
% Project the current image axes to the cannonical AC-PC axes. These
% are defined as X=[1,0,0], Y=[0,1,0], Z=[0,0,1], with the origin
% (0,0,0) at the AC. Note that the following are the projections
x = [0 1 imY(3)]; x = x./norm(x);
y = [1  0 imX(3)]; y = y./norm(y);
%z = [0  imX(2) 1]; z = z./norm(z);
z = [0  -imY(1) 1]; z = z./norm(z);
% Define the 3 rotations using the projections. We have to set the sign
% of the rotation, depending on which side of the plane we came from.
rot(1) = sign(x(3))*acos(dot(x,[0 1 0])); % rot about x-axis (pitch)
rot(2) = sign(y(3))*acos(dot(y,[1 0 0])); % rot about y-axis (roll)
rot(3) = sign(z(2))*acos(dot(z,[0 0 1])); % rot about z-axis (yaw)

scale = ni.pixdim;
% Affine build assumes that we need to translate before rotating. But,
% our rotations have been computed about the origin, so we'll pass a
% zero translation and set it ourselves (below).
im2tal = affineBuild([0 0 0], rot, scale, [0 0 0]);
tal2im = inv(im2tal);

% Insert the translation.
%tal2im(1:3,4) = [origin+scale/2]';
tal2im(1:3,4) = [origin]';
im2tal = inv(tal2im);

if (~exist('outFile','var') || isempty(outFile))
    outFile = niftiFile;
end
resp = questdlg(['Save new transform matrix in ' outFile '?'],'Save confirmation','Ok','Cancel','Ok');
if(strcmpi(resp,'cancel'))
    disp('user canceled- transform NOT saved.');
    return;
end
if(exist(outFile,'file'))
    clear ni;
    ni = niftiRead(outFile);
    ni = niftiApplyCannonicalXform(ni);
else
    ni.fname = outFile;
end
ni = niftiSetQto(ni,im2tal,true);
% NOTE: our data are always left-handed (ie. 'neurological;
% unflipped; left-is-left). So, we force the qfac to reflect
% that.
ni.qfac = 1;

writeFileNifti(ni);
disp('transform saved.');
return;


%-----------------------------------------------------------------------
% Job saved on 18-Nov-2014 09:28:14 by cfg_util (rev $Rev: 6134 $)
% spm SPM - SPM12 (6225)
% cfg_basicio BasicIO - Unknown
%-----------------------------------------------------------------------
matlabbatch{2}.spm.stats.fmri_est.spmmat(1) = cfg_dep('fMRI model specification: SPM.mat File', substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','spmmat'));
matlabbatch{2}.spm.stats.fmri_est.write_residuals = 0;
matlabbatch{2}.spm.stats.fmri_est.method.Classical = 1;


classdef StressMinimizationWithGivenTopology < handle

    properties (Access = public)

    end

    properties (Access = private)
        mesh
        dataRes
        designVariable
    end

    properties (Access = private)
       microCase
       path
       fileResName
       initialIter
       vademecumName
       topOptProblem
    end

    methods (Access = public)

        function obj = StressMinimizationWithGivenTopology()
            obj.init();
            obj.wrapResAndMesh();
            obj.createTopOpt();
            obj.createDesignVariable();
            obj.solveTopOpt();
        end

    end

    methods (Access = private)

        function init(obj)
            obj.microCase = 'Rectangle';
            obj.vademecumName = 'SuperEllipseQMax';
            meshType  = 'Medium';
            fCase = [obj.microCase,meshType];
            obj.path = ['/media/alex/My Passport/LatticeResults/StressNorm',fCase,'/'];
            obj.fileResName  = 'ExperimentingPlot';
            obj.initialIter = 3;
        end

        function createTopOpt(obj)
            s = SettingsTopOptProblem('ExperimentingPlotRectangle');
            s.designVarSettings.creatorSettings.m1 = obj.dataRes.DesignVar1;
            s.designVarSettings.creatorSettings.m2 = obj.dataRes.DesignVar2;
            s.designVarSettings.creatorSettings.alpha0 =  obj.dataRes.AlphaGauss';
            obj.topOptProblem = TopOpt_Problem(s);
        end

        function solveTopOpt(obj)
            obj.topOptProblem.computeVariables();
            obj.topOptProblem.postProcess();
        end

        function wrapResAndMesh(obj)
            s.folderPath = obj.path;
            s.fileName   = [obj.fileResName,num2str(obj.initialIter)];
            w = WrapperMshResFiles(s);
            w.compute();
            obj.mesh    = w.mesh;
            obj.dataRes = w.dataRes;
        end

        function createDesignVariable(obj)
            s = SettingsDesignVariable();
            s.mesh                  = Mesh_Total(obj.mesh);
            s.type                  = 'MicroParams';
            s.initialCase           = 'full';
            s.scalarProductSettings = obj.createScalarProductParams();
            s.creatorSettings       = obj.createCreatorSettings();
            desVar = DesignVariable.create(s);
            desVar.alpha = obj.dataRes.AlphaGauss';
            obj.designVariable = desVar;
        end

        function s = createScalarProductParams(obj)
            s.epsilon = [];
            s.mesh = obj.mesh;
        end

        function s = createCreatorSettings(obj)
            s.m1 = obj.dataRes.DesignVar1;
            s.m2 = obj.dataRes.DesignVar2;
            s.homogSettings.fileName = obj.vademecumName;
            s.homogSettings.type     = 'ByVademecum';
        end

    end

end


function out=locfit_all(varargin)

% Smoothing noisy data using Local Regression and Likelihood.
%
% This is a combination of the locfit and predict functions
%

% Minimal input validation
if nargin < 1
   error( 'At least one input argument required' );
end

predict_args = {};

locfit_args = varargin{1};

if nargin==2
predict_args = varargin{2};
end;

fit = locfit( locfit_args{:} );

predict_out = predict( fit, predict_args{:} );

out = {fit predict_out};