function coef = plotnsdgt(coef,a,varargin)
%PLOTNSDGT Plot non-stationary Gabor coefficients
%   Usage:  plotnsdgt(c,a,fs,dynrange);
%
%   Input parameters:
%         coef     : Cell array of coefficients.
%         a        : Vector of time positions of windows.
%         fs       : signal sample rate in Hz (optional)
%         dynrange : Color scale dynamic range in dB (optional).
%
%   `plotnsdgt(coef,a)` plots coefficients computed using |nsdgt| or
%   |unsdgt|. For more details on the format of the variables *coef* and *a*,
%   please read the function help for these functions.
%
%   `plotnsdgt(coef,a,fs)` does the same assuming a sampling rate of
%   *fs* Hz of the original signal.
%
%   `plotnsdgt(coef,a,fs,dynrange)` additionally limits the dynamic range.
%
%   `C=plotnsdgt(...)` returns the processed image data used in the
%   plotting. Inputting this data directly to `imagesc` or similar
%   functions will create the plot. This is useful for custom
%   post-processing of the image data.
%
%   `plotnsdgt` supports all the optional parameters of |tfplot|. Please
%   see the help of |tfplot| for an exhaustive list. In addition, the
%   following parameters may be specified:
%
%     'xres',xres  Approximate number of pixels along x-axis / time.
%                  The default value is 800
%
%     'yres',yres  Approximate number of pixels along y-axis / frequency
%                  The default value is 600
%
%   See also: tfplot, nsdgt, unsdgt, nsdgtreal

%   AUTHOR : Florent Jaillet and Peter L. Søndergaard
%   TESTING: OK
%   REFERENCE: NA

if nargin<2
  error('%s: Too few input parameters.',upper(mfilename));
end;

definput.import={'ltfattranslate','tfplot'};

definput.keyvals.xres=800;
definput.keyvals.yres=600;

[flags,kv,fs]=ltfatarghelper({'fs','dynrange'},definput,varargin);

timepos=cumsum(a)-a(1);

N=length(a);
cwork=zeros(kv.yres,N);

%% -------- Interpolate in frequency ---------------------

for ii=1:N
  column=coef{ii};
  M=length(column);
  cwork(:,ii)=interp1(linspace(0,1,M),column,linspace(0,1,kv.yres),'nearest');
end;

%% --------  Interpolate in time -------------------------

% Time step in next equidistant spacing on the x-axis (in samples)
aplot=timepos(end)/kv.xres;

% Time positions where we want our pixels plotted (in samples)
xr=(0:kv.xres-1)*aplot;

% Move zero frequency to the center and Nyquist frequency to the top.
if rem(kv.yres,2)==0
  cwork=circshift(cwork,kv.yres/2-1);
else
  cwork=circshift(cwork,(kv.yres-1)/2);
end;

coef=zeros(kv.yres,kv.xres);
for ii=1:kv.yres
  data=interp1(timepos,cwork(ii,:).',xr,'nearest').';
  coef(ii,:)=data;
end;

yr=[-1+2/kv.yres,1];

coef=tfplot(coef,aplot,yr,'argimport',flags,kv);

if nargout<1
    clear coef;
end


classdef AbstractMesh < handle

    properties (GetAccess = public, SetAccess = protected)
        coord
        connec

        nelem
        ndim

        type

        coordElem
        interpolation

        edges
    end

    properties (Access = private)
       xFE
    end

    methods (Access = public)

       function xV = computeBaricenter(obj)
            xV = obj.xFE.computeValueInCenterElement();
       end

       function xGauss = computeXgauss(obj,xV)
            xGauss = obj.xFE.interpolateFunction(xV);
       end

       function dvolume = computeDvolume(obj,quad)
            s.mesh = obj;
            g = Geometry.create(s);
            g.computeGeometry(quad,obj.interpolation);
            dvolume = g.dvolu;
            dvolume = dvolume';
       end

       function q = computeElementQuality(obj)
            quad = Quadrature.set(obj.type);
            quad.computeQuadrature('CONSTANT');
            volume = obj.computeDvolume(quad);
            L(1,:) = obj.computeSquarePerimeter();
            q = 4*sqrt(3)*volume./L;
       end

       function v = computeVolume(obj)
            quad = Quadrature.set(obj.type);
            quad.computeQuadrature('CONSTANT');
            v = obj.computeDvolume(quad);
            v = sum(v(:));
       end

        function computeEdges(obj)
            s.nodesByElem = obj.connec;
            edge = EdgesConnectivitiesComputer(s);
            edge.compute();
            obj.edges = edge;
        end

    end

    methods (Access = protected)

        function createInterpolation(obj)
            obj.interpolation = Interpolation.create(obj,'LINEAR');
        end

        function computeElementCoordinates(obj)
            obj.computeCoordFEfunction();
            obj.coordElem = obj.xFE.fValues;
        end

    end

    methods (Access = private)

        function computeCoordFEfunction(obj)
            s.mesh    = obj;
            s.fValues = obj.coord;
            obj.xFE = P1Function(s);
        end

        function L = computeSquarePerimeter(obj)
            obj.computeEdges();
            nElem = size(obj.connec,1);
            L = zeros(nElem,1);
            for iedge = 1:obj.edges.nEdgeByElem
                edge = obj.edges.edgesInElem(:,iedge);
                nodesEdge = obj.edges.nodesInEdges(edge,:);
                for idim = 1:obj.ndim
                    xA = obj.coord(nodesEdge(:,1),idim);
                    xB = obj.coord(nodesEdge(:,2),idim);
                    L = L + (xA - xB).^2;
                end
            end
        end

    end

end


function [DF] = df_build(V,C)
% DF_BUILD Build a volumetric distance field and spatial index that can be used
% to speed up approximate NN queries in 3D This code is not optimized, it is
% very slow for big datasets
%
% [DF] = df_build(V,C)
%
% Inputs:
%   V  Coordinates of the points
%   C  Column vector that defines the number of cells for every
%      dimension
% Output:
%   DF  structure to be passed to df_query to execute queries

if ~exist('C','var')
    C=[10;10;10];
end

MIN = min(V,[],1);
MAX = max(V,[],1);

S = (MAX-MIN)./C';
S(S==0) = 0.0000001;

D = zeros(C'+1);
N = zeros(C'+1);

for x=1:size(D,1)
    progressbar(x,size(D,1));
    for y=1:size(D,2)
        for z=1:size(D,3)
            i = [x,y,z];
            p = MIN + (i-1).*S;
            [D(x,y,z) N(x,y,z)] = min(normrow(repmat(p,size(V,1),1)-V));
        end
    end
end

% Prepare DF struct
DF.MIN = MIN;
DF.MAX = MAX;
DF.D = D;
DF.N = N;
DF.C = C;
DF.S = S;
end


function p = getNMSPenalty(B,b)

p = -0.5*(getMaxIncFloat(B',b)+getIOUFloat(B',b));


function imgOut = pyrBlend(img1, img2, weight)
%
%
%        imgOut = pyrBlend(img1, img2, weight)
%
%
%        Input:
%           -img1: an image to be blended
%           -img2: an image to be blended
%           -weight: the weights for img1
%
%        Output:
%           -imgOut: the final blended image
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
%

if(~isSameImage(img1, img2) || ~isSimilarImage(img1, weight))
   error('pyrBlend: input images are different!');
end

col = size(img1, 3);

p1 = pyrImg3(img1, @pyrLapGen);
p2 = pyrImg3(img2, @pyrLapGen);

g1 = pyrGaussGen(weight);
g2 = pyrGaussGen(1 - weight);

imgOut = zeros(size(img1));

for i=1:col
    tpg1 = pyrLst2OP(p1(i), g1,  @pyrMul);
    tpg2 = pyrLst2OP(p2(i), g2,  @pyrMul);
    tf   = pyrLst2OP(tpg1, tpg2, @pyrAdd);

    imgOut(:,:,i) = pyrVal(tf);
end

end


function exact = p02_exact ( )

%*****************************************************************************80
%
%% P02_EXACT returns the exact integral for problem 2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 July 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real EXACT, the value of the integral.
%
  exact = sqrt ( pi );

  return
end


function [ mcmap, cdata_mapped ] = multicmap( h, cmaps, clims )
% MULTICMAP Apply multiple colormaps to image objects
%
%   [MCMAP,CDATA]=MULTICMAP(H,CMAPS,CLIMS) given handles to
%   image objects plotted in the current axes, along with
%   specification of individual colormaps for the image
%   objects, this function combines the individual colormaps
%   into a single multi-colormap matrix, and computes re-mapped
%   CData matrices for individual image objects, so that they
%   point to their respective colormaps within the multi-colormap.
%
%   This function assumes that CData of each image object
%   is a 2D matrix of indexes to the figures colormap
%   (which is the default behavior in MATLAB), as opposed
%   to CData being a 3D matrix of true color RGB image values.
%
%   Not that this routine is a generalization of examples
%   presented in [1].
%
%   Known limitations: currently multiple subplots in a single
%                      figure are not supported.
%
%   Inputs
%           H numeric array (or structure) containing handles
%             to image objects plotted in the current axes
%
%           CMAPS column cell array (or structure) of colormaps
%                 for the image objects specified in H. Each
%                 colormap should conform to MATLAB's colormap
%                 specifications, i.e., it should be an m-by-3
%                 matrix of real numbers between 0.0 and 1.0.
%                 Each row of a given colormap matrix is an RGB
%                 vector that defines one color. See "doc colormap"
%                 for further information regarding MATLAB's colormaps.
%
%           CLIMS m-by-2 matrix, or structure of two element
%                 row vectors, each containing lower and upper
%                 limits for each image object's CData indexes.
%                 See "doc imagesc" for detailed diagram and
%                 explanation of CLIMS.
%
%   Outputs
%           MCMAP m-by-3 colormap matrix composed of individual
%                 colormaps supplied in CMAPS.
%
%           CDATA re-mapped CData matrices as members of a cell array
%                 for individual image objects specified in H.
%
%   References
%           [1] MathWorks: Product Support,
%               "1215 - Using Multiple Colormaps in a Single Figure"
%               url: http://www.mathworks.com/support/tech-notes/1200/1215.html
%
%   Example
%            clear all; close all; clc;
%
%            % Read the sample sample images
%            data.earth = load( 'earth' );
%            data.penny = load( 'penny' );
%
%            % Get indexed images into variables
%            photo.earth = data.earth.X;
%            photo.penny = data.penny.P;
%
%            % Get dimensions of each image
%            dims.earth = size( photo.earth );
%            dims.penny = size( photo.penny );
%
%            % Define x- and y-points for each image
%            x.earth = [ 1:dims.earth(1) ];
%            x.penny = [ 1:dims.penny(1) ] + round((dims.earth(1)-dims.penny(1))/2);
%            y.earth = 1:dims.earth(2);
%            y.penny = [ 1:dims.penny(2) ] + round((dims.earth(2)-dims.penny(2))/2);
%
%            % Define colormaps for each image like so:
%            maps.earth = data.earth.map;
%            maps.penny = hot(64);
%
%            % Define transparency for visible parts of each image
%            alpha.earth = 1;        % fully opaque
%            alpha.penny = 0.7;      % 30% transparency
%
%            % Define which parts of the second image are to be fully transparent (invisible)
%            AlphaData.penny = ones( size( photo.penny ) ) * alpha.penny;
%            AlphaData.penny( photo.penny<5*min(photo.penny(:)) ) = 0;
%
%            % Plot images with their respective colormaps
%            hfig = figure( 'Position', [ 400 10 600 600 ], 'PaperPositionMode', 'auto', 'color', 'w' );
%
%            % Make sure both images get retained in the current axes
%            hold on;
%
%            % Plot images and retain handles to the image objects
%            h.earth = image( x.earth, y.earth, photo.earth );
%            h.penny = image( x.penny, y.penny, photo.penny );
%
%            % Apply transparency settings
%            set( h.earth, 'AlphaData', alpha.earth );
%            set( h.penny, 'AlphaData', AlphaData.penny );
%
%            % Apply axes limits
%            xlim( [ min(struct2array(x)) max(struct2array(x)) ] );
%            ylim( [ min(struct2array(y)) max(struct2array(y)) ] );
%
%            % Make sure our images are not up-side-down
%            axis ij square off
%
%            % Apply colormaps to their respective image objects
%            multicmap( h, maps );
%
%   See also EXAMPLE_TWO_IMAGES, EXAMPLE_THREE_IMAGES, EXAMPLE_SPEECH.

%   Author: Kamil Wojcicki, UTD, February 2012.

    % check for correct number of input arguments
    if nargin<2 || nargin>3
        error( sprintf('Incorrect number of input arguments.\nType "help %s" for usage help.\n', mfilename) );
    end

    % if image object handles were passed-in as values for members
    % of a structure, then convert the structure to a numeric array
    if isstruct( h )
        h = struct2array( h );
    end

    % determine number of image objects
    N = length( h );

    % if individual colormaps were passed-in as matrices for members
    % of a structure, then convert the structure to a cell array
    if isstruct( cmaps )
        cmaps = struct2cell( cmaps );
    end

    % combine colormaps for individual image objects into
    % a single multi-colormap (as a m-by-3 matrix)
    mcmap = cell2mat( cmaps );

    % determine if data limits were specified
    if nargin==3

        % if the data limits were specified as 1-by-2 arrays
        % for member of a structure, then convert the structure
        % to a cell array of data limits
        if isstruct( clims )
            clims = struct2cell( clims );
        end

        % if the data limits are as 1-by-2 arrays, members of
        % a cell array, then convert the cell array into m-by-2 matrix
        if iscell( clims )
            clims = cell2mat( clims );
        end

        % determine the dimensionality of the data limits matrix
        [ rows, columns ] = size( clims );

        % for each image object there should be lower
        % and upper limit for the data (i.e., exactly 2)
        assert( columns==2 );

        % if only one array of data limit values was supplied
        % then use it for all image objects by replicating
        % it for each
        if rows==1
            clims = repmat( clims, N, 1 );

        % otherwise, make sure that the number of supplied
        % data limits matched the number of image objects
        else
            assert( rows==N );
        end

    end

    % for each image object compute CData re-mapped
    % to index to the new multi-colormap.
    for n = 1:N

        % get the image data (assumed to be indices
        % into the figure's colormap)
        cdata = get( h(n), 'CData' );

        % if climits were supplied, apply them
        if nargin==3
            cdata( cdata<clims(n,1) ) = clims(n,1);
            cdata( cdata>clims(n,2) ) = clims(n,2);
        end

        % figure-out the maximum, minimum and range
        % of the current image object's CData
        cdata_max = max( cdata(:) );
        cdata_min = min( cdata(:) );
        cdata_range = cdata_max - cdata_min;

        % get the size of the colormap for the
        % current image object
        cmap_size = size( cmaps{n}, 1 );

        % re-map the CData for the current image object to its colormap
        cdata_mapped{n} = min( cmap_size, round((cmap_size-1)*(cdata-cdata_min)/cdata_range)+1 );

        % re-map the CData for the current image object to its
        % corresponding colormap within the multi-colormap
        if n>1, cdata_mapped{n} = cdata_mapped{n} + max( cdata_mapped{n-1}(:) ); end

    end

    % if no outputs have been requested, then update data for
    % for the individual image objects to the re-mapped data,
    % also set data limits (for plotting) and apply the new colormap
    if nargout==0

        % for each image object update CData to re-mapped data
        for n = 1:N
            set( h(n), 'CData', cdata_mapped{n} );
        end

        % set CData axis limits (for plotting)
        caxis( [ min(cdata_mapped{1}(:)) max(cdata_mapped{end}(:)) ] );

        % apply the new colormap
        colormap( mcmap );

    end

% EOF


classdef HomogenizationTests < handle & matlab.unittest.TestCase

    properties (TestParameter)
            errorTests = {...
                'testNumericalConvergenceOfNumberOfLaminates';
                'testCommutingHomogPlaneStressWithZeroPoisson';
                'testCommutingVoigtHomog';
                'testAnisotropicPlaneStressbyEnergyEquivalence';
                'testStressInPlaneStress';
                'testStressRotationInVoigtNotationIn3D';
                'testStressRotationInVoigtNotationInPlaneStress';
                'testInverseSymmetricFourthOrderTensor' ;
                'testInverseNonSymmetricFourthOrderTensor';
                'testInverseOfInverseForStiffTensor';
                'testIsotropicFourthOrderTensor'
                'testSymmetrizeIsotropicFourthOrderTensor';
                'testSymmetryForIAniTensorInVoigt'
                'testMakeAnisotorpicTensorPlaneStressSymbolically';
                'testEnergyEquivalenceVoigtAndTensorNotationForIsoTensor';
                'testEnergyEquivalenceVoigtAndTensorNotationForIAniTensor';
                'testComplianceTensorThrougtVoigtComparingEnergy';
                'TestTwoRankSequentialLaminate';
                'testHorizontalTensorRotatedVsVPH';
                }
            passedTests = {...
                'testDiagonalLaminate';
                'testHorizontalLaminate';
                'TestGeneralTwoRankSequentialLaminate';
                'testNotCommutingHomogPlaneStress';
                'testSymmetrizeFourthOrderTensor';
                'testHorizontalTensorRotatedVsVHP';
                'testHorizontalTensorRotatedVsRank2';
                'testHorizontalTensorRotatedVsHVP';
                }
            elementdiffreact = {'testHorizontalTensorRotatedVsHVP'};
    end

%     methods (Test, TestTags = {'HomogenizationTests', 'Elementdiffreact'})
%
%         function testsElementdiffreact(testCase, elementdiffreact)
%             testCase.fixFolder();
%             test = eval(elementdiffreact);
%             passed = test.hasPassed();
%             verifyTrue(testCase, passed)
%         end
%
%     end

    methods (Test, TestTags = {'HomogenizationTests', 'ShowingError'})

        function testsError(testCase, errorTests)
            testCase.fixFolder();
            test = eval(errorTests);
            err = test.computeError();
            tol = test.tol;
            testCase.verifyLessThanOrEqual(err, tol)
        end

    end

    methods (Test, TestTags = {'HomogenizationTests', 'NotShowingError'})

        function testsPassed(testCase, passedTests)
            testCase.fixFolder();
            test = eval(passedTests);
            passed = test.hasPassed();
            verifyTrue(testCase, passed)
        end

    end

    methods (Access = private)

        function fixFolder(testCase)
            import matlab.unittest.fixtures.CurrentFolderFixture
            changeToFolder = '../../';
            testCase.applyFixture(CurrentFolderFixture(changeToFolder));
        end
    end

end


function adj_num = ns_adj_count ( node_num, triangle_num, ...
  variable_num, triangle_node, triangle_neighbor, node_u_variable, ...
  node_v_variable, node_p_variable )

%*****************************************************************************80
%
%% NS_ADJ_COUNT counts adjacencies in a Navier Stokes triangulation.
%
%  Discussion:
%
%    This routine is called to count the adjacencies, so that the
%    appropriate amount of memory can be set aside for storage when
%    the adjacency structure is created.
%
%    The value of ADJ_NUM computed and returned by this routine should
%    be identical to the value computed by NS_ADJ_COL_SET.
%
%    The triangulation is assumed to involve 6-node triangles.
%
%    Variables for the horizontal and vertical velocities are associated
%    with every node.  Variables for the pressure are associated only with
%    the vertex nodes.
%
%    We are interested in determining the number of nonzero entries in the
%    stiffness matrix of the Stokes equations, or the jacobian matrix of
%    the Navier Stokes equations.  To this end, we will say, somewhat
%    too broadly, that two variables are "adjacent" if their associated
%    nodes both occur in some common element.  This adjacency of variables
%    I and J is taken to be equivalent to the possible nonzeroness of
%    matrix entries A(I,J) and A(J,I).
%
%    A sparse compressed column format is used to store the counts for
%    the nonzeroes.  In other words, while the value ADJ_NUM reports the
%    number of adjacencies, the vector ADJ_COL is sufficient to allow us
%    to properly set up a sparse compressed matrix for the actual storage
%    of the sparse matrix, if we desire to proceed.
%
%  Local Node Numbering:
%
%       3
%    s  |\
%    i  | \
%    d  |  \
%    e  6   5  side 2
%       |    \
%    3  |     \
%       |      \
%       1---4---2
%
%         side 1
%
%  Variable Diagram:
%
%      UVP
%       |\
%       | \
%       |  \
%      UV   UV
%       |    \
%       |     \
%       |      \
%      UVP--UV--UVP
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 September 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters
%
%    Input, integer NODE_NUM, the number of nodes.
%
%    Input, integer TRIANGLE_NUM, the number of triangles.
%
%    Input, integer VARIABLE_NUM, the number of variables.
%
%    Input, integer TRIANGLE_NODE(6,TRIANGLE_NUM), lists the nodes that
%    make up each triangle.  The first three nodes are the vertices,
%    in counterclockwise order.  The fourth value is the midside
%    node between nodes 1 and 2; the fifth and sixth values are
%    the other midside nodes in the logical order.
%
%    Input, integer TRIANGLE_NEIGHBOR(3,TRIANGLE_NUM), for each side of
%    a triangle, lists the neighboring triangle, or -1 if there is
%    no neighbor.
%
%    Input, integer NODE_U_VARIABLE(NODE_NUM), NODE_V_VARIABLE(NODE_NUM),
%    NODE_P_VARIABLE(NODE_NUM), the index of the horizontal velocity,
%    vertical velocity and pressure variables associated with a node,
%    or -1 if no such variable is associated with the node.
%
%    Output, integer ADJ_NUM, the number of Navier Stokes variable adjacencies.
%
  triangle_order = 6;

  adj_num = 0;
%
%  Set every variable to be adjacent to itself.
%
  adj_num = variable_num;
%
%  Set every variable to be adjacent to the other variables associated with
%  that node.
%
%  U <=> V
%  U <=> P (if there is a P variable)
%  V <=> P (if there is a P variable)
%
  for node = 1 : node_num

    adj_num = adj_num + 2;

    p1 = node_p_variable(node);

    if ( 0 < p1 )
      adj_num = adj_num + 4;
    end

  end
%
%  Examine each triangle.
%
  for triangle = 1 : triangle_num
%
%  For sure, we add the new adjacencies:
%
%    U5 V5 <=> U1 V1 P1
%    U6 V6 <=> U2 V2 P2
%    U4 V4 <=> U3 V3 P3
%    U5 V5 <=> U4 V4
%    U6 V6 <=> U4 V4
%    U6 V6 <=> U5 V5
%
    adj_num = adj_num + 60;
%
%  Add edges (1,2), (1,4), (2,4) if this is the first occurrence,
%  that is, if the edge (1,4,2) is on a boundary (TRIANGLE2 <= 0)
%  or if this triangle is the first of the pair in which the edge
%  occurs (TRIANGLE < TRIANGLE2).
%
%  Maybe add
%
%    U1 V1 P1 <=> U2 V2 P2
%    U1 V1 P1 <=> U4 V4
%    U2 V2 P2 <=> U4 V4
%
    triangle2 = triangle_neighbor(1,triangle);

    if ( triangle2 < 0 | triangle < triangle2 )
      adj_num = adj_num + 42;
    end
%
%  Maybe add
%
%    U2 V2 P2 <=> U3 V3 P3
%    U2 V2 P2 <=> U5 V5
%    U3 V3 P3 <=> U5 V5
%
    triangle2 = triangle_neighbor(2,triangle);

    if ( triangle2 < 0 | triangle < triangle2 )
      adj_num = adj_num + 42;
    end
%
%  Maybe add
%
%    U1 V1 P1 <=> U3 V3 P3
%    U1 V1 P1 <=> U6 V6
%    U3 V3 P3 <=> U6 V6
%
    triangle2 = triangle_neighbor(3,triangle);

    if ( triangle2 < 0 | triangle < triangle2 )
      adj_num = adj_num + 42;
    end

  end

  return
end


function [ Y ] = tapas_rdcm_reduce_zeros(X, Y)
% [ Y ] = tapas_rdcm_reduce_zeros(X, Y)
%
% If there are more zero-valued frequencies than informative ones,
% subsamples those frequencies to balance dataset
%
%   Input:
%   	X           - design matrix (predictors)
%       Y           - data
%
%   Output:
%       Y           - balanced data
%

% ----------------------------------------------------------------------
%
% Authors: Stefan Fraessle (stefanf@biomed.ee.ethz.ch), Ekaterina I. Lomakina
%
% Copyright (C) 2016-2022 Translational Neuromodeling Unit
%                         Institute for Biomedical Engineering
%                         University of Zurich & ETH Zurich
%
% This file is part of the TAPAS rDCM Toolbox, which is released under the
% terms of the GNU General Public License (GPL), version 3.0 or later. You
% can redistribute and/or modify the code under the terms of the GPL. For
% further see COPYING or <http://www.gnu.org/licenses/>.
%
% Please note that this toolbox is in an early stage of development. Changes
% are likely to occur in future releases.
%
% ----------------------------------------------------------------------

% get all indices
idx = 1:size(Y,1);

% data
data = sum(abs([Y X]),2);

% zero frequencies
idx_0 = idx(data == 0);

% number of zero frequencies
n0 = sum(data==0);

% number of non-zero and non NaN frequencies
n1 = sum(data>0);

% balance the data if there are too many zeros
if ( n0 > n1 )
    idx_del = [zeros(1,n1) ones(1,n0-n1)];
    idx_del = idx_del(randperm(n0))>0;
    Y(idx_0(idx_del),:) = NaN;
end

end


function ns3de_test ( )

%*****************************************************************************80
%
%% NS3DE_TEST tests the NS3DE library.
%
%  Location:
%
%    http://people.sc.fsu.edu/~jburkardt/m_src/navier_stokes_3d_exact/ns3de_test.m
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 January 2015
%
%  Author:
%
%    John Burkardt
%
  timestamp ( )
  fprintf ( 1, '\n' );
  fprintf ( 1, 'NS3DE_TEST\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Test the NS3DE library.\n' );

  ns3de_test01 ( );
  ns3de_test02 ( );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'NS3DE_TEST\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  timestamp ( )

  return
end


function [h,h2] = logzplot(varargin)
%Surface plot with log-scaled color and z-axis
%
% SYNTAX
%
%   LOGZPLOT
%   LOGZPLOT(Z)
%   LOGZPLOT(Z,C)
%   LOGZPLOT(X,Y,Z)
%   LOGZPLOT(X,Y,Z,C)
%   LOGZPLOT(...,'PLOTFUN')
%   LOGZPLOT(TriRep,'PLOTFUN')
%   LOGZPLOT(TRI,X,Y,Z,'PLOTFUN')
%   LOGZPLOT(TRI,X,Y,Z,C,'PLOTFUN')
%   LOGZPLOT(...,@PLOTFUN)
%   LOGZPLOT colorbar or LOGZPLOT(...,'colorbar')
%   LOGZPLOT(HANDLE,...)
%   H = LOGZPLOT(...)
%   [H,H2] = LOGZPLOT(...)
%
% DESCRIPTION
%
% LOGZPLOT creates a plot with logarithmic scaling of the z-axis and color
% data.  The plot type can be any of IMAGE, MESH, PCOLOR, SURF, TRISURF or
% TRIMESH, specified as a string or function handle.  The default plot type
% is SURF.  If called without data inputs, LOGZPLOT applies the log-scale
% transformation to an existing surface, patch or image object.  LOGZPLOT
% called with the optional argument 'colorbar' will also create a
% log-scaled colorbar.
%
% LOGZPLOT(Z)
% LOGZPLOT(Z,C)
% LOGZPLOT(X,Y,Z)
% LOGZPLOT(X,Y,Z,C)   Create a log-scaled surface plot using the data in Z
% by first calling SURF() and then transforming the resulting surface
% object.  The optional arguments X and Y specify values for the X and Y
% locations of the elements of Z. If given, X and Y must be specified
% together, and be of the appropriate size for the data in Z.  If the
% optional argument C is given, the surface's color will be based on the
% values in C instead of Z.
%
% LOGZPLOT(...,'PLOTFUN')
% LOGZPLOT(TriRep,'PLOTFUN')
% LOGZPLOT(TRI,X,Y,Z,'PLOTFUN')
% LOGZPLOT(TRI,X,Y,Z,C,'PLOTFUN')
% LOGZPLOT(...,@PLOTFUN)   Use the plotting function specified by the
% string or function handle in PLOTFUN to plot the data. By default, SURF
% is used to generate the plot. Supported plotting functions are SURF,
% MESH, PCOLOR, TRISURF and TRIMESH. The number and type of the data inputs
% depends on the selected plotting function.
%
% For IMAGE plots, the data inputs must be of the form (C) or (X,Y,C),
% where C is the data used to determine the pixel colors, and X and Y
% specify the scales of the x and y axes.  See the documentation for IMAGE
% for more information.
%
% For SURF and MESH plots, the data inputs must be of the form
% (Z), (X,Y,Z), or (X,Y,Z,C).  See the documentation for SURF and MESH for
% more information.
%
% For PCOLOR plots, the data inputs must be of the form (C) or (X,Y,C).
% See the documentation for PCOLOR for more information.
%
% For TRISURF and TRIMESH plots, the data must be input either as a TriRep
% object or as (TRI,X,Y,Z,C) where TRI is the triangulation of the data in
% X and Y, Z is the height data, and C is optional color data to be used
% instead of Z to color the plot.  See the documentation for TRISURF and
% TRIMESH for more information
%
% LOGZPLOT(...,'colorbar')   Additionally creates a log-scaled colorbar.
%
% LOGZPLOT(AX_HANDLE,...)   Uses the existing axes specified by AX_HANDLE
% to create the plot.
%
% H = LOGZPLOT(...)   Returns the handle of the surface, patch or image
% object that has been transformed.
%
% [H,H2] = LOGZPLOT(...)   In addition to the plot object handle, returns
% the handle of the colorbar.
%
% LOGZPLOT   Calling LOGZPLOT with no arguments will apply a log-scale
% transformation to a surface or patch object located in the current axes.
% The first such object found will be used by LOGZPLOT.  If the object has
% already been transformed by LOGZPLOT, calling LOGZPLOT again will have no
% effect.
%
% LOGZPLOT colorbar
% LOGZPLOT('colorbar')   Additionally create a log-scaled colorbar, or
% scale an existing colorbar attached to the axes of the log-transformed
% plot. The resulting colorbar scale should be accurate to the log-scaled
% data.  See the REMARKS section below for more information.
%
% LOGZPLOT(HANDLE)
% LOGZPLOT(HANDLE,'colorbar')   Transform the surface or patch object
% specified by HANDLE, or, if HANDLE refers to an axes, transform a surface
% or patch object located in the specified axes.
%
% REMARKS
%
% If LOGZPLOT is used to transform an existing surface or patch object, the
% color data ('CData' for surface objects, 'FaceVertexCData' for trisurf
% and trimesh patch objects) must be in indexed form.  LOGZPLOT can not
% transform objects with truecolor (RGB) color data, and will exit with a
% warning if called on an object with truecolor color data.  LOGZPLOT sets
% the object's 'CDataMapping' property to 'scaled'.
%
% LOGZPLOT replaces the original color data, CData, with a transformed
% version, log10(CData).  An additional linear scaling is performed on the
% transformed data so that the scale on a colorbar will have the same range
% as the original data.
%
% Changing the value of the axes 'CLim' (color limits) property using
% either the CAXIS command or set(ax_handle,'CLim') will alter the mapping
% of the data to the colormap as described in the documentation for the
% CAXIS command. This is a useful technique to highlight different data
% ranges in the plot.  See Example 2 below.
%
% However, as noted above, the log-transformed data does not result in an
% accurate colorbar scale without an additional (linear) transformation.
% To accurately map the color data to the colorbar's scale after a change
% to the axes 'CLim' property, LOGZPLOT attaches a set of listener
% functions to the axes that correct the color data scaling whenever the
% 'CLim' property is changed.  This allows the user to specify 'CLim'
% values in the same units and range as the original data.
%
% The listener functions were written for MATLAB R2010a, and may not
% function correctly on older releases due to changes in the MATLAB
% graphics system. If problems related to the listener functions occur, set
% the parameter 'listenerEnable' to false in the first section of the
% LOGZPLOT code, just below the help text.  This will disable the listener
% functionality and prevent rescaling of the color data after a CLim
% change.
%
% The scaling of the color data performed by LOGZPLOT introduces numerical
% error. The magnitude of the error depends on the range of the original
% data as well as the values of the axes' CLim property.  The error is
% cumulative, so making many changes to the CLim values can potentially
% result in inaccurate color data.
%
% If an object created or modified by LOGZPLOT is located in an axes with
% non-log-scaled indexed color objects (surface, patch, or image), the
% colorbar scale will not be accurate.  To ensure accurate colorbar scales,
% do not combine a LOGZPLOT-scaled object with non-scaled indexed-color
% objects in the same axes.
%
% LOGZPLOT attempts to avoid re-transforming a previously log-scaled
% plot (from a previous call to LOGZPLOT).  This allows multiple calls
% to LOGZPLOT using the same object, e.g. to add a colorbar after creating
% the plot.
%
% Because MATLAB's OpenGL renderer does not support logarithmic axes, the
% figure's 'Renderer' property must be set to another renderer for proper
% display of the plot.  MATLAB should change the renderer automatically. In
% some cases when using an existing figure for the plot output, the
% renderer will not change automatically, and the log-scale z-axis will not
% display properly.  If this occurs, set the renderer manually using:
%    set(fig_handle,'Renderer','ZBuffer')
% where fig_handle is the handle of the figure in question.  See the
% documentation for 'Figure Properties' for more information.
%
% Compared to other high-level plotting functions, TRIMESH (and to a lesser
% extent TRISURF) offer incomplete support for the specification of an axes
% handle as a target for the plot output in place of gca().  In particular,
% TRIMESH cannot accept an axes handle if the data is specified as a TriRep
% object.  If LOGZPLOT is called with a TriRep object and TRIMESH as the
% plotting function, the plot will be created in the current axes, ignoring
% any axes handle input.
%
% EXAMPLES
%
% % Example 1 - Compare linear and log-scaled surface plots
%
% % Generate some Gaussian data with a small sinusoidal component:
% x = linspace(-10,10,101);
% [X ,Y] = meshgrid(x);
% Z = 5*exp(-(0.82*(X+3.5).^2 + 0.46*(Y-3.5).^2)) + ...
%     0.8*exp(-(0.45*(X-1.5).^2 + 0.95*(Y-1.5).^2)) + ...
%     0.2*exp(-(0.75*(X-4).^2 + 0.85*(Y+1).^2)+(0.7*(X-3)+.3*(Y-1)).^2)+...
%     0.06*exp(-(0.2*(X+2.5).^2 + 0.3*(Y+3.5).^2)) + ...
%     -0.45*exp(-(0.5*(X+3.3).^2 + 1.5*(Y-2.5).^2)) + ...
%     0.0015*sin(2.6*X+1.1*Y-0.2*X.*Y) + ...
%     0.0009*sin(1.3*X+2.1*Y+0.12*X.*Y);
%
% % Scale the data so its range is 1 to 30000:
% minz = 1;
% maxz = 3e4;
% Z = (maxz-minz)*(Z-min(Z(:)))./(max(Z(:))-min(Z(:))) + minz;
%
% % Add a large Gaussian that will swamp the rest of the data:
% Z = Z + 1e6*exp(-2*(X.^2 + (Y-4).^2));
%
% % Linear z-axis with linear color scale:
% figure(1)
% set(1,'position',[254 335 642 471])
% colormap(jet(64))
% h = surf(X,Y,Z); colorbar
% title('Linear Z-scale and Coloring')
% % Almost all of the surface's detail is hidden because both the height
% % scale and color scale are dominated by the single prominent feature of
% % the data.
%
% % Log-scale z-axis with linear color scale:
% % Use SURF, then change the z-axis scaling using set(gca,'ZScale','log').
% figure(2)
% set(2,'position',[254 335 642 471])
% colormap(jet(64))
% h = surf(X,Y,Z); colorbar
% set(gca,'ZScale','log')
% title('Log Z-scale with Linear Coloring')
% % Note how the log-scale z-axis improves the visibility of the small
% % elevation features of the surface. However, the coloring of the surface
% % is not ideal - the variation in color is still concentrated near the
% % top of the surface due to the linear color scale.
%
% % Log-scale plot using LOGZPLOT to achieve both log-scale z-axis and
% % log-scale color:
% figure(3)
% set(3,'position',[254 335 642 471])
% colormap(jet(64))
% logzplot(X,Y,Z,'colorbar')
% title('Logarithmic Z-scale and Coloring')
% % The plot created by LOGZPLOT shows the advantage of using log-scaled
% % color in addition to the log-scaled z-axis.
%
% % Example 2 - Multiple calls to LOGZPLOT, changing the 'CLim' property
%
% % (Using the X,Y,Z data from Example 1)
% figure(4)
% colormap(jet(64))
%
% % Make a surface using pcolor:
% pcolor(X,Y,Z); shading flat
%
% % Call logzplot to transform to the pcolor plot to log-scale:
% logzplot
%
% % Call logzplot again to add a log-scale colorbar:
% logzplot colorbar
%
% % Use the CAXIS command to set the axes CLim parameter (color limits) to
% % highlight the lower range of the data.  The colorbar scale should
% % adjust to the new limits:
% caxis([1 70])
%
% % Call CAXIS again with different CLim values, to highlight the middle
% % range of the data:
% caxis([40 8000])
%
% % One more call to CAXIS to reset the color limits:
% caxis auto
%
%
% See also SURF, MESH, PCOLOR, TRISURF, TRIMESH, CAXIS, IMAGE
%

% $$FileInfo
% $Filename: logzplot.m
% $Path: $toolboxroot/
% $Product Name: logzplot
% $Product Release: 1.2
% $Revision: 1.2.8
% $Toolbox Name: Custom Plots Toolbox
% $$
%
% Copyright (c) 2010-2012 John Barber.
%
% Release History:
% v 1.0 : 2010-Nov-08
%       - Initial release
% v 1.1 : 2010-Nov-30
%       - Added support for TRISURF and TRIMESH plots
%       - Improved memory performance
%       - Improved speed of axes CLim change listener function
%       - Improved colorbar support
% v 1.2 : 2012-May-30
%       - Added support for plots using IMAGE
%       - Added colorbar handle output
%       - Fixed CLim equality test bug
%       - Code cleanup (variable/function names changed, etc.)

%% Defaults and initial values

% Listener enable flag:
% Disable if listener function causes errors
% -- false = disabled
% -- true = enabled (default)
listenerEnable = true;
% listenerEnable = false;  % Uncomment this line to disable listener

% Supported plotting functions:
plotFunList = {'surf','pcolor','mesh','trisurf','trimesh','image'};

% Default values:
% hSurf = [];
% hAx = [];
% pcolorFlag = false;
inputHandle = [];
colorbarFlag = false;
plotFun = @surf;
x = [];
y = [];
z = [];
CData = [];
tr = [];
triRep = [];
badInput = false;
plotFlag = false;

%% Parse inputs
if ~isempty(varargin)

    % Get char arrays and make indices of other classes
    chars = varargin(cellfun(@ischar,varargin));
    numIdx = cellfun(@isnumeric,varargin);
    fHandleIdx = cellfun(@(x)(isa(x,'function_handle')),varargin);
    scalarIdx = cellfun(@isscalar,varargin);
    emptyIdx = cellfun(@isempty,varargin);
    cellIdx = cellfun(@iscell,varargin);
    triRepIdx = cellfun(@(x)(isa(x,'TriRep')),varargin);

    % Make an index of non-empty non-scalar arrays
    numIdx = numIdx & ~scalarIdx & ~emptyIdx;
    numIdx = find(numIdx);

    % Make a cell array with just the function handles
    fHandles = varargin(fHandleIdx);

    % Detect an HG handle if it was given
    handleList = cell2mat(varargin(scalarIdx & ~fHandleIdx & ...
        ~emptyIdx & ~cellIdx));
    inputHandle = handleList(find(ishghandle(handleList),1));
    inputHandle((end-length(inputHandle)+2):end) = [];

    % Test for 'colorbar' and 'plot function name' inputs
    k = 1;
    while k <= length(chars)
        switch lower(chars{k})
            case 'colorbar'
                colorbarFlag = true;
                k = k + 1;
            case plotFunList
                plotFun = str2func(chars{k});
                k = k + 1;
            otherwise
                k = k + 1;
        end
    end

    % If a valid function handle was input, take it
    if ~isempty(fHandles) && ...
            any(strcmp(func2str(fHandles{end}),plotFunList))
        plotFun = fHandles{end};
    end

    % Get the data to be plotted, otherwise, exit with an error
    switch func2str(plotFun)
        case 'image'
            % For image plots, valid inputs are 1 (CData) or 3 (x,y,CData)
            switch length(numIdx)
                case 1
                    z = varargin{numIdx};
                    x = 1:size(z,2);
                    y = 1:size(z,1);
                    plotFlag = true;
                case 3
                    x = varargin{numIdx(1)};
                    y = varargin{numIdx(2)};
                    z = varargin{numIdx(3)};
                    plotFlag = true;
                otherwise
                    badInput = true;
            end

        case {'surf','mesh','pcolor'}
            % For surface plots, valid inputs are 1 (z), 2 (z,CData),
            % 3 (x,y,z), or 4 (x,y,z,CData)
            switch length(numIdx)
                case 0
                    %
                    plotFlag = false;
                case 1
                    z = varargin{numIdx};
                    x = 1:size(z,2);
                    y = 1:size(z,1);
                    plotFlag = true;
                case 2
                    z = varargin{numIdx(1)};
                    CData = varargin{numIdx(2)};
                    x = 1:size(z,2);
                    y = 1:size(z,1);
                    plotFlag = true;
                case 3
                    x = varargin{numIdx(1)};
                    y = varargin{numIdx(2)};
                    z = varargin{numIdx(3)};
                    plotFlag = true;
                case 4
                    x = varargin{numIdx(1)};
                    y = varargin{numIdx(2)};
                    z = varargin{numIdx(3)};
                    CData = varargin{numIdx(4)};
                    plotFlag = true;
                otherwise
                    badInput = true;
            end

        case {'trisurf','trimesh'}
            % For trisurf/trimesh, valid inputs are 1 (TriRep object),
            % 4 (tr,x,y,z) or 5 (tr,x,y,z,CData)
            if find(triRepIdx)
                triRep = varargin{triRepIdx};
                plotFlag = true;
                % Force LOGZPLOT to use gca for trimesh because it does not
                % properly utilize an axes handle input when called with
                % TriRep input
                if ~isempty(inputHandle) && ...
                        strcmp(func2str(plotFun),'trimesh')
                    msgid = [mfilename ':IgnoreInputHandle'];
                    msgtext = ['trimesh does not properly support axes' ...
                        ' handle input.  Using gca() for plot output.'];
                    warning(msgid,msgtext)
                    inputHandle = gca;
                end
            else
                if length(numIdx) == 4
                    tr = varargin{numIdx(1)};
                    x = varargin{numIdx(2)};
                    y = varargin{numIdx(3)};
                    z = varargin{numIdx(4)};
                    plotFlag = true;
                elseif length(numIdx) == 5
                    tr = varargin{numIdx(1)};
                    x = varargin{numIdx(2)};
                    y = varargin{numIdx(3)};
                    z = varargin{numIdx(4)};
                    CData = varargin{numIdx(5)};
                    plotFlag = true;
                else
                    badInput = true;
                end
            end
    end

    % Exit with an error if the inputs didn't work out
    if badInput
        msgid = [mfilename ':InvalidInputs'];
        msgtext = ['Invalid input.  Type ' ...
            'help ' mfilename ' for correct syntax'];
        error(msgid,msgtext)
    end

end % Done parsing input arguments

%% Make/modify plot

% Get handles:
[hFig,hAx,hSurf,priorFlag] = getHandles(inputHandle,plotFlag);

if priorFlag
    % Surface is already scaled, so just call the colorbar subfunction,
    % then exit:
    if colorbarFlag
        hCbar = LogZPlotColorbar(hFig,hAx);
    end

    % Set return values and exit
    if nargout > 0
        h = hSurf;
    end
    if nargout > 1
        h2 = hCbar;
    end

    return
end

if ~plotFlag
    % Determine the plot type and get its CData

    switch get(hSurf,'Type')
        case 'surface'
            CDataName = 'CData';
            % To determine if it is a pcolor plot, check if the ZData is
            % all zeros
            pcolorFlag = all(all(get(hSurf,'ZData')==0));
        case 'patch'
            CDataName = 'FaceVertexCData';
            pcolorFlag = false;
        case 'image'
            CDataName = 'CData';
            pcolorFlag = true; % avoid setting ZScale
    end

    % Now get the CData to work on
    CData = get(hSurf,CDataName);

    % If the CData is RGB, we don't know what to do, so throw a warning
    if size(CData,3) == 3;
        msgid = [mfilename ':TrueColorCData'];
        msgtext = ['The CData of the surface object is truecolor. ' ...
            'The surface will not be transformed'];
        warning(msgid,msgtext)

        % Set return values and exit
        if nargout > 0
            h = [];
        end
        if nargout > 1
            h2 = [];
        end

        return
    end

else % plotFlag == true
    % Make a plot with the user-suppled data

    % If we didn't get any CData as an input, use the ZData
    if isempty(CData)
        CData = z;
    end

    % Handle different plot types
    switch func2str(plotFun)
        case {'surf','mesh'}
            CDataName = 'CData';
            pcolorFlag = false;
            hSurf = plotFun(hAx,x,y,z,CData);
        case 'pcolor'
            CDataName = 'CData';
            pcolorFlag = true;
            hSurf = plotFun(hAx,x,y,CData);
        case {'trisurf','trimesh'}
            CDataName = 'FaceVertexCData';
            pcolorFlag = false;
            if isempty(triRep)
                hSurf = plotFun(tr,x,y,z,CData(:),'Parent',hAx);
            elseif strcmp(func2str(plotFun),'trimesh')
                % Workaround for broken axes handle support in trimesh
                hSurf = plotFun(triRep);
            else
                hSurf = plotFun(triRep,'Parent',hAx);
            end
            CData = get(hSurf,CDataName);
        case 'image'
            CDataName = 'CData';
            pcolorFlag = true;
            if isvector(x), x2 = x; else x2 = x(1,:); end
            if isvector(y), y2 = y; else y2 = y(:,1); end
            hSurf = plotFun(x2,y2,CData,'Parent',hAx);
            set(hAx, 'YDir','normal')
    end

    % Clear x,y,z now that we're done with them.  We are clearing z
    % _before_ we modify CData.  This way, when CData <= z from the
    % assignment statement a few lines above, MATLAB won't need to create
    % a second copy of the data in memory.
    clear x y z tr triRep

end

% Get rid of (CData <= 0) and (CData == Inf)
CData(CData<=0) = NaN;
CData(CData==Inf) = NaN;

% Find min/max
minC = min(CData(:));
maxC = max(CData(:));

% Convert data to log space
CData = log10(CData);

% Normalize the log scaled CData to have the same range as the ZData so
% that the colorbar scale will be correct
CData = minC + (maxC-minC)*(CData-log10(minC))/(log10(maxC/minC));

% Now set the CData of the surface to the normalized CData
set(hSurf,CDataName,CData)

% Make sure we are in 'scaled' CDataMapping mode
set(hSurf,'CDataMapping','scaled')

% Set a flag so we'll know the surface has already been transformed
setappdata(hSurf,'LogZPlotTransformedCData',true)

% Set the Z scale to 'log' if it isn't a pcolor plot
if ~pcolorFlag
    set(hAx,'ZScale','log')
end

% Call the colorbar subfunction
hCbar = [];
if colorbarFlag
    hCbar = LogZPlotColorbar(hFig,hAx);
end

% Store the CData range and set up the listeners
if listenerEnable

    setappdata(hSurf,'LogZPlotCLim',[minC maxC])
    setappdata(hSurf,'LogZPlotCLimOriginal',[minC maxC]);
    try
        fh = @(src,event)CLimChange(src,event,hAx,hSurf,true,CDataName);

        hCLimModeListener = handle.listener(handle(hAx),...
            findprop(handle(hAx),'CLimMode'), 'PropertyPreSet',...
            {@CLimModeChange,hAx,fh});

        hCLimListener = handle.listener(handle(hAx), ...
            findprop(handle(hAx),'CLim'), 'PropertyPostSet', ...
            {@CLimChange,hAx,hSurf,false,CDataName});

        listenerHandles = [hCLimModeListener; hCLimListener];
        setappdata(hSurf,'LogZPlotListeners',listenerHandles)

    catch %#ok<CTCH>
    end

end

% Set return values and exit
if nargout > 0
    h = hSurf;
end
if nargout > 1
    h2 = hCbar;
end

end % End of function logzplot
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function CLimChange(src,evnt,hAx,hSurf,autoFlag,CDataName) %#ok<INUSL>
% Listener function to update hSurf.CData with the proper scaling whenever
% hAx.CLim changes.  Executed post-set.

% Get old and new CLim values
priorCLim = getappdata(hSurf,'LogZPlotCLim');
newCLim = get(hAx,'CLim');

% autoFlag is set when this function is called by the CLimMode pre-set
% listener, signifying that we are going back to 'auto' mode and need to
% scale the data to the original limits.  This handles the case where
% CLimMode is reset after having been set to manual.
if autoFlag
    newCLim = getappdata(hSurf,'LogZPlotCLimOriginal');
end

% If newCLim and priorCLim are the same, no need to do anything
if abs(priorCLim(1) - newCLim(1)) < 10*eps(priorCLim(1)) ...
   && abs(priorCLim(2) - newCLim(2)) < 10*eps(priorCLim(2))
    return
end

% Warn and don't scale data if CLim is <= 0
if any(newCLim<=0)
    msgid = [mfilename ':NegativeCAxisLimit'];
    msgtext = [mfilename ' only supports positive CLim values.  ' ...
               'Colorbar scale will not be accurate.'];
    warning(msgid,msgtext)
    return
end

% Chop up priorCLim
pL = priorCLim(1);
pH = priorCLim(2);

% Chop up newCLim
nL = newCLim(1);
nH = newCLim(2);

% There are two parts to the transformation: 1) Undo the previous
% normalization (restore CData to its original values) 2) Normalize the
% CData to the new CLim.  They are shown here separately, but computed
% in-place in one step by computing the constants K1 and K2 below.

% 1) Undo the previous normalization to priorCLim:
% CData = (CData-pL)*(log10(pH/pL)/(pH-pL)) + log10(pL);

% 2) Normalize CData to new CLim:
% CData = nL+(nH-nL)*(CData-log10(nL))/log10(nH/nL);

% Compute renormalization constants K1,K2
K1 = nL+(nH-nL)/(log10(nH/nL))*(log10(pL)-log10(nL)-pL*log10(pH/pL)/(pH-pL));
K2 = (nH-nL)*log10(pH/pL)/(log10(nH/nL)*(pH-pL));

% Update the surface with the new CData
set(hSurf,CDataName,K1+K2*get(hSurf,CDataName));

% Write the new CLim to appdata:
setappdata(hSurf,'LogZPlotCLim',newCLim);

end % End of function logzplot/CLimChange
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function CLimModeChange(src,evnt,hAx,fhCLimChange)  %#ok<INUSL>
% Listener function to reset the CData using fhCLimChange whenever
% the CLimMode is changed back to 'auto'.  This needs to happen _before_
% the CLimMode is actually changed so that the auto-mode axes refresh uses
% the correct (new) limits instead of basing them on the old CData.

if strcmp(get(hAx,'CLimMode'),'manual')
    fhCLimChange(0,0)
end

end % End of function logzplot/CLimModeChange
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [hFig,hAx,hSurf,priorFlag] = ...
                getHandles(inputHandle,plotFlag)
% Given an input handle and plotFlag, get figure, axes, surface handles and
% priorFlag.

% Default return value unless we find a flag on the surface object
priorFlag = false;

% Return empty for hSurf if plotFlag == true
hSurf = [];

if ~isempty(inputHandle)
    % If we were given a handle, determine its type and then get the other
    % handles we need
    switch lower(get(inputHandle,'Type'))
        case 'axes'
            hAx = inputHandle;
            hFig = ancestor(hAx,'figure');
        case {'surface','patch','image'}
            hSurf = inputHandle;
            hAx = ancestor(hSurf,'axes');
            hFig = ancestor(hSurf,'figure');
        otherwise
            msgid = [mfilename ':InvalidInputHandle'];
            msgtext = ['Input handle must refer to a valid axes or '...
                'surface object'];
            error(msgid,msgtext);
    end
else
    % No input handle so use the current figure and axes
    hFig = gcf;
    hAx = gca;
end

if ~plotFlag
    % If necessary, try to find a surface object
    if isempty(hSurf)
        hSurf = findobj(hAx,'Type','surface','-or','Type','patch',...
            '-or','Type','image');
    end

    % If we couldn't find one, or found more than one, exit
    if isempty(hSurf)
        msgid = [mfilename ':NoSurfaceObject'];
        msgtext = 'Could not locate a surface object to transform';
        error(msgid,msgtext);
    elseif length(hSurf) > 1
        msgid = [mfilename ':MultipleSurfaceObjects'];
        msgtext = [mfilename ' only supports one surface object per axes'];
        error(msgid,msgtext)
    end

    % Check for prior logzplot transformation
    priorFlag = getappdata(hSurf,'LogZPlotTransformedCData');

end

end % End of function logzplot/getHandles
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function hCbar = LogZPlotColorbar(hFig,hAx,hCbar)

if nargin == 2
    % See if there are existing colorbars in the figure
    hCbar = findobj(hFig,'tag','Colorbar');
end

% We only want to modify a colorbar whose peer axes is hAx.  To check this,
% use the not fully documented handle() and h.axes property.  Best to wrap
% this in a try block and do nothing if it fails.
try
    for k = length(hCbar):-1:1
        hTestAx = handle(hCbar(k));
        if (double(hTestAx.axes) ~= hAx)
            hCbar(k) = [];
        end
    end
catch   %#ok<CTCH>
    hCbar = [];
end

% For multiple colorbars, call this function recursively for each one
if length(hCbar) > 1
    for k = 1:length(hCbar)
        LogZPlotColorbar(hFig,hAx,hCbar(k));
    end
    return
end

% If there isn't a colorbar, make it now
if isempty(hCbar)
    hCbar = colorbar('peer',hAx);
end

switch get(hCbar,'Location')
    case {'East','West','EastOutside','WestOutside'}
        scaleName = 'YScale';
    case {'North','South','NorthOutside','SouthOutside'}
        scaleName = 'XScale';
end

% Set the colorbar axes scale to 'log'
set(hCbar,scaleName,'log')

end % End of function logzplot/LogZPlotColorbar
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


function [B, obj] = optimize_B(fft_r, fft_X, para)

%d = length(fft_r);

lambda = para.lambda;
fft_B = fft_X*diag(fft_r); % a N by d matrix
% fft(X) is column-wise fft fft(X,2) is row-wise fft
B_time = ifft(fft_B,[], 2);
B_time = real(B_time);
B = zeros(size(B_time));
B(B_time>=0) = 1;
B(B_time<0) = -1;
%B = B / sqrt(d); % Jan 22

if (para.bit < length(fft_r))
    B(:, para.bit+1:end) = B(:, para.bit+1:end).*0;
    B_time(:, para.bit+1:end) = B(:, para.bit+1:end);
end

obj = sum(sum((B-B_time).^2));
obj = obj + lambda*sum((real(fft_r).^2 + imag(fft_r).^2 - 1).^2);
end


% Copyright 2017 Lime Microsystems Ltd.
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
%    http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
%
% Just for fun, recover ASCII text from DPDCH with BCH(15,11) etc FEC
% Note real encoding uses Viterbi over several radio frames!  Viterbi is more efficient than block coding.
% also have not muxed DPCCH into DPDCH
function [y,evm,din,dout]=WCDMADLtxtMsgRead2( x )
	m=4;
	n=2^m-1; % also from bchpoly (1)
  ply=bchpoly(n);
  szp=size(ply);
  fecLevel=1;
  if fecLevel>szp(1)
    printf("Required FEClevel=%i too high for m=%i reduced to %i\n", fecLevel, m, szp(1));
    fecLevel=szp(1);
  end
	k=ply(fecLevel,2); % from bchpoly (2)
	t=ply(fecLevel,3); % from bchpoly (3)
  agc=1/abs(sqrt(sum(x.*conj(x))/length(x))); % agc as each channel is not a fixed level
  y=x*agc;
	% convert qpsk to bit stream
  qam=[1+i,1-i,-1+i,-1-i]/sqrt(2);
  bitsPerQAMSymbol=2;
	% convert qpsk to bit stream
%	y=WCDMAbpskDemod(x);
	evmref2=sum(abs(qam))/length(qam);
	[evm,loc]=min(abs(repmat(conj(qam'),1,length(y))-repmat(y,length(qam),1))); % decode QAM symbols
%	evm=evm./abs(qam(loc)); % some EVMs define relative to desired symbol
	evm/=evmref2; % some EVMs define relative to rms of QAM symbol table
	din=reshape(de2bi(loc-1,bitsPerQAMSymbol,2,"left-msb")',1,bitsPerQAMSymbol*length(loc)); % convert to binary stream
	bitsPerFrame=length(din);
	%convert bistream back to text
	chars6b=floor(floor(2*length(x)/n)*k/6); % DPDCH is complex x2 data
	symbols=floor(2*length(x)/n);
	framelen=symbols*n;
  y=din(1:framelen); % discarding padding
  y=matdeintrlv(y,n,symbols);% deinterleave
%	y=reshape(reshape(y,40,15)',1,600); % was 10 15 150
	% discard padding bits at end
	y=y(1:framelen);
	% convert into a nx? matrix
	l=size(y);
	y=reshape(y,l(2)/n,n); % group n bits for decoding
	y=bchdeco(y,k,t);
	y=reshape(y,1,k*l(2)/n);
	% convert back to binary, convert to 6 bit words, discarding padding
	dout=y(1:(6*chars6b));
	y=ASCII6dec(dout);
	printf('WCDMAtxtMsgDLRead[%s],BCH(%g,%g)\n', y, n, k );
end

% testing
% a=WCDMAtxtMsgDLWrite2("HelloZ",300);
% WCDMAtxtMsgDLRead2(a)


%
% LibQPEP: A Library for Globally Optimal Solving Quadratic Pose Estimation Problems (QPEPs),
%          It also gives highly accurate uncertainty description of the solutions.
%
%
% Article:
%      Wu,    J.,    Zheng,    Y.,    Gao,    Z.,    Jiang,    Y.,    Hu,    X.,    Zhu,    Y.,    Jiao,    J.,    Liu,    M. (2020)
%           Quadratic Pose Estimation Problems: Unified Solutions,
%           Solvability/Observability Analysis and Uncertainty Description
%           in A Globally Optimal Framework.
%
%
% Authors:      Jin Wu and Ming Liu
% Affiliation:  Hong Kong University of Science and Technology (HKUST)
% Emails:       jin_wu_uestc@hotmail.com; eelium@ust.hk
% Websites:     https://zarathustr.github.io
%               https://ram-lab.com

function sols = solver_WQ_approx(data)
[C0, C1_] = setup_elimination_template_solver_WQ_approx(data);
C1 = C0 \ C1_;
RR = [ - C1(end-12:end, :); eye(27)];
AM_ind = [38, 16, 1, 19, 2, 3, 21, 22, 4, 25, 5, 6, 28, 7, 8, 30, 31, 9, 34, 10, 11, 36, 37, 12, 39, 40, 13];
AM = RR(AM_ind, :);
[V, D] = eig(AM);
V = V ./ (ones(size(V, 1), 1) * V(1, :));
sols = complex(zeros(4, 27));
sols(2, :) = sqrt(V(10, :));
sols(1, :) = V(2, :) ./ (sols(2, :));
sols(3, :) = V(4, :) ./ (sols(1, :));
sols(4, :) = V(3, :) ./ (sols(1, :) .* V(16, :));
end


function [a,b,c] = FCE(L,t)
% finite strain ellipsoid
%
% Syntax
%   [a,b,c] = FCE(L,t)
%   r = FCE(l,t)
%
% Input
%  L -
%  t - time
%
% Output
%

Gamma = L.vorticity;

if nargout == 1

  % r = log(a/c)
  a = 2 * asinh(sinh(sqrt(1-Gamma.^2)) .* L.strainRate .* t ./ sqrt(1-Gamma.^2));

else

end


function varargout = input_medit(V,F,C)
  % INPUT_MEDIT  Display input mesh using medit, highlighting boundary
  % edges and non-manifold edges
  %
  % C = input_medit(V,F,C)
  %
  % Inputs:
  %   V  #V by 3 list of mesh positions
  %   F  #F by 3 list of triangle indices
  %   Optional:
  %     C  #C connected component IDs
  %

  % Gather boundary and non-manifold edges
  NME = nonmanifold_edges(F);
  BE = outline(F);
  BE = setdiff(BE,NME,'rows');
  E = [NME 1+0*NME(:,1); ...
        BE 2+0*BE(:,1);];
  if ~exist('C') || isempty(C)
    C = randcycle(connected_components(F));
    C = C(:);
    % hack so that not all equal (medit doesn't like that)
    if all(C==C(1))
      C(ceil(rand*size(C,1))) = C(1)+1;
    end
  end
  if size(C,1)<size(V,1)
      C(size(V,1)) = 0;
      C(C==0) = max(C(:))+1;
  end
  % Gather self-intersecting faces
  ND = doublearea(V,F)>0;
  [~,~,IF] = selfintersect(V,F(ND,:),'DetectOnly',true);
  bad = false(size(F,1),1);
  bad(ND) = full(0<sparse(IF(:),1,1,sum(ND),1));
  F = [F bad];
  medit(V,[],F,'Data',C,'Edges',E,'Wait',false);
  if nargout>0
    varargout{1} = C;
  end
end


function X = tenrand(varargin)
%TENRAND Uniformly distributed pseudo-random tensor.
%
%   X = TENRAND(SZ) forms a tensor of size SZ with pseudo-random
%   values drawn from a uniform distribution on the unit interval.
%
%   TENRAND(SZ) is equivalent to TENSOR(RAND(SZ(1),SZ(2),...),SZ).
%
%   See also TENSOR, SPTENRAND, RAND.
%
%MATLAB Tensor Toolbox.
%Copyright 2015, Sandia Corporation.

% This is the MATLAB Tensor Toolbox by T. Kolda, B. Bader, and others.
% http://www.sandia.gov/~tgkolda/TensorToolbox.
% Copyright (2015) Sandia Corporation. Under the terms of Contract
% DE-AC04-94AL85000, there is a non-exclusive license for use of this
% work by or on behalf of the U.S. Government. Export of this data may
% require a license from the United States Government.
% The full license terms can be found in the file LICENSE.txt

if nargin == 1
    sz = varargin{1};
else
    sz = cell2mat(varargin);
end

data = rand([sz 1 1]);
X = tensor(data,sz);


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

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @defmethod @@sym null (@var{A})
%% Basis for the nullspace of a symbolic matrix.
%%
%% Return a matrix whose columns are a basis for the nullspace of
%% the matrix.
%% Examples:
%% @example
%% @group
%% A = sym([1 1; 2 0]);
%% null (A)
%%   @result{} (sym) []  (empty 2×0 matrix)
%% @end group
%%
%% @group
%% A = sym([1 2; 1 2]);
%% null (A)
%%   @result{} (sym 2×1 matrix)
%%
%%       ⎡-2⎤
%%       ⎢  ⎥
%%       ⎣1 ⎦
%% @end group
%%
%% @group
%% A = sym(zeros(2,2));
%% null (A)
%%   @result{} (sym 2×2 matrix)
%%
%%       ⎡1  0⎤
%%       ⎢    ⎥
%%       ⎣0  1⎦
%% @end group
%% @end example
%%
%% @seealso{@@sym/rank, @@sym/orth}
%% @end defmethod

function r = null(A)

  cmd = { 'A = _ins[0]'
          'if not A.is_Matrix:'
          '    A = sympy.Matrix([A])'
          'ns = A.nullspace()'
          'if len(ns) == 0:'
          '    return sympy.zeros(A.cols, 0),'
          'return sympy.Matrix.hstack(*ns),' };

  r = pycall_sympy__ (cmd, A);

end

%!test
%! A = sym([1 2; 3 4]);
%! assert (isempty (null (A)))

%!assert (isempty (null (sym(4))))

%!test
%! A = sym([1 2 3; 3 4 5]);
%! assert (isequal (null(A), sym([1;-2;1])))


function points = duplicateGerms(lx, ly, points)
% Duplicate germs for voronoi periodic boundary condition.
%
%   GERMS2 = duplicateGerms(LX, LY, GERMS);
%   LX and LY are vectors containing positions of pixels in an image
%   GERMS are points within thin image
%   The result is the set of germes repeated in each of the 8 directions
%   aroundthe central image. The number of returned points is 9 times the
%   number of input points.
%
%   Example
%   duplicateGerms([1 100], [1 100], rand(30, 2)*100);
%
%   See also
%     imvoronoi2d, imAWVoronoi, imPowerDiagram
%

% ------
% Author: David Legland
% e-mail: david.legland@inrae.fr
% Created: 2009-05-29,    using Matlab 7.7.0.471 (R2008b)
% Copyright 2009 INRA - Cepia Software Platform.

N = size(points, 1);

% width of window in each dimension
if length(lx)>1
    width = [lx(end)-2*lx(1)+lx(2) ly(end)-2*ly(1)+ly(2)];
else
    width = [lx ly];
end

% duplicate the array of points with same coordinates
points = repmat(points, [9 1]);

% add x-shift for left points
for i=[1 2 3]
    points((i-1)*N+1:i*N, 1) = points((i-1)*N+1:i*N, 1) - width(1);
end

% add x-shift for right points
for i=[7 8 9]
    points((i-1)*N+1:i*N, 1) = points((i-1)*N+1:i*N, 1) + width(1);
end

% add y-shift for bottom points
for i=[1 4 7]
    points((i-1)*N+1:i*N, 2) = points((i-1)*N+1:i*N, 2) - width(2);
end

% add y-shift for top points
for i=[3 6 9]
    points((i-1)*N+1:i*N, 2) = points((i-1)*N+1:i*N, 2) + width(2);
end


%% The Index of EBSD data
%
%%
% In previous chapters we have discussed how to select EBSD data by
% properties. In this chapter we are intested in the order the EBSD are
% stored within MTEX. Lets start by importing some sample data

mtexdata twins

%%
% and restricting it to very small rectangular subset

poly = [44 0 4 2];
ebsd = ebsd(inpolygon(ebsd,poly));

plot(ebsd,ebsd.orientations,'micronbar','off','edgecolor','k')

%%
% In the above plot each square corresponds to one entry in the variable
% |ebsd|. Lets visualize the order

text(ebsd,1:length(ebsd))

%%
% We may easily select specific measurement pixels by specifying their
% indeces

hold on
plot(ebsd(16:18),'edgeColor','red','facecolor','none','linewidth',4)
legend off
hold off

%%
% Whether lines or columns run first is not related to MTEX but inherits
% from the ordering of the imported EBSD data. Since, we have restricted
% our large EBSD map to the small subset the indece of restricted data does
% not coincide with the indece of the imported data anymore. However, the
% original indeces are still stored in |ebsd.id|. Lets visualize them

plot(ebsd,ebsd.orientations,'micronbar','off','edgecolor','k')
text(ebsd,ebsd.id)

%%
% In order to select EBSD data according to their original id use the
% option |'id'|, i.e.,

hold on
plot(ebsd('id',316:318),'edgeColor','red','facecolor','none','linewidth',4)
legend off
hold off

%% Square Grids
%
% In the cases of gridded data it is often useful to convert them into a
% matrix form.

ebsd = ebsd.gridify;

plot(ebsd,ebsd.orientations,'micronbar','off')

[i,j] = ndgrid(1:size(ebsd,1),1:size(ebsd,2));
str = arrayfun(@(a,b) ['(' int2str(a) ',' int2str(b) ')'],i,j,'UniformOutput',false);
text(ebsd,str)

%%
% This allows to select EBSD data simply by their coordinates within the
% grid, e.g., by

hold on
plot(ebsd(2,2:4),'edgeColor','red','facecolor','none','linewidth',4)
legend off
hold off

%%
% Note that the <EBSD.gridify.html |gridify|> command changes the order of
% measurements. They are now sort such that rows runs first and columns
% second, as this is the default convention how Matlab indexes matrices.

plot(ebsd,ebsd.orientations,'micronbar','off')
text(ebsd,1:length(ebsd))

%% Hexagonal Grid
%
% The command <EBSD.gridify.html |gridify|> may also be applied to EBSD
% data measured on a hexagonal grid.

mtexdata titanium silent

ebsd = ebsd.gridify

%%
% This rearranges the measurements in a matrix form which can be indexed
% similarly as in the square case.

ebsd = ebsd(10:16,68:79);

%%
% Lets visualize the matrix coordinates for the hexagonal grid

plot(ebsd,ebsd.orientations,'edgeColor','k','micronbar','off')
axis off

[i,j] = ndgrid(1:size(ebsd,1),1:size(ebsd,2));
str = arrayfun(@(a,b) ['(' int2str(a) ',' int2str(b) ')'],i,j,'UniformOutput',false);
text(ebsd,str)

%% Cube Coordinates
% In hexognal grids it is sometimes advantageous to use three digit cube
% coordinates to index the cell. This can be done using the commands
% <EBSDhex.hex2cube.html |hex2cube|> and <EBSDhex.cube2hex.html
% |cube2hex|>. Much more details on indexing hex grids can be found at
% <https://www.redblobgames.com/grids/hexagons/ here>.

plot(ebsd,ebsd.orientations,'edgeColor','k','micronbar','off')
axis off

[i,j] = ndgrid(1:size(ebsd,1),1:size(ebsd,2));
[x,y,z] = ebsd.hex2cube(i,j);
str = arrayfun(@(a,b,c) ['(' int2str(a) ',' int2str(b) ',' int2str(c) ')'],x,y,z,'UniformOutput',false);
text(ebsd,str)


 function y = mtimes_block(ob, x, iblock, nblock)
%function y = mtimes_block(ob, x, iblock, nblock)
% y = G(i'th block) * x	or y = G'(i'th block) * x
% in either case the project data will be "small"
% iblock is 1,...,nblock

% support 'exists' option for seeing if this routine is available
if nargin == 2 & ischar(x) & streq(x, 'exists')
	y = 1;
	return
end

if nargin ~= 4, ir_usage, end

nb = ob.nb;
na = ob.na;

%
% forward projection
%
if ~ob.is_transpose
	if ob.apower ~= 1, error notdone, end

	% if needed, expand concise column
	if ob.is_masked
		idim = size(x);
		np = sum(ob.mask(:));
		nxy = numel(ob.mask);
		if idim(1) ~= np
			error 'size mismatch'
		end
		x = embed(x, ob.mask);
		x = reshape(x, nxy, idim(2));
	end

	y = double(wtfmex('chat', ob.chat, 'proj,block', single(x), ...
		int32(iblock-1), int32(nblock)));

	% fix: extract the relevant columns - should do in wtfmex?
	ia = iblock:nblock:na;
	nv = length(ia);

	if ndims(y) == 3			% [nb,na,nz]
		y = y(:,ia,:);			% [nb,nv,nz]

	elseif size(y,1) == nb*na		% [nba,nz]
		nz = size(y,2);
		y = reshape(y, nb, na, nz);	% [nb,na,nz]
		y = y(:,ia,:);			% [nb,nv,nz]
		y = reshape(y, nb*nv, nz);	% [nb*nv,nz]

	elseif size(y,1) == nb			% [nb,na]
		y = y(:,ia);			% [nb,nv]
	else
		error size
	end

%
% backprojection
%
else
	if ob.apower ~= 1, error notdone, end

	ia = iblock:nblock:na;
	nv = length(ia);

	if ndims(x) == 3		% [nb,nv,nz]
		error todo

	elseif size(x,1) == nb*nv	% [nb*nv,nz]
		nz = size(x,2);
		tmp = zeros(nb, na, nz);
		tmp(:,ia,:) = reshape(x, [nb nv nz]);
		x = reshape(tmp, [nb*na nz]);

	elseif size(x,1) == nb		% [nb,nv]
		error todo

	else
		error bug
	end

	y = double(wtfmex('chat', ob.chat, 'back,block', single(x), ...
		int32(iblock-1), int32(nblock)));

	if ob.is_masked
		if size(y,1) == numel(ob.mask)
			y = y(ob.mask,:);	% [nxy,nz] -> [np,nz]
		else
			y = y(ob.mask);		% [nx,ny] -> [np]
		end
	end
end


function [X] = spm_dot(X,x,i)
% Multidimensional dot (inner) product
% FORMAT [Y] = spm_dot(X,x,[DIM])
%
% X   - numeric array
% x   - cell array of numeric vectors
% DIM - dimensions to omit (asumes ndims(X) = numel(x))
%
% Y  - inner product obtained by summing the products of X and x along DIM
%
% If DIM is not specified the leading dimensions of X are omitted.
% If x is a vector the inner product is over the leading dimension of X
%
% See also: spm_cross
%__________________________________________________________________________
% Copyright (C) 2015 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_dot.m 7314 2018-05-19 10:13:25Z karl $

% initialise dimensions
%--------------------------------------------------------------------------
if iscell(x)
    DIM = (1:numel(x)) + ndims(X) - numel(x);
else
    DIM = 1;
    x   = {x};
end

% omit dimensions specified
%--------------------------------------------------------------------------
if nargin > 2
    DIM(i) = [];
    x(i)   = [];
end

% inner product using recursive summation (and bsxfun)
%--------------------------------------------------------------------------
for d = 1:numel(x)
    s         = ones(1,ndims(X));
    s(DIM(d)) = numel(x{d});
    X         = bsxfun(@times,X,reshape(full(x{d}),s));
    X         = sum(X,DIM(d));
end

% eliminate singleton dimensions
%--------------------------------------------------------------------------
X = squeeze(X);

return

% NB: alternative scheme using outer product
%==========================================================================

% outer product and sum
%--------------------------------------------------------------------------
x      = spm_cross(x);
s      = ones(1,ndims(X));
S      = size(X);
s(DIM) = S(DIM);
x      = reshape(full(x),s);
X      = bsxfun(@times,X,x);
for d  = 1:numel(DIM)
    X  = sum(X,DIM(d));
end
X      = squeeze(X);


% std_comppol() - inverse component polarity in a component cluster
%
% Usage: [compout pol] = std_comppol(compin);
%
% Inputs:
%    compin  - component scalp maps, one per column.
%
% Outputs:
%    compout - component scalp maps some of them with inverted
%              polarities, one per column.
%    pol     - logical vector of component with inverted
%              polarities (same length as the number of rows in
%              compin)
%
% Author: Arnaud Delorme & Hilit Serby, SCCN, INC, UCSD, 2004

% Copyright (C) 2004 Arnaud Delorme, Salk Institute, arno@salk.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function [compin, pol] = std_comppol(compin);

if nargin < 1
    help std_comppol;
    return;
end;

% remove the NaN
% --------------
for index = 1:size(compin,2)
    compin(isnan(compin(:,index)),:) =[];
end;

% run several iterations
% ----------------------
pol     = ones(1,size(compin,2));
for repeat=1:3
    compave = mean(compin,2);
    for index = 1:size(compin,2)

        % remove diagonal and put 0 and 1
        % -------------------------------
        if ~all(compin(:,index) == 0)
             r = corrcoef(compave, compin(:,index) );
        else r = zeros(2,2);
        end;

        % invert component polarities
        % ---------------------------
        if r(2) < 0
            compin(:,index) = -compin(:,index);
            pol(index)      = -pol(index);
        end;
    end;
end;


function errs = Fsampson(F,u);
% FSAMPSON ... first order geometrical error (Sampson Distance)
% errs = Fsampson(F,u);
% F ... 3x3 Fundamental matrix
% u ... 6xN point pairs homogenous
%
% errs ... 1xN error for each point pair
%
% $Id: Fsampson.m,v 1.1 2005/05/23 16:15:59 svoboda Exp $

N = size(u,2);

u1 = u(1:3,:);
u2 = u(4:6,:);

errs = zeros(1,N);
for i=1:N
  Fu1 = F*u1(:,i);
  Fu2 = F'*u1(:,i);
  errs(i) = (u2(:,i)'*F*u1(:,i))^2 / (sum([Fu1(1:2)'.^2,Fu2(1:2)'.^2]));
end


function  [cct, ta1, tetael] = srcintf1(la, nn1, ct4, src4, src5, ctc0, ctad, nprimtilt, lmax, K, stfname)
% srcintf1.m integrates the source including polarisation over conformal time using the approach of Seljak :
% integration over the photon past light cone, see M Zaldarriaga et al., ApJ nr 494, 491 (1998) for K > 0
% the function needs an l-range (la), a k-range (nn1) a ctime-range (ct4), the present conformal time (ctc0),
% decoupling time (ctad), the source in conformal time for the temperature and polarisation, resp
% src4(1..lct4, 1..lnn1), src5(1..lct4, 1..lnn1), the index of the primary power spectrum (nprimtilt),
% the maximum la of the anistropy spectrum (lmax) and the curvature energy content from the Friedman equation (K),
% the startfile name of the ultra-spherical function (stfname).
%
% output: ctt is the square of the temperature spectrum (1) resp the E-polarisation spectrum (2)
% resp the cross-correlation of temperature and polarisation (3), tetatl, tetael temperature resp, polarisation
% temperature for all k1 values (for the last la).
%
% D Vangheluwe 13 june 2005
% remark 1a: attention :nn1 is an integer array :wavenumber array k1 is made from it by taking k1 = nn1 * sqrt(K)
% remark 1: we use ultra-spherical bessel values which have two parameters and must be found by integration:
%   for the calculation of the ultra-spherical bessel functions see: cmb/usphint.m
% remark 2: for the ode equation of the u-function, see equation (36) of Zaldarriaga & Seljak.
% remark 3: take attention the value of nn1 should lie within the range of kb1 values : there is no check!!
%   see spline of start  values x10 and pbd0.
% remark 4: how do we get the ultra-spherical bessel function values? see development and test routine usphpar.m
%  and usphpar1.m
% remark 5: this function is a fast version of srcpint.m (the source need not to be in the loop
% if there is enough memory, probably 80Mbytes will be used)
% remark6 on 13 june: this routine has been obtained by modifying srcpintf.m according to usphpar1.m

if (K < 0),
   error('the space curvature constant K should be > 0 for this routine');
   return;
end
kk0 = sign(K);
lla = size(la, 2);
k1 = nn1 * sqrt(K);
lk1 = size(k1, 2);
lct4 = size(ct4, 2);
k1step = k1(2) - k1(1);
ct4step = ct4(2) - ct4(1);
k1max = k1(lk1);
k1min = k1(1);
ct4sym = 0.5 * pi/sqrt(K);

% if necessary adapt the source to the period of the ultra-spherical function for K >0
ct0 = ct4(1);
ict1 = 1 : lct4;
if ct4sym < ct4(end)
   ctc4 = ctc0 - ct4;
   ict1 = find(ctc4 < ct4sym);
   lct1 = size(ict1,2);
%   ct0 = ctc0 - ct4sym;
   ct0 = ct4(ict1(1));
% map the region ctc4 >= ct4sym onto ict1 by mirroring it wrt the point: ctc4 = ct4sym
   ict2 = find(ctc4 < ct4sym  &  ctc4 > 2*ct4sym - ctc0 + ct4step);
% values of ct4 to be used to calculate (by interpolation) the mirrored source values:
   ct44 = 2*(ctc0 - ct4sym) - ct4(ict2);
% define a (small) region (index icts) where the source changes rapidely and should be splined for reconstruction:
% ct4(icts(1..end)) is projected onto ct44s(end..1) :notice that the index is inverted, the phaseshift between
% the two amounts to : 2*rem(ctc0 - ct4sym - ct4(1), ct4step).
% The same phaseshift and index inversion exists also between ct4(ict1(1..end) and ct44(end..1)
% icts and ict3 have the same size and take attention that they can be empty for ctc0 - ctad +100 < ct4sym!!
   ctcsmin = 2*ct4sym - ctc0 + (ctad - 100);
   ctcsmax = 2*ct4sym - ctc0 + (ctad + 100);
   icts = find((ct4 < ctad + 100)  &  (ct4 >= ctad - 100)  &  (ctc0 - ct4 >= ct4sym));
   ict3 = find(ctc4(ict2) < ctcsmax  &  ctc4(ict2) >= ctcsmin);
   if ~isempty(ict3),    ct44s = ct44(ict3); end
end

% load the table and find the start values for the integration of the ode for u-functions
% the startfile can be obtained by running usphst.m
%  stv1 = load('usphst.dat');
stv1 = load(stfname);
lmax0 = stv1.ust.la(end);

nrsteps = 10000;   % default 10000
%lmax = 1500;
xmax = k1(lk1) * ctc0;   % =default 3000
xstep = 2*lmax0/nrsteps;
kx = 1e-12 : xstep : xmax;

% allocate the data in order to speed up the routine
kctc0 = zeros(1, lct4);
kctc = zeros(1, lct4);
jl = zeros(lct4, 1);
htable = zeros(lct4, 1);
cmbtable = zeros(1, lk1);

% calculate the curvature length times wavenumber : a parameter for the ultra_spherical bessel function
kb = sqrt(abs(K)) ./k1;

%#########
%kb(1)
%kb(end)
if all(kb == 0), kbzero = 1; x10 = 1e-12 * ones(1, lk1);
else  % not all kb are zero

   kbzero = 0;
   ikb = find(kb > 10);
   if ~isempty(ikb),
      kb(ikb) = 10 * ones(1, size(ikb, 2));
      message('boundary kb > 10 reached')
   end

% split the structure stv1 from the startfile : x1: start values where pbi_beta = 1e-6,
% pbd : dphi_beta/dx at the start values, all data exact within 1e-6.
% the la-values resp kb-vector should be the same as in the program usphst.m
   la1 = stv1.ust.la;
   lla1 = size(la1, 2);
   kb2 = stv1.ust.kb;
   x1v1 = stv1.ust.x1;
   pbdv1 = stv1.ust.pbd;

end %all(kb == 0)

%############################# start
for il = 1:lla

    l = la(il)
    laa = sqrt(l * (l + 1));

% make a range of wavenumber and kb starting at 1/(l+1)
    clear('k2')
%    ik2 = (l+1) : lk1;
    ik2 = find(nn1 >= l+1);
    k2 = k1(ik2);
    lk2 = size(k2, 2);
    nn2 = nn1(ik2);
    cmbtable = zeros(1,lk2);

% the range of indices in src for k2 will be ik2 : take care, do not neglect!!:
    k2min = k2(1);
    k2max = k2(lk2);
    tetatl = zeros(1, lk2);
    tetael = zeros(1, lk2);
    kb = sqrt(abs(K)) ./k2;
    odd_la = xor(rem(nn2,2), rem(l,2));

% the kb-range is made more progressive towards 1/la
    nrkbsteps = 100;
    kbmax = 1/laa;
    ekbmax = -7;
    ekbmin = log(kbmax - 1e-5)/log(10);
    ekbstep = (ekbmax - ekbmin)/nrkbsteps;
    ekb1 = ekbmin : ekbstep : ekbmax;
    kb1 = kbmax - 10 .^ekb1;
    lkb1 = size(kb1, 2);
    if l == la1(1)
        if any(kb1 ~= kb2)  error('kb vector is unequal to the start vector'); return; end
    end

% find the start values (hs) for the ode integration step as a function of la and kb (is a surface):
% the long sought magic formula : la1 is the la-vector from usphst1.m!!
    hs = 0.5 * x1v1 .* repmat((la1 .^-0.9)', 1, lkb1);
    if ~kbzero
       il1 = find(la1 == l);
       if isempty(il1)
           error('la not in the range of la1')
           break;
       else
           x10 = spline(kb1, x1v1(il1,:), kb);
           pbd0 = spline(kb1, pbdv1(il1,:), kb);
           hstart = spline(kb1, hs(il1,:), kb);
       end

% calculate the start values for the u-function : u0 = [u, du/dx] with u = r(x) * phi_beta(x) and
%  du/dx = phi_beta(x) * dr(x)/dx + r(x) * dphi_beta(x)/dx :
       r10 = sin(kb .* x10) ./kb;
       rd10 = cos(kb .* x10);
       u0 = [r10 *1e-6; r10 .* pbd0 + 1e-6 * rd10];

% define the step and set 'odeint' to a constant number of steps for all cases (kb)
       toi = 1e-4;
       hmax = 0.3;   %we take hmax = 0.3 as the default value
       maxstp = 150;   % default maxstp = 150
       x1e = ones(1, lk2) * xmax;
% solve the u-function instead of the phi_beta function : xs2 does not have a constant step
       [xs2, u2, nok, nbad, nfev] = odeintp(u0, x10, x1e, toi, hstart, 0, hmax, maxstp, @uspheq1, l, kb, kk0);

% prepare a spline of the solution for a constant step in xs (the values are found with ppval1):
       y2der = splinep(xs2, u2);
% calculate the number of constant steps, xstep in the solution xs2: ilast is the last one
%       ilast = ceil((xs2(end,:) - x10)/xstep);
% set the number of overlapping steps for the matching to the asymptotic solution (default= 40):
       noverflow = 85;
       ncsteps = 0;

    end  % kbzero

% calculate also the spherical bessel function as we may need it for kb < 1e-5
    table_bv = sphbes(l, kx);
% set some constants needed for the polarisation formula
    gl = sqrt((l + 2) * (l + 1) * l * (l - 1));

% interpolate and integrate (sum with the Simpson rule) over conformal time :
    for i = 1:lk2
%    for i = 47:47

       clear('htable')
       if kb(i) > 1e-5 * (1500/l)

% define a vector of argument values for the ultra-spherical bessel function (x1): reverse ct4
%          clear('xs', 'x1', 'x2', 'yspl2','iover')
          x1 = x10(i) : xstep : xmax;
% define some parameters for the calculation ; x1=x1sym up to the symmetry point, x1* kb = pi/2 needed for K>0 :
          x1sym = min(0.5*pi/kb(i), xmax);
% in the next 10 lines make a table over x1 (ul) of ultra-spherical bessel values:

          if  xs2(end,i) >=  x1sym

% asymptotic expansion is not needed here as we found already the complete solution: include one point xs2 > x1sym+xstep
% adding xs2step + xstep to x1sym in the find logic statement of xs2 makes sure that xs(end) > x1(ilast) > x1sym
             xs2step = max(diff(xs2(:,i)));
             ix2 = find(xs2(:,i) <= (x1sym + xs2step + xstep));
% include one point xs2 > x1sym in the interpolation of the ode solution:
%             ix2 = [ix2', (ix2(end) + 1)];
             [xs, yspl2] = ppval1(xs2(ix2,i), u2(ix2,i), y2der(ix2,i), xstep);
%             ilast = floor((x1sym - x10(i))/xstep) + 1;
             ilast = floor((x1sym - x10(i))/xstep) + 2;

          else  % all steps in odeint are used (full interpolation) : an asymptotic solution is needed

             [xs, yspl2] = ppval1(xs2(:,i), u2(:,i), y2der(:,i), xstep);
             ilast = floor((xs(end) - x10(i))/xstep) + 1 - ncsteps;
% define the overflow index (iover): default 85 (or 40) steps should at least include one zero and one maximum of u2
             iover = (ilast - noverflow) : ilast;

% find the asymptotic values and the phase correction in the overflow region:
             dphi = phdif(x1(iover), usphas(l, kb(i), x1(iover), 0, 0, kk0), yspl2(iover));

          end

% calculate the ultra-spherical bessel values
          kctc0 = ctc0 * k2(i) * ones(1, lct4);
          kctc = k2(i) * ct4;
          xctc = kctc0 - kctc;
% xctc > x1(1) is necessary as x1(1)=x10 is not the origin of ct, but the point where odeint started
          if   xs2(end,i) >=  x1sym
% debug action 12-6-2005 : interpolation over xs limits our range to xs(end) at most if it happens xs(end) < x1sym
%             ixode = find(xctc > x1(1)  &  xctc <= x1sym);
             ixode = find(xctc > x1(1)  &  xctc <= min(x1sym, xs(end)));
          else
             ixode = find(xctc > x1(1)  &  xctc <= x1(ilast));
          end
          ul = zeros(1, lct4);
          if  ~isempty(ixode)
             r1 = sin(kb(i) * xs)/kb(i);

% interpolate the ultra-spherical bessel function when we are in the k-range of the ode solution
             ul(ixode) = interpl(xs, yspl2 ./ r1, xctc(ixode));
% calculate the necessary values of the asymptotic expansion of the ultra-spherical bessel function
             if  (xs2(end,i) <  x1sym)   % asymptotic expansion needed for K>0
                ixas = find(xctc > x1(ilast)  &  xctc <= x1sym);
                ul(ixas) = usphas1(l, kb(i), xctc(ixas), dphi, 1, kk0);
             end

% if necessary adapt the source to the period of the ultra-spherical function for K >0 by mirroring:
% we should have: find(k2(i)* (ctc0 - ct4(ict1)) < x1sym) == find(xctc < x1sym) == ict1
             src41 = src4(:,ik2(i));
             src51 = src5(:,ik2(i));
             if  ct4sym < ct4(end)
% reconstruct the source by linear interpolation : not so accurate but sufficient where changes are slow
                src42 = interpl(ct4, src4(:,ik2(i))', ct44)';
                src52 = interpl(ct4, src5(:,ik2(i))', ct44)';
% for efficieny reason reconstruct the source by splines only in the region (ict3) where it changes fast
                if ~isempty(ict3)
                  src42(ict3) = spline(ct4(icts), src4(icts,ik2(i)), ct44s)';
                  src52(ict3) = spline(ct4(icts), src5(icts,ik2(i)), ct44s)';
                end
                if odd_la(i) == 1
                   src41(ict2) = src41(ict2) + src42;
                   src51(ict2) = src51(ict2) + src52;
                else
                   src41(ict2) = src41(ict2) - src42;
                   src51(ict2) = src51(ict2) - src52;
                end
             end

debug = 0;
if debug == 1
ct4step
nn2(i)
ctc0-ct4sym
ul(ict1(1))
src41(ict1(1))
ct0
odd_la(i)
xs2(end,i)
ct4(ict1(1))
ct4(end) - ct4sym
ct4(end) - x10(i)/k2(i)

figure(1)
plot(ct4(ict1), src41(ict1), ct4, ul, 'k--', ct4, src4(:,ik2(i)), 'b--', ct4(ict2(ict3)), src42(ict3),'r')
%plot(ct4(ict1), src41(ict1), ct4, ul, 'k--', ct4, src4(:,ik2(i)), 'b--')
%axis([6500, 7100, -0.05, 0.05])
end

% integrate the source function over ct4, following formula (40) of Zaldarriaga et al.(1998)
             htable = src41(ict1) .* ul(ict1)';
             tetatl(i) = simpsint(ct0, ct4(end), htable) + (ct0 - ctc0 + ct4sym) * src41(ict1(1)) * ul(ict1(1));
             htable = src51(ict1) .* ul(ict1)';
             tetael(i) = simpsint(ct0, ct4(end), htable) + (ct0 - ctc0 + ct4sym) * src51(ict1(1)) * ul(ict1(1));
          else
             tetatl(i) = 0;
             tetael(i) = 0;
          end

       else  %if kb(i) <= 1e-5 *(1500/l)

% interpolate the spherical bessel function
          kctc0 = ctc0 * k2(i) * ones(1, lct4);
          kctc = k2(i) * ct4;
          xctc = kctc0 - kctc;
          jl = interpl(kx, table_bv, xctc)';
% integrate the source function following (12) and (13) of Seljak resp (18) of Zaldarriaga and Seljak
% the integration interval is limited to ct4 where the source <> 0
          htable = src4(:,ik2(i)) .* jl;
          tetatl(i) = simpsint(ct4(1), ct4(end), htable);
          htable = src5(:,ik2(i)) .* jl;
          tetael(i) = simpsint(ct4(1), ct4(end), htable);

       end  %if kb(i)

   end  % forloop k2

%ta1 = tetatl;
f2 = 1;
%if (K ~= 0),  f2 = coth(pi*k2/sqrt(abs(K))); end
factor = sqrt((k2 .^2 - 4*K) ./ (k2 .^2 - K));
%factor = 1;
% perform the integration over k2min-k2max, following (9) of Seljak resp (19) of Zaldarriaga and Seljak
   cmbtable = f2 .* factor .* (tetatl .^2) .* k2 ./ (k2 .^2 - K) .^ (1.5 - 0.5*nprimtilt);
ta1 = cmbtable;
%    cct.ctt(il) = l*(l + 1) * sqrt(K) * sum(cmbtable');
    cct.ctt(il) = l*(l + 1) * k1step * sum(cmbtable');
%   cct.ctt(il) = l*(l + 1) * simpsint(k2min, k2max, cmbtable')
   cmbtable = factor .* (tetael .^2) .* k2 ./ (k2 .^2 - K) .^ (1.5 - 0.5*nprimtilt);
   cct.cee(il) = gl^2 * l*(l + 1) * k1step * sum(cmbtable');
   cmbtable = factor .* (tetael .* tetatl) .* k2 ./ (k2 .^2 - K) .^ (1.5 - 0.5*nprimtilt);
   cct.cte(il) = l*(l + 1) * gl * k1step * sum(cmbtable');
end  % forloop la


% minimum distance from point on ellipse of fly to nose of any other fly
function [data,units] = compute_dell2nose(trx,n)

flies = trx.exp2flies{n};
nflies = numel(flies);
data = cell(1,nflies);

for i1 = 1:nflies,
  fly1 = flies(i1);
  % access closestfly to ensure that dell2nose is computed
  trx(fly1).closestfly_ell2nose;
  data{i1} = trx(fly1).dell2nose;
end
units = parseunits('mm');


function f = eval(SO3F,g,varargin)
% evaluate sum of unimodal components at orientation g
%
% Syntax
%   f = SO3F.eval(g)
%
% Input
%  SO3F - @SO3FunUnimodal
%  rot  - @rotation
%
% Options
%  exact   -
%  epsilon -
%
% Description
% general formula:
%
% $$ f(r) = sum_j w_j \psi(r,c_j) $$

% if isa(g,'orientation')
%   ensureCompatibleSymmetries(SO3F,g)
% end

% decide along which dimension to split the summation matrix
if isa(g,'SO3Grid')
  lg1 = length(g);
else
  lg1 = -length(g);
end

if isa(SO3F.center,'SO3Grid')
  lg2 = length(SO3F.center);
else
  lg2 = -length(SO3F.center);
end

along = (lg1 > lg2 && lg1 > 0) || (abs(lg1) > abs(lg2) && lg2 < 0);
if along
  num = abs(lg2);
else
  num = abs(lg1);
end

% init variables
f = SO3F.c0 * ones(size(g));
iter = 0; numiter = 1; ind = 1; %for first run

% now iterate along the splitting
while iter <= numiter
  if iter > 0% split
    ind = 1 + (1+(iter-1)*diter:min(num-1,iter*diter));
    if isempty(ind), return; end
  end

  %eval the kernel
  if along
    M = SO3F.psi.K_symmetrised(g,SO3F.center(ind),SO3F.CS,SO3F.SS,'nocubictrifoldaxis',varargin{:});
    if SO3F.antipodal
      M = 0.5*(M + SO3F.psi.K_symmetrised(g,inv(SO3F.center(ind)),SO3F.CS,SO3F.SS,'nocubictrifoldaxis',varargin{:}));
    end
    f = f + reshape(full(M * reshape(SO3F.weights(ind),[],1)),size(f));
  else
    M = SO3F.psi.K_symmetrised(g(ind),SO3F.center,SO3F.CS,SO3F.SS,'nocubictrifoldaxis',varargin{:});
    if SO3F.antipodal
      M = 0.5*(M + SO3F.psi.K_symmetrised(inv(g(ind)),SO3F.center,SO3F.CS,SO3F.SS,'nocubictrifoldaxis',varargin{:}));
    end
    f(ind) = f(ind) + reshape(full(M * SO3F.weights(:)),size(f(ind)));
  end

  if num == 1
    return
  elseif iter == 0 % iterate due to memory restrictions?
    numiter = ceil( max(1,nnz(M))*num / getMTEXpref('memory',512 * 1024) / 256 );
    diter = ceil(num / numiter);
  end

  if numiter > 1 && ~check_option(varargin,'silent'), progress(iter,numiter); end

  iter = iter + 1;
end

if isalmostreal(f)
  f = real(f);
end

end


function [vMc, fMc_org, fStd_Mc, fMeanMc, fMedianMc] = calc_BstMcMaxCurvVar(mCatalog,fBinning, nSample)
% function [vMc, fMc_org, fStd_Mc, fMeanMc, fMedianMc] = calc_BstMcMaxCurvVar(mCatalog,fBinning, nSample)
%--------------------------------------------------------------------------------------------------------
% Bootstrap EQ catalog and determine Mc using maximum curvature
%
% Incoming variables:
% mCatalog   : EQ catalog
% fBinning   : Magnitude binning interval
% nSample    : Number of bootstrap samples
%
% Outgoing variables:
% vMc      : Best Mc estimate according to MLS
% vMls     : Vector of maximum likelihood scores
% fMc_org  : Mc estimate from original data
% fStd_Mc  : Standard deviation (assuming normal distribution)
% fSkew    : Skewness of Mc distribution
% vPerc    : Percentiles at [5 10 90 95] percent levels
% fMedianMc  : Median (50 percentile) of vMc
% fMeanMc  : Mean of Mc
%
% J. Woessner: woessner@seismo.ifg.ethz.ch
% last update: 14.02.03

% Check input
if nargin == 0, error('No catalog input'); end
if nargin == 1, fBinning = 0.1, nSample = 500, disp('Default Bin size 0.1, Default 500 bootstrap samples');end
if nargin == 2, nSample = 500, disp('Default 500 bootstrap samples'); end
if nargin > 3, error('Too many arguments!'); end

% Initialize
vMls = [];
vMc = [];

% Get magnitudes
vMags = mCatalog(:,6);

% Create bootstrap samples using bootstrap matlab toolbox
mMag_bstsamp = bootrsp(vMags,nSample);
% First step:
fMc_org = calc_Mc(mCatalog, 1);
% Determine Mc uncertainty
for nSamp=1:nSample
    mCatalog(:,6) = mMag_bstsamp(:,nSamp);
    fMc = calc_Mc(mCatalog, 1);
    vMc =  [vMc; fMc];
end

% Check for Nan and create output
vSel = isnan(vMc);
vNoNanMc = vMc(~vSel,:);
if ~isempty(vNoNanMc)
    fStd_Mc = std(vNoNanMc);
    fMeanMc = mean(vNoNanMc);
    fMedianMc = median(vNoNanMc);
else
    fStd_Mc = nan;
    fMeanMc = nan;
    fMedianMc = nan;
end


% Pick an index from the vector v,
% where each element is 0 or 1.
% Only pick from the elements denoted by 1.
%
% Output
%  item: scalar indx
function item = randset(v)
    assert(isvector(v));
    assert(all(v==0|v==1));
    indx = find(v);
    z = randint(1,1,[1 length(indx)]);
    item = indx(z);
end


function y = scale_cols(x, s)
% SCALE_COLS       Scale each column of a matrix.
% SCALE_COLS(x,s) returns matrix y, same size as x, such that
% y(:,i) = x(:,i)*s(i)
% It is more efficient than x*diag(s).

%y = x.*repmat(s(:)', rows(x), 1);

for i = 1:size(x,2)
    y(:,i) = x(:,i)*s(1,i);
end

%y = x.*(ones(rows(x),1)*s(:)');


function value = r8_power ( r, p )

%*****************************************************************************80
%
%% R8_POWER computes the P-th power of R.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 October 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R, the base.
%
%    Input, integer P, the power, which may be negative.
%
%    Output, real VALUE, the value of R**P.
%
  mults = 0;
%
%  Force P to be an integer.
%
  p = floor ( p );

%
%  Special case.  R^0 = 1.
%
  if ( p == 0 )
    value = 1.0;
%
%  Special case.  Positive powers of 0 are 0.
%  For negative powers, we go ahead and compute it, hoping software will complain.
%
  elseif ( r == 0.0 )
    if ( 0 < p )
      value = 0.0;
    else
      value = r^p;
    end
  elseif ( 1 <= p )
    value = r^p;
  else
    value = r^p;
  end

  return
end


function [GAmp,GTime]=GyRadial(p)

global VCtl;
global VObj;
global VVar;

t1Start=p.t1Start;
t2Middle=p.t2Middle;
t3Start=p.t3Start;
tRamp=p.tRamp;
Gy1Sign=p.Gy1Sign;
Gy2Sign=p.Gy2Sign;
Gy3Sign=p.Gy3Sign;

% 2D radial encoding
FOV = VCtl.FOVFreq; % choose FOVFreq as real FOV
Res = VCtl.ResFreq; % choose ResFreq as real resolution

switch VCtl.R_AngPattern
    case 'Linear'
       eval(['R_AngRange=' VCtl.R_AngRange ';']);
       AngInc = R_AngRange / VCtl.R_SpokeNum;
    case 'Golden'
       AngInc = 111.246 * (pi/180); % Golden-angle sample
end

GyAmp=(1/FOV)/((VObj.Gyro/(2*pi))*(1/VCtl.BandWidth));
tHalf=1/(2*(VObj.Gyro/(2*pi))*GyAmp*(FOV/Res));
[GAmp1,GTime1]=StdTrap(t1Start-tRamp,          ...
                       t1Start+tHalf+tRamp,    ...
                       t1Start,                          ...
                       t1Start+tHalf,                    ...
                       GyAmp*sin(AngInc * (VVar.PhaseCount - 1))*Gy1Sign,2,2,2);
[GAmp2,GTime2]=StdTrap(t2Middle+VCtl.TEAnchorTime-tHalf-tRamp, ...
                       t2Middle+VCtl.TEAnchorTime+tHalf+tRamp, ...
                       t2Middle+VCtl.TEAnchorTime-tHalf,               ...
                       t2Middle+VCtl.TEAnchorTime+tHalf,               ...
                       GyAmp*sin(AngInc * (VVar.PhaseCount - 1))*Gy2Sign,2,2,2);
[GAmp3,GTime3]=StdTrap(t3Start-tRamp,            ...
                       t3Start+tHalf+tRamp,      ...
                       t3Start,                          ...
                       t3Start+tHalf,                    ...
                       GyAmp*sin(AngInc * (VVar.PhaseCount - 1))*Gy3Sign,2,2,2);

GAmp=GAmp2;
GTime=GTime2;

if Gy1Sign~=0
    GAmp=[GAmp1, GAmp];
    GTime=[GTime1, GTime];
end

if Gy3Sign~=0
    GAmp=[GAmp, GAmp3];
    GTime=[GTime, GTime3];
end

[GTime,m,n]=unique(GTime);
GAmp=GAmp(m);

end


function overlap=compute_overlap(results,ground_truth)
gt_boxes = [ground_truth(:,1:2), ground_truth(:,1:2) + ground_truth(:,3:4) - ones(size(ground_truth,1), 2)];
 results.gt = gt_boxes;
    %   compute the OP
    pd_boxes = results.res;
    pd_boxes = [pd_boxes(:,1:2), pd_boxes(:,1:2) + pd_boxes(:,3:4) - ones(size(pd_boxes,1), 2)  ];
    lenALL=size(ground_truth,1);
     OP = zeros(size(gt_boxes,1),1);
    for i=1:size(gt_boxes,1)
        b_gt = gt_boxes(i,:);
        b_pd = pd_boxes(i,:);
        OP(i) = computePascalScore(b_gt,b_pd);
    end
    thresholdSetOverlap = 0:0.05:1;
    successNumOverlap = zeros(length(thresholdSetOverlap));
     for tIdx=1:length(thresholdSetOverlap)
         successNumOverlap(idx,tIdx) = sum(OP >thresholdSetOverlap(tIdx));
     end
     aveSuccessRatePlot = successNumOverlap/(lenALL+eps);
     overlap=mean(aveSuccessRatePlot);
end


function [sys,x0,str,ts]=ESO2_NL(t,x,u,flag,a1,a2,d,Beta,b0)
switch flag,
    case 0
      sys=[3,0,3,2,0,0,1];
      x0=[0;0;0];
      str=[];
      ts=[0 0];
    case 1
      e=x(1)-u(1);
      sys(1)=x(2)-Beta(1)*e;
      sys(2)=x(3)-Beta(2)*fal(e,a1,d)+b0*u(2);
      sys(3)=-Beta(3)*fal(e,a2,d);
    case 3
        sys=x;
    case {2,4,9}
        sys=[];
    otherwise
        error(['Unhandled flag=',num2str(flag)]);
end
function f=fal(e,a,d)
    if abs(e)<d
        f=e*d^(a-1);
    else f=(abs(e))^a*sign(e);
    end


function [y,LL] = delta2static_ML(mu, variance, delta_order, dimS)
[nFr, dim] = size(mu);
nDelta = dim/dimS;

if length(delta_order)==1 && nDelta > 1
    delta_order = ones(nDelta, 1) * delta_order;
end

D = genDeltaTransform(nFr, delta_order(1));
A = D*D;

for i = 1:dimS
    ScaleS = diag(1./variance(:,i));
    ScaleD = diag(1./variance(:,i+dimS));
    ScaleA = diag(1./variance(:,i+dimS*2));

    R = ScaleS + D'*ScaleD*D + A'*ScaleA*A;
    p = ScaleS * mu(:,i) + D' * ScaleD * mu(:,dimS+i) + A' * ScaleA * mu(:,dimS*2+i);
    y(:,i) = inv(R) * p;
end

if 1
    X = comp_dynamic_feature(mu(:,1:dimS), 2, 2);
    Y = comp_dynamic_feature(y, 2, 2);
    XE = (X-mu).^2 ./ variance;
    YE = (Y-mu).^2 ./ variance;

    LL(:,1) = mean(XE);
    LL(:,2) = mean(YE);

end
end