%   CLASS Core Block
% =========================================================================
%
% DESCRIPTION
%   Class to manage pre processing utilities
%
% EXAMPLE
%   go_block = Core_Block();
%
% FOR A LIST OF CONSTANTs and METHODS use doc Core_PP
%
% Note for the future: the class uses the current obs storage of goGPS
% -> switch to objects for rover and master observations is suggested

%--------------------------------------------------------------------------
%               ___ ___ ___
%     __ _ ___ / __| _ | __|
%    / _` / _ \ (_ |  _|__ \
%    \__, \___/\___|_| |___/
%    |___/                    v 1.0RC1
%
%--------------------------------------------------------------------------
%  Copyright (C) 2021 Geomatics Research & Development srl (GReD)
%  Written by:       Andrea Gatti
%  Contributors:     Andrea Gatti, ...
%  A list of all the historical goGPS contributors is in CREDITS.nfo
%--------------------------------------------------------------------------
%
%    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/>.
%
%--------------------------------------------------------------------------
% 01100111 01101111 01000111 01010000 01010011
%--------------------------------------------------------------------------

classdef Core_PP < handle

    properties (Constant, Access = private)
    end

    properties (Access = public)% Public Access
        log
        state
    end

    % ==================================================================================================================================================
    %  CREATOR
    % ==================================================================================================================================================

    methods (Static)
        function this = Core_PP()
            this.init()
        end
    end

    % ==================================================================================================================================================
    %  PRE PROCESSING MAIN FUNCTIONS
    % ==================================================================================================================================================

    methods % Public Access
        function init(this)
            % Init singletons
            %
            % SYNTAX
            %   this.init()
            this.log = Core.getLogger();
            this.state = Core.getState();
        end

        function [ph] = jmpFix(this, ph, lambda)
            % after a missing data try to fix the jmp in the observations with an N * lambda correction
            cs_factor = this.state.cs_thr;
            ph = ph';
            for a = 1 : size(ph,2)
                arc = zero2nan(ph(:,a));
                x_arc = (1 : numel(arc))';
                arc_fit = zeros(size(arc));

                int_factor = zeros(size(arc));
                int_factor(~isnan(arc)) = lambda(a,1) * cs_factor;
                arc = arc ./ int_factor;
                if any(arc)
                    %PLOT:figure;
                    %PLOT:plot(x_arc, arc, 'LineWidth', 1); hold on;
                    lim = getFlagsLimits(~isnan(arc));
                    for l = 1 : size(lim, 1) - 1
                        id = lim(1, 1) : lim(l, 2);
                        id = id(~isnan(arc(id)));
                        id = id((max(1, numel(id) - this.state.getMinArc(this.time.getRate)+1) : end));

                        p = polyfit(x_arc(id), arc(id), 3);
                        if l < size(lim, 1)
                            arc_fit1 = polyval(p, x_arc([lim(l, 2) lim(l + 1, 1)]));

                            id2 = lim(l + 1, 1) : lim(l + 1, 2);
                            id2 = id2(1 : min(numel(id), this.state.getMinArc (this.time.getRate)));
                            p2 = polyfit(x_arc(id2), arc(id2), 3);
                            arc_fit2 = polyval(p2, x_arc([lim(l, 2) lim(l + 1, 1)]));

                            arc(lim(l + 1, 1) : end) = arc(lim(l + 1, 1) : end) + round(mean(arc_fit1 - arc_fit2));
                        end
                        %PLOT: plot(x_arc, arc);
                    end
                    %PLOT: plot(x_arc, arc, 'LineWidth', 2); hold on;
                end
                ph(:,a) = nan2zero(arc) .* int_factor;
            end
            ph = ph';

            %PLOT: figure; plot(zero2nan(ph));
            %PLOT: d_ph = diff(zero2nan([ph(1,:); ph])); figure; plot(d_ph - movmedian(d_ph, 3, 'omitnan'));
        end
    end

    % ==================================================================================================================================================
    %  STATIC LAUNCHERS
    % ==================================================================================================================================================

    methods (Static) % Public Access
        function [data, flagged_out] = flagRawObs(data, time_set, time_ref, thr_factor, thr_min, win_size)
            % Flag the data above max(thr_min, thr_factor) * mean(movstd))
            % SYNTAX: data = flagRawObs(data,  time_set, time_ref, thr_factor, <thr_min = 0 >)
            if nargin < 5
                thr_min = 0;
            end
            if nargin < 6
                win_size = 5;
            end

            flag = 1;
            i = 0;
            % Interpolate to reference time to find outliers in the 4th derivative
            if ~isempty(time_set)
                data_interp = zeros(size(data));
                for s = 1 : size(data,2)
                    tmp = nan2zero(data(:,s));
                    if any(tmp)
                        id_interp = (conv(tmp ~= 0, ones(9,1), 'same') > 0);
                        data_interp(id_interp,s) = interp1(time_set, zero2nan(data(:,s)), time_ref(id_interp), 'spline', 'extrap');
                    end
                end
            else
                data_interp = data;
            end

            % loop for outliers rejection
            flagged_out = false(size(data));
            while (sum(flag(:)) > 0) && (i < 5)
                sensor = zero2nan(data_interp);
                sensor = bsxfun(@minus, sensor, median(sensor, 2, 'omitnan'));
                i = i + 1;
                % expand the set of observations to allow flogging at the border of the valid intervals
                sensor = movstd(sensor, win_size, 'omitnan');
                flag = sensor > max(thr_min, thr_factor * mean(serialize(zero2nan(sensor .* ~isnan(zero2nan(data)))), 'omitnan'));
                data(flag) = NaN;
                data_interp(flag) = NaN;
                flagged_out  = flagged_out | flag;
            end
        end

        function [data, flagged_out] = flagRawObsD4(data, time_set, time_ref, thr_factor, thr_min, win_size)
            % Flag the data above max(thr_min, thr_factor) * mean(movstd))
            %
            % SYNTAX
            %   data = flagRawObsD4(data,  time_set, time_ref, thr_factor, <thr_min = 0 >)
            if nargin < 5
                thr_min = 0;
            end
            if nargin < 6
                win_size = 5;
            end

            flag = 1;
            i = 0;
            % Interpolate to reference time to find outliers in the 4th derivative
            if ~isempty(time_set)
                data_interp = zeros(size(data));
                for s = 1 : size(data,2)
                    tmp = zero2nan(data(:,s));
                    id_interp = ~isnan(tmp);
                    if sum(~isnan(tmp) > 2)
                        data_interp(id_interp,s) = interp1(time_set(id_interp), tmp(id_interp), time_ref(id_interp), 'spline', 'extrap');
                    end
                end
            else
                data_interp = data;
            end

            % loop for outliers rejection
            flagged_out = false(size(data));
            while (sum(flag(:)) > 0) && (i < 5)
                sensor = Core_Utils.diffAndPred(zero2nan(data_interp), 4);
                sensor = bsxfun(@minus, sensor, median(sensor, 2, 'omitnan'));
                i = i + 1;
                % expand the set of observations to allow flogging at the border of the valid intervals
                sensor = movstd(sensor, win_size, 'omitnan');
                flag = sensor > max(thr_min, thr_factor * mean(serialize(zero2nan(sensor .* ~isnan(zero2nan(data)))), 'omitnan'));
                data(flag) = NaN;
                data_interp(flag) = NaN;
                flagged_out  = flagged_out | flag;
            end
        end

        function [data, flagged_out] = flagBorders(data, win_size)
            % Flag the data above max(thr_min, thr_factor) * mean(movstd))
            % SYNTAX: [data, flagged_out] = flagBorders(data, win_size)
            if nargin < 2
                win_size = 20;
            end

            % Interpolate to reference time
            time_set = 1 : size(data,1);
            id_interp = flagExpand(~isnan(data), 5) & isnan(data);
            data_interp = data;
            for s = 1 : size(data,2)
                tmp = data(~isnan(data(:,s)),s);
                if numel(tmp) > 5
                    data_interp(id_interp(:,s),s) = interp1(time_set(~isnan(data(:,s))), tmp, time_set(id_interp(:,s)), 'spline', 'extrap');
                end
            end

            % loop for outliers rejection
            sensor = Core_Utils.diffAndPred(zero2nan(data_interp), 4);
            sensor = bsxfun(@minus, sensor, median(sensor, 2, 'omitnan'));
            % expand the set of observations to allow flagging at the border of the valid intervals
            sensor(isnan(data)) = 0;
            sensor = maxfilt_mat(movstd(sensor, ceil(win_size/2), 'omitnan'),5);
            sensor(isnan(data)) = 0;
            std_max = sensor; std_max(flagExpand(sensor == 0, win_size)) = 0;
            sensor_max = maxfilt_mat(max(std_max, [], 2), ceil(win_size/2));
            sensor_max = simpleFill1D(sensor_max, sensor_max == 0);
            % remove possible outliers over thr and small arcs < 5 epochs
            flagged_out = ~Core_PP.remShortArcs(~(sensor > sensor_max | isnan(data))', 5)' & ~isnan(data);
            data(flagged_out) = NaN;
        end
    end

    % ==================================================================================================================================================
    %  STATIC public misc utilities
    % ==================================================================================================================================================

    methods (Static) % Public Access
        function [obs, dt_dj, is_jumping] = remDtJumps(obs)
            % remove a jumps of the clock from ph/pr
            % this piece of code is very very criptic, but it seems to work
            % review this whenever possible
            %
            % SYNTAX:
            %   [obs, dt_dj, is_jumping] = remDtJumps(obs)
            obs = zero2nan(obs);
            dt_dj = 0;
            is_jumping = false;

            % Iterate for very particular instable cases
            for i = 1 : 2
                % Try to find the biggest jumps (experimental)
                ddt = median(Core_Utils.diffAndPred(zero2nan(obs),1), 2, 'omitnan');
                pos_jmp = abs(ddt) > 1e5;
                d3dt = median(Core_Utils.diffAndPred(zero2nan(obs),3), 2, 'omitnan');
                ddt = cumsum(cumsum(nan2zero(d3dt)));
                dt0 = 0;
                if sum(pos_jmp) > 0
                    is_jumping = true;
                    ddt = ddt - simpleFill1D(ddt, pos_jmp);
                    dt0 = cumsum(nan2zero(ddt));
                    ph_bk = obs;
                    obs = bsxfun(@minus, obs, dt0);

                    % approach on 3rd and 4th derivate (classic)
                    ddt_sensor = cumsum(cumsum(nan2zero(d3dt)) - medfilt_mat(cumsum(nan2zero(d3dt)), 3));
                    % check if there is any discontinuity in the clock drift
                    clock_thresh = 1e3;
                    pos_jmp = abs(ddt_sensor - medfilt_mat(ddt_sensor, 3)) > clock_thresh;
                    pos_jmp(1:2) = 0;
                    if sum(pos_jmp) > 0
                        ddt = ddt - simpleFill1D(ddt, pos_jmp);
                        dt = cumsum(ddt);
                        ph_bk = obs;
                        obs = bsxfun(@minus, obs, dt);
                        d4dt = median(Core_Utils.diffAndPred(zero2nan(obs),4), 2, 'omitnan');
                        dobs = Core_Utils.diffAndPred(obs);
                        % find jmps on the median 4th derivate
                        jmp_candidate = flagExpand(abs(nan2zero(d4dt)) > clock_thresh, 2);
                        % detect the real jmp index
                        lim = getFlagsLimits(jmp_candidate);
                        jmp = false(size(jmp_candidate));
                        for l = 1 : size(lim,1)
                            dtmp = dobs(lim(l,1) : lim(l,2), :);
                            [~, id_max] = max(abs(nan2zero(median(dtmp, 2 ,'omitnan')))');
                            jmp(id_max + lim(l,1) - 1) = true;

                            % find the magnitude of the jump
                            dtmp_f = simpleFill1D(dtmp, isnan(dtmp)); % fill temp data
                            tmp_diff = diff(dtmp_f);
                            tmp_diff(:, isnan(dtmp(id_max,:))) = nan; % do not use filled data for estimating the magnitude of jump

                            d4dt(id_max + lim(l,1) - 1) = median(sign(dobs(id_max + lim(l,1) - 1,:)),'omitnan') * ...
                                median(abs(max(tmp_diff)),'omitnan');
                        end
                        % velocity offsets beteween sat
                        d4dt(~jmp) = 0;
                        obs = bsxfun(@minus, obs, cumsum(nan2zero(d4dt)));
                        dt = dt + cumsum(d4dt);
                    else
                        dt = zeros(size(ddt));
                    end
                    dt_dj = dt_dj + dt0 + dt;
                end
            end
            dt_dj = dt_dj / 299792458;
        end

        function [ph_out, dt] = remDtHF(ph)
            % [ !! ] EXPERIMENTAL FUNCTION
            % Remove high frequency from phases estimated by the 4th derivative
            % WARNING: this code works but it has a lot of border effects, especially if the dataset it's not continuous
            %
            % SYNTAX:
            %   [ph_out, dt] = remDtHF(ph)
            d4dt = median(Core_Utils.diffAndPred(zero2nan(ph),4), 2, 'omitnan');

            % Filter low frequencies:
%             dt_hf = cumsum(cumsum(cumsum(cumsum(nan2zero(d4dt)))));
%             x = (1 : numel(dt_hf))';
%             ws = 5;
%             margin = 2 * round(ws/2);
%             xi = (1 - margin : numel(dt_hf) + margin)';
%             dt_lf = interp1(x(~isnan(dt_hf)), dt_hf(~isnan(dt_hf)), xi, 'spline', 'extrap');
%             dt_lf = splinerMat([],medfilt_mat(dt_lf, 5), 5);
%             dt_hf = dt_hf - dt_lf(margin + 1 : end - margin);
            dt = cumsum(Core_PP.highPass(nan2zero(d4dt), 313, 0.01, 101));
            dt = cumsum(Core_PP.highPass(nan2zero(dt), 177, 0.01, 101));
            dt = cumsum(Core_PP.highPass(nan2zero(dt), 143, 0.01, 101));
            dt = cumsum(Core_PP.highPass(nan2zero(dt), 107, 0.01, 101));
            ph_out = nan2zero(bsxfun(@minus, zero2nan(ph), dt));
            dt = dt / 299792458;
        end

        function [pr, ph, dt_pr, dt_ph] = correctTimeDesyncHF(time_ref, time, pr, ph)
            %   Correction of jumps in code and phase due to dtR and time de-sync
            % SYNTAX:
            %   [pr, ph, dt_pr, dt_ph] = correctTimeDesync(time_ref, time, pr, ph)

            log = Logger.getInstance();

            time_desync  = round((time_ref - time) * 1e7) / 1e7;
            %figure(1); clf; plot(diff(zero2nan(ph))); hold on;
            %figure(2); clf; plot(diff(zero2nan(pr))); hold on;

            ph_ds = bsxfun(@minus, ph, time_desync .* 299792458);
            pr_ds = bsxfun(@minus, pr, time_desync .* 299792458);
            % if adding the desync will improve the std it means that the receiver does not compensate for it
            [ph, flag] = Core_PP.testDesyncCorrection(ph, ph_ds);
            if flag
                time_desync_ph = time_desync;
                log.addMessage('Correcting phase for time desync', 100);
            else
                time_desync_ph = 0;
            end

            [pr, flag] = Core_PP.testDesyncCorrection(pr, pr_ds);
            if flag
                time_desync_pr = time_desync;
                log.addMessage('Correcting pseudo-ranges for time desync', 100);
            else
                time_desync_pr = 0;
            end
            clear pr_ds ph_ds;
            [ph, dt_ph_jumps] = Core_PP.remDtJumps(ph);
            [ph, dt] = Core_PP.remDtHF(ph);
            dt_ph = dt_ph_jumps + dt;
            %figure(1); plot(diff(zero2nan(ph)),'.k');

            % correct the pseudo-ranges for HF
            pr_lf = bsxfun(@minus, pr, dt .* 299792458);
            [pr, flag] = Core_PP.testDesyncCorrection(pr, pr_lf);
            if flag
                dt_pr = dt_ph;
                log.addMessage('Correcting pseudo-ranges for dt HF as estimated from phases observations', 100);
            else
                dt_pr = zeros(size(dt_ph));
            end

            % correct the pseudo-ranges for jumps
            pr_dj = bsxfun(@minus, pr, dt_ph_jumps .* 299792458);
            [pr, flag] = Core_PP.testDesyncCorrection(pr, pr_dj);
            if flag
                dt_pr = dt_pr + dt_ph_jumps;
                log.addMessage('Correcting pseudo-ranges for dt as estimated from phases observations', 100);
            end

            % in some receivers the pseudo-range is not continuous while the phase are ok
            [pr_ds, dt_pr_jumps] = Core_PP.remDtJumps(pr);
            [pr, flag] = Core_PP.testDesyncCorrection(pr, pr_ds);
            if flag
                dt_pr = dt_pr_jumps + dt_pr;
                log.addMessage('Correcting pseudo-ranges for dt as estimated from their observations', 100);
            end

            dt_ph = dt_ph + time_desync_ph;
            dt_pr = dt_pr + time_desync_pr;
            %figure(2); plot(diff(zero2nan(pr)),'.k');
        end

        function [pr, ph, dt_pr, dt_ph] = correctTimeDesync(time_ref, time, pr, ph)
            %   Correction of jumps in code and phase due to dtR and time de-sync
            % SYNTAX:
            %   [pr, ph, dt_pr, dt_ph] = correctTimeDesync(time_ref, time, pr, ph)

            log = Core.getLogger();

            id_not_empty = time ~= 0;

            time_desync = nan(size(time));
            time_desync(id_not_empty)  = round((time(id_not_empty) - time_ref(id_not_empty)) * 1e7) / 1e7; % the rinex time has a maximum of 7 significant decimal digits
            time_desync = simpleFill1D(time_desync,isnan(time_desync),'nearest');

            if any(time_desync)
                [ph_dj, dt_ph_dj] = Core_PP.remDtJumps(ph);
                [pr_dj, dt_pr_dj] = Core_PP.remDtJumps(pr);
                ddt_pr = Core_Utils.diffAndPred(dt_pr_dj);

                %% time_desync is a introduced by the receiver to maintain the drift of the clock into a certain range
                ddt = [0; diff(time_desync)];
                ddrifting = ddt - ddt_pr;
                drifting = cumsum(ddt - ddt_pr);

                % Linear interpolation of ddrifting
                jmp_reset = find(abs(ddt_pr) > 1e-7); % points where the clock is reset
                jmp_fit = setdiff(find(abs(ddrifting) > 1e-7), jmp_reset); % points where desync interpolate the clock
                d_points = [drifting(jmp_reset); drifting(jmp_fit) - ddrifting(jmp_fit)/2];
                jmp = [jmp_reset; jmp_fit];
                drifting = interp1(jmp, d_points, (1 : numel(drifting))', 'spline');

                dt_ph = drifting + dt_ph_dj;
                dt_pr = drifting + dt_pr_dj;

                t_offset = round(mean(dt_pr(jmp) - time_desync(jmp) + ddrifting(jmp)/2) * 1e7) * 1e-7;
                dt_ph = dt_ph - t_offset;
                dt_pr = dt_pr - t_offset;

                ph = bsxfun(@minus, ph, dt_ph .* 299792458);
                pr = bsxfun(@minus, pr, dt_pr .* 299792458);
            else
                [ph_dj, dt_ph_dj] = Core_PP.remDtJumps(ph);
                [pr_dj, dt_pr_dj] = Core_PP.remDtJumps(pr);
                ddt_pr = Core_Utils.diffAndPred(dt_pr_dj);
                jmp_reset = find(abs(ddt_pr) > 1e-7); % points where the clock is reset
                if numel(jmp_reset) > 2
                    drifting = interp1(jmp_reset, dt_pr_dj(jmp_reset), (1 : numel(ddt_pr))', 'spline');
                else
                    drifting = 0;
                end
                dt_pr = dt_pr_dj - drifting;
                t_offset = mean(dt_pr);
                dt_ph = dt_ph_dj - drifting - t_offset;
                dt_pr = dt_pr - t_offset;

                ph = bsxfun(@minus, ph, dt_ph .* 299792458);
                pr = bsxfun(@minus, pr, dt_pr .* 299792458);
            end

            if any(dt_ph_dj)
                log.addMessage(log.indent('Correcting carrier phases jumps', 6),100);
            else
                log.addMessage(log.indent('Correcting carrier phases for a dt drift estimated from desync interpolation', 6),100);
            end
            if any(dt_pr_dj)
                log.addMessage(log.indent('Correcting pseudo-ranges jumps', 6),100);
            else
                log.addMessage(log.indent('Correcting pseudo-ranges for a dt drift estimated from desync interpolation', 6),100);
            end
        end

        function [obs_out] = remShortArcs(obs_in, min_len)
            % Removal of observation arcs shorter than given threshold.
            % SYNTAX:
            %   [obs_out] = Core_PP.remShortArcs(obs_in, threshold_gap);
            %
            % INPUT:
            %   obs_in = input observation matrix (num_sat x epochs)
            %   min_len = threshold on the number of epochs for an arc to be
            %                   considered "short"
            %
            % OUTPUT:
            %   obs_out = input observation matrix (num_sat x epochs)

            if (nargin < 2)
                min_len = 10;
            end

            obs_out = obs_in';

            for s = 1 : size(obs_in,1)

                % find intervals of zeros
                lim = getFlagsLimits(obs_in(s,:) == 0 | isnan(obs_in(s, :)));

                % find the intervals of good obs_in
                lim = [[1; lim(:,2)+1] [lim(:,1)-1; size(obs_in,2)]];
                lim = [lim (lim(:,2) - lim(:,1) +1)];

                lim = lim(lim(:,3) <= min_len, :);

                for i = 1 : size(lim,1)
                    obs_out(lim(i,1) : lim(i,2), s) = 0;
                end
            end

            obs_out = obs_out';
        end
    end

    % ==================================================================================================================================================
    %  PRIVATE FUNCTIONS called by public calls
    % ==================================================================================================================================================

    methods (Access = public)
    end

    % ==================================================================================================================================================
    %  STATIC FUNCTIONS used as utilities
    % ==================================================================================================================================================
    methods (Static, Access = public)
        function [data_out] = highPass(data, spline_base, cut_off, filt_border)
            % Compute an high pass filter on a dataset
            % Additionally apply a spline interpolation before thee fft transformation
            %
            % SYNTAX:
            %   [filtered_data] = highPass(data, spline_base, cut_off, filt_border);
            %
            % INPUT:
            %   data            dataset to filter
            %   spline_base     spline_base for spline filtering (if 0 do not do it)
            %   cut_off         cut-off frequency for the filter
            %   filt_border     filter dimension (larger -> smoother)
            %
            % OUTPUT:
            %   filtered_data   data reduced by splines and spectral filter

            if nargin < 4
                filt_border = 1e100;
            end

            spline_base = min(round(numel(data)/2), spline_base);

            %%% DEBUG figure(133); clf; plot(data); hold on;

            % if the number of data is even interpolate one observation
            is_even = false;
            if (cut_off > 0) && (mod(numel(data),2) == 0) % is even
                is_even = true;
                x = (1 : numel(data))';
                data = [interp1(x(~isnan(data)), data(~isnan(data)), 0, 'pchip', 'extrap'); data];
            end
            data = data - (0 : numel(data)-1)' * (median(data(max(1,length(data)-4):end)) - median(data(1:min(5,length(data))))) / numel(data);

            n_obs = length(data);

            % filter low frequencies with splines to limit border effects:
            if (spline_base > 0)
                x = (1 : n_obs)';
                ws = 5;
                margin = 2 * round(ws/2);
                xi = (1 - margin : n_obs + margin)';

                dt_lf = [median(data(1:min(5,length(data)))) * ones(margin,1); data(~isnan(data)); ones(margin,1) * median(data(max(1,length(data)-4):end))];
                %%% DEBUG figure(133); plot(xi - 1, dt_lf);
                dt_lf = splinerMat([],medfilt_mat(dt_lf, ws), spline_base);

                data = data - dt_lf(margin + 1 : end - margin);
            end
            %%% DEBUG figure(133); plot(data((1 + is_even) : end));

            if (cut_off > 0)
                % replicate signal to limit the border effects
                data = [flipud(data); data; flipud(data)];

                %%% DEBUG figure(110); clf; plot(zero2nan(data));

                % Take fft
                fftx = fftshift(fft(data));

                % Calculate the number of unique points (find the zero frequency - mean of the signal)
                f0_id = ceil((length(data) + 1) / 2);

                % This is an evenly spaced frequency vector with f0_id points.
                f = (0:f0_id-1) ./ length(data);

                % FFT is symmetric, throw away second half
                fftx_half = fftx(f0_id : end);

                % design the filter
                w = zeros(size(fftx_half));
                f_cut = cut_off;
                id_cut = find(f > f_cut, 1, 'first');
                filt_border = min(2*id_cut - 1, filt_border);
                w(1 : (id_cut - ((filt_border - 1) / 2))) = 0;
                w((id_cut + ((filt_border - 1) / 2)) : end) = 1;
                w((id_cut - ((filt_border - 1) / 2)) : (id_cut + ((filt_border - 1) / 2))) = 1 - (1 ./ (1+exp(-10:20/(filt_border-1):10)))'; % use a sigmoid filter for the design

                % compute power spectra - for debug
                %%% DEBUG psd = abs(fftx_half)/length(data)*sqrt(length(data)); % Take the magnitude of fft of x and scale the fft so that it is not a function of the length of x
                %%% DEBUG figure(125); clf; loglog(f, psd)

                % apply the filter
                fftx_half = fftx_half .* w;

                % compute power spectra of the filtered data - for debug
                %%% DEBUG psd_f = abs(fftx_half) / length(data) * sqrt(length(data)); % Take the magnitude of fft of x and scale the fft so that it is not a function of the length of x

                fftx = ifftshift([flipud(conj(fftx_half)); fftx_half(2:end)]);

                %%% DEBUG figure(125); hold on; loglog(f, psd_f)
                data_out = real(ifft(fftx));
                data_out = data_out(n_obs + ((1 + is_even) : n_obs));
                %%% DEBUG figure(133); plot(data_out); title('data');
            else
                data_out = data;
            end
        end
    end

end


function [estimate] = ft_inverse_music(cov, leadfield, varargin)

% FT_INVERSE_MUSIC
%
% Use as
%  estimate = ft_inverse_music(cov, leadfield, ...)


% POP_LIMO - prepare and convert EEGLAB data and structure to be
%              processed by LIMO.
%
% Usage:
%   >> STUDY = pop_limo( STUDY, ALLEEG, 'key', val)
%   >> STUDY = pop_limo( STUDY, ALLEEG, 'dat', 'key', val)
%   >> STUDY = pop_limo( STUDY, ALLEEG, 'ica', 'key', val)
%
% Inputs:
%   STUDY        - an EEGLAB STUDY set of loaded EEG structures
%   ALLEEG       - ALLEEG vector of one or more loaded EEG dataset structures
%   'dat'|'ica'  - show the interface for data channels or for ICA. The
%                  default is to use data.
%
% Optional inputs: same as STD_LIMO
%
% Graphical interface:
%   "See GLM factors" - [push button] See all the GLM factors or columns in
%                   the design matrix. This list depends on your study
%                   design. Adding contrast will change this list. In
%                   practice, it is important to understand that every
%                   single factor will be fitted by the GLM, and the choice
%                   of these factors is critical. It is recommended to
%                   include as many factors as possible, especially because
%                   this allows you to define new contrast later on without
%                   having to recompute the GLM on each subject (as long as
%                   these new contrast do not involve new factors).
%
%  "Interaction model for categorical indep. var." - When using more than
%                   one categorical variable, clicking this option forces
%                   to have factors which are the conjunction of the
%                   different independent var. values. This is useful only
%                   if you want to calculate interactions at the subject.
%                   The 'best' option is typically to have a design with
%                   all conditions (no factors) and create factors at the
%                   group level.
%
%  "Split regressions (continuous indep. var.)" - This options allows to
%                   split continuous variables for the different
%                   categorical variables. This is useful to compute
%                   interaction between continuous and categorical
%                   variables.
%
%  "Input data to use for the GLM" - [pop up menu] measure to use as input
%                   for the GLM. Currently, only "ERP" and "spectrum" are
%                   supported.
%
%  "Optimization method" - [pop up menu] may be Ordinary Least Squares (OLS),
%                   Weighted Least Squares (WLS), or Iterative Reweighted Least
%                   Squares. WTS should be used as it is more robust to trials
%                   with different time course. OLS is a standard solution and
%                   WLS/IRLS are solution that automatically weight down outliers
%                   (trials/data point).
%
%  "Options"        - [edit box] additional options. These are given
%                   directly as input to the std_limo.m function. They may
%                   be ['freqlim', value] frequency trimming in Hz or
%                   ['timelim', value] time trimming in millisecond. These
%                   allow to speed up computation by not including all the
%                   data as input. Example: 'timelim', [-50 650] only
%                   include data within the -50 ms and 650 ms for ERPs.
%
% "Erase previous model" - [checkbox] erase previous model for this
%                   measure.
%
% Outputs:
%   STUDY       - an EEGLAB STUDY set of loaded EEG structures
%
% Author: Arnaud Delorme, SCCN, UCSD, 2015-
%         Cyril Pernet, LIMO Team - edit info and defaults
%
% See also: STD_LIMO

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

function [STUDY,com,limofiles] = pop_limo(STUDY, ALLEEG, measureflag, varargin)

if nargin < 2
    help pop_limo;
    return;
end

com = '';
if nargin > 2
    if strcmpi(measureflag,'dat')
        measureflagindx = 1;
    elseif strcmpi(measureflag,'ica')
        measureflagindx = 2;
    else
        varargin = { measureflag varargin{:} };
        measureflagindx = 1;
    end
else
    measureflagindx = 1;
end

% check that channel location are present
ALLEEG = eeg_checkset(ALLEEG, 'chanloc');

if nargin < 4
    dataMeasures = { 'ERP' 'Spectrum' 'ERSP'};
    fileMeasures = { 'daterp' 'datspec' 'dattimef'; 'icaerp' 'icaspec' 'icatimef'};
    methods      = { 'WLS' 'OLS' 'IRLS'};
    cb_measure   = [ 'if get(gcbo, ''value'') == 1,' ...
                     '   set(findobj(gcbf, ''tag'', ''options''), ''string'', '''');' ...
                     'else,' ...
                     '   set(findobj(gcbf, ''tag'', ''options''), ''string'', ''''''freqlim'''', [1 25]'');' ...
                     'end;' ];
    cb_listfactors = [ 'pop_listfactors(STUDY, ''gui'', ''on'', ' ...
                               '''level'', ''both'',' ...
                               '''splitreg''   , fastif(get(findobj(gcbf, ''tag'', ''splitreg''   ), ''value''), ''on'', ''off''),' ...
                               '''interaction'', fastif(get(findobj(gcbf, ''tag'', ''interaction''), ''value''), ''on'', ''off''));' ];
    uilist = { ...
        {'style' 'text'       'string' 'LInear MOdeling of EEG data' 'fontweight' 'bold' 'fontsize', 12} ...
        {'style' 'pushbutton' 'string' 'See GLM variables' 'callback' cb_listfactors } ...
        {'style' 'checkbox'   'string' 'Interaction model for categorical indep. var.' 'value' 0 'tag' 'interaction' } ...
        {'style' 'checkbox'   'string' 'Split regressions (continuous indep. var.)' 'tag' 'splitreg' } {} ...
        {'style' 'text'       'string' 'Input data to use for the GLM' } ...
        {'style' 'popupmenu'  'string' dataMeasures 'tag' 'measure' 'callback' cb_measure} ...
        {'style' 'text'       'string' 'Estimation method' } ...
        {'style' 'popupmenu'  'string' methods 'tag' 'method' } ...
        {'style' 'text'       'string' 'Options' } ...
        {'style' 'edit'       'string' '' 'tag' 'options' } ...
        {'style' 'checkbox'   'string' 'Erase previous model' 'tag' 'erase' 'value' true } ...
        };

    cline = [1.1 0.8];
    geometry = { [1.6 1] 1 1 1 cline cline cline 1 };
    geomvert = [ 1 1 1     1 1 1     1     1 ];

    [out_param userdat tmp res] = inputgui( 'geometry' , geometry, 'uilist', uilist, 'geomvert', geomvert, ...
                                            'title', 'LInear MOdeling of EEG data -- pop_limo()', 'helpcom', 'pophelp(''pop_limo'');');
    if isempty(res), return; end
    opttmp  = eval( [ '{ ' res.options ' }' ]);
    if length(opttmp) > 0 && isnumeric(opttmp{1})
        error([ 'Wrong options. Options must be in the format' 10 '''key'', val. For example ''timelim'', [-100 600]' ]);
    end
    options = { 'method' methods{res.method} 'measure' fileMeasures{measureflagindx,res.measure} opttmp{:} ...
                'erase'       fastif(res.erase, 'on', 'off') ...
                'splitreg'    fastif(res.splitreg, 'on', 'off') ...
                'interaction' fastif(res.interaction, 'on', 'off') };
else
    options = varargin;
end

[STUDY,limofiles] = std_limo(STUDY, ALLEEG, options{:});
com = sprintf('pop_limo(STUDY, ALLEEG, %s);', vararg2str(options));


% std_substudy()  - create a sub-STUDY set by removing datasets, conditions, groups, or
%                   subjects.
% Usage:
%  >> [ STUDY ALLEEG ] = std_substudy(STUDY, ALLEEG, 'key', 'val', ...);
%
% Optional Inputs:
%   STUDY                - existing study structure.
%   ALLEEG               - vector of EEG dataset structures to be included in the STUDY.
%
% Optional Inputs:
%   'dataset'   - [integer array] indices of dataset to include in sub-STUDY
%                 Default is all datasets.
%   'subject'   - [cell array] name of subjects to include in sub-STUDY.
%                 Default is all subjects.%
%   'condition' - [cell array] name of conditions to include in sub-STUDY
%                 Default is all conditions.
%   'group'     - [cell array] name of gourps to include in sub-STUDY
%                 Default is all groups.
%   'rmdat'     - ['on'|'off'] actually remove datasets 'on', or simply
%                 remove all references to these datasets for channels and
%                 clusters ('off').
%
% Example:
%    % create a sub-STUDY using only the first 3 subjects
%    % WARNING: make sure your STUDY is saved before creating a sub-STUDY
%    [STUDY ALLEEG] = std_substudy(STUDY, ALLEEG, 'subject', STUDY.subjects(1:3));
%
% Authors: Arnaud Delorme, CERCO/CNSR & SCCN, INC, UCSD, 2009-

% Copyright (C) Arnaud Delorme, SCCN, INC, UCSD, arno@sccn.ucsd.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 [ STUDY ALLEEG ] = std_substudy(STUDY, ALLEEG, varargin);

if nargin < 3
    help std_substudy;
    return;
end

opt = finputcheck(varargin, { 'condition' 'cell' {}      {};
                              'dataset'   'integer' {}   [];
                              'group'     'cell' {}      {};
                              'rmdat'     'string' { 'on' 'off' }      'on';
                              'subject'   'cell' {}      {} }, 'std_substudy');
if isstr(opt), return; end;

% find datasets to remove
% -----------------------
tagdel = [];
if ~isempty(opt.subject)
    for index = 1:length(STUDY.datasetinfo)
        if ~strmatch(STUDY.datasetinfo.subject, opt.subject, 'exact')
            tagdel = [ tagdel index ];
        end;
    end;
end;
if ~isempty(opt.condition)
    for index = 1:length(STUDY.datasetinfo)
        if ~strmatch(STUDY.datasetinfo.condition, opt.condition, 'exact')
            tagdel = [ tagdel index ];
        end;
    end;
end;
if ~isempty(opt.group)
    for index = 1:length(STUDY.datasetinfo)
        if ~strmatch(STUDY.datasetinfo.group, opt.group, 'exact')
            tagdel = [ tagdel index ];
        end;
    end;
end;
if ~isempty(opt.dataset)
    tagdel = [ tagdel setdiff([1:length(ALLEEG)], opt.dataset) ];
end;
tagdel = unique(tagdel);

% find new dataset indices
% ------------------------
alldats = [1:length(ALLEEG)];
if strcmpi(opt.rmdat, 'on')
    alldats(tagdel) = [];
    for index = 1:length(ALLEEG)
        tmp = find(alldats == index);
        if isempty(tmp), tmp = NaN; end;
        datcoresp(index) = tmp;
    end;
    ALLEEG(tagdel) = [];
    STUDY.datasetinfo(tagdel) = [];
    for index = 1:length(STUDY.datasetinfo)
        STUDY.datasetinfo(index).index = index;
    end;
else
    alldats(tagdel) = [];
    for index = 1:length(ALLEEG)
        tmp = find(alldats == index);
        if isempty(tmp), tmp = NaN; else tmp = index; end;
        datcoresp(index) = tmp;
    end;
end;

% check channel consistency
% -------------------------
for i = 1:length(STUDY.changrp)
    for c = 1:size(STUDY.changrp(i).setinds,1)
       for g = 1:size(STUDY.changrp(i).setinds,2)
           newinds = datcoresp(STUDY.changrp(i).setinds{c,g});
           nonnans = find(~isnan(newinds));
           STUDY.changrp(i).setinds{c,g} = newinds(nonnans);
           STUDY.changrp(i).allinds{c,g} = STUDY.changrp(i).allinds{c,g}(nonnans);
       end;
    end;
end;

% check cluster consistency
% -------------------------
for index = 1:length(STUDY.cluster)
    STUDY.cluster(index).sets(:) = datcoresp(STUDY.cluster(index).sets(:));
    for i = size(STUDY.cluster(index).sets,2):-1:1
        if all(isnan(STUDY.cluster(index).sets(:,i)))
            STUDY.cluster(index).sets(:,i) = [];
            STUDY.cluster(index).comps(:,i) = [];
        end;
    end;
    [tmp STUDY.cluster(index).setinds STUDY.cluster(index).allinds] = std_setcomps2cell(STUDY, STUDY.cluster(index).sets, STUDY.cluster(index).comps);
end;

STUDY = std_reset(STUDY);
STUDY = std_checkset(STUDY, ALLEEG);


% -------------------------------------------------------------------------------------------------------------------------
function [layer_names, layer_ids] = find_layers_from_type(net, type)
% -------------------------------------------------------------------------------------------------------------------------
 % works with simplenn
  layer_names = [];
  layer_ids = [];
  for l = 1:numel(net.layers)
    if ~isempty(strfind(net.layers(l).type, type))
      layer_names{end+1} = net.layers(l).name;
	  layer_ids{end+1} = l;
    end
  end
end


function cs_install (do_pause)
%CS_INSTALL: compile and install CSparse for use in MATLAB.
%   Your current working directory must be CSparse/MATLAB in order to use this
%   function.
%
%   The directories
%
%       CSparse/MATLAB/CSparse
%       CSparse/MATLAB/Demo
%       CSparse/MATLAB/UFget
%
%   are added to your MATLAB path (see the "pathtool" command to add these to
%   your path permanently, for future MATLAB sessions).
%
%   Next, the MATLAB CSparse demo program, CSparse/MATLAB/cs_demo is executed.
%   To run the demo with pauses so you can see the results, use cs_install(1).
%   To run the full MATLAB test programs for CSparse, run testall in the
%   Test directory.
%
%   Example:
%       cs_install          % install and run demo with no pauses
%       cs_install(1)       % install and run demo with pauses
%
%   See also: cs_demo
%
%   Copyright 2006-2007, Timothy A. Davis.
%   http://www.cise.ufl.edu/research/sparse

fprintf ('Compiling and installing CSparse\n') ;
if (nargin < 1)
    do_pause = 0 ;
end

if (~isempty (strfind (computer, '64')))
    error ('64-bit version not supported; use CXSparse instead') ;
end

if (do_pause)
    input ('Hit enter to continue: ') ;
end
addpath ([pwd filesep 'CSparse']) ;
addpath ([pwd filesep 'Demo']) ;

v = getversion ;
if (v >= 7.0)
    addpath ([pwd filesep 'UFget']) ;
else
    fprintf ('UFget not installed (MATLAB 7.0 or later required)\n') ;
end

cd ('CSparse') ;
cs_make (1) ;
cd ('../Demo') ;
cs_demo (do_pause)

%-------------------------------------------------------------------------------
function v = getversion
% determine the MATLAB version, and return it as a double.
v = sscanf (version, '%d.%d.%d') ;
v = 10.^(0:-1:-(length(v)-1)) * v ;


function [region_parts, orig_sp, varargout] = spagglom(I_rgb, opts, varargin)
% The main function for method described in "Generating object segmentation
% proposals using global and local search".
%
% INPUTS
%
%   'I_rgb' is an rgb image of type uint8
%   'opts' is an options cell array, initialized by running script
%       spagglom_options.m
%   Additionally, precalculated superpixelation for the image and/or pixel
%       features can be supplied - please see the code for details. Script
%       test_recalls.m also contains few examples.
%
% OUTPUTS
%
%   'region_parts' is a cell array, each item of which is a set of natural
%       numbers
%   'orig_sp' is a cell array. Each element represents a superpixel,
%       containing various information. The indexing corresponds to
%       region_parts. For example region_parts{1} = [4, 8] means that the
%       first region is made up of superpixels 4 and 8, which can be
%       accessed by orig_sp{4} and orig_sp{8}.
%   Additionally, histograms for each generated region proposal are
%       returned if third output variable is specified. See the very bottom
%       of this function for details.
%
%
% Requires VLFeat. Version 9.16 was used for developing.

%% Parse varargin
I_seg = [];
words = [];
histograms = [];
argl = length(varargin);
if mod(argl,2) ~= 0 % string-value pairs
    error('Give pairs of extra arguments.');
end
for argi = 0:((argl/2) - 1)
    arg_str = varargin(2*argi + 1);
    arg_val = varargin(2*argi + 2);
    switch arg_str{1}
        case 'I_seg' % Integer map of image superpixelation
            I_seg = arg_val{1};
        case 'words' % Pixelwise features
            words = arg_val{1};
        case 'histograms' % Histograms for each superpixel. Using this is not as straightforward as the above two
            histograms = arg_val{1};
        otherwise
            error('Argument error.');
    end
end

[h, w, ~] = size(I_rgb); % image size

opts.sp_reindexed = 0;

region_parts{1} = []; % suppresses errors if no region_parts or graphcut_parts are generated below
graphcut_parts{1} = [];

%% Initial segmentation

% Calculate the initial segmentation
[sp, K] = initial_seg(I_rgb, opts, I_seg);

orig_sp = sp; % make a copy of sp. This will be used by the scoring routine.

%% Features
if isempty(histograms) % by default, this is true
    % Compute pixel-wise features
    if isempty(words)
        [words, k] = compute_features(I_rgb, I_rgb, 'rgb', opts);
    else % use user 'words'
        k = [];
        for r = 1:length(words)
            k(r) = max(words{r}(:)); % histogram sizes
        end
    end

    % Compute histograms from features and add them to superpixels
    sp = compute_histograms(sp, words, k, h, w);

else % use user supplied histograms
    assert(length(histograms) == length(sp)); % one set of histograms for each superpixel
    hist_num = length(histograms{1});
    % Important: You must setup 'opts.features' in spagglom_options.m to
    % match what type of histograms you are supplying, in correct order.

    for r = 1:length(sp) % for each superpixel
        for fn = 1:hist_num % for each histogram
            sp{r}.hist{fn} = histograms{r}{fn}; % copy the histogram values
        end
    end
end

%% Agglomeration of superpixels

% Calculate similarity scores between all neighboring superpixel pairs
scores = similarity_scores(sp, K, opts);

%%
%% Run the non-branching part of the algorithm. "Refining the superpixelation". <<< PHASE 1 >>>
opts.phase = 1; % Critically important line

%[sp, K, scores, region_parts_phase1] = spagglom_sub(sp, K, scores, 0, opts);
[sp, K, ~, ~] = spagglom_sub(sp, K, scores, 0, opts); % returns the current state of 'sp' and 'K'

%% Update indexing of superpixels

if 1 % update indexing for speedup. After this region_parts_primary cannot be used!
    [sp, K, scores] = update_sp_indexing(sp, K, h, w, opts); % makes rest of the algorithm (and scoring) faster by decreasing amount of parts and sp
    orig_sp = sp; % Replace the orig_sp
    opts.sp_reindexed = 1; % a note that this step was performed
else
    % Not updating the indexing allows for returning the
    % region_parts_phase1 above, because they can be represented using the
    % orig_sp defined earlier.
end

%%
%% Run the local and global search <<< PHASE 2 >>>
opts.phase = 2; % Critically important line
sp = setup_on_edge(sp, h, w); % Setup on_edge variables. Required before graphcut_regions()

graphcut_parts{1} = graphcut_regions(sp, K, opts);

initial_regions_created = 0; % default 0
[~, ~, ~, region_parts{1}] = spagglom_sub(sp, K, scores, initial_regions_created, opts); % CREATE INITIAL REGIONS HERE (YES 0 <-> 1 NO)
initial_regions_created = 1; % may prevent unnecessary duplicates if the above local search is repeated below

% Example of how to run in another color space
% [sp_nrgb, scores_nrgb] = change_color_space('nrgb', I_rgb, sp, K, im_num, h, w, [], opts);
% [~, ~, ~, region_parts{2}] = spagglom_sub(sp_nrgb, K, scores_nrgb, initial_regions_created, opts);
% graphcut_parts{2} = graphcut_regions(sp_nrgb, K, opts);

%% Combine all found regions
% Above you can collect region_parts{1}, region_parts{2}, region_parts{3}, ... as
% many as you want. You can only add region_parts_phase1 if you did NOT
% update superpixel indexing above.
%region_parts = horzcat(region_parts_phase1, region_parts{:}, graphcut_parts{:});
region_parts = horzcat(region_parts{:}, graphcut_parts{:});

%% Keep only unique entries
regions_bin = false(length(region_parts), length(orig_sp)); % Represent regions as binary masks of the superpixelation orig_sp
for ku = 1:length(region_parts)
    regions_bin(ku, region_parts{ku}) = 1;
end

% Use unique() to remove duplicates
[~, ue, ~] = unique(regions_bin, 'rows'); % This could perhaps be optimized further by summing rows of regions_bin and running unique for groups having the same sum (the same amount of parts)
region_parts = region_parts(ue); % The return value

%% Output region histograms if desired
if nargout == 3
    varargout{1} = cell(1,length(region_parts));
    for ku = 1:length(region_parts)
        varargout{1}{ku} = merge_histograms(orig_sp, region_parts{ku});
    end
    %varargout{1}{10}{2} % Example: gives the second histogram (the rgb
    % histogram in default case) of 10th region
end


function irepistruct = irepitiming(irepistruct)
% irepistruct = irepitiming(irepistruct)
%
% See irepistructure.m for more info on the struct parameters
%
% $Id: irepitiming.m,v 1.2 2016/04/11 03:19:08 greve Exp $

InvFlip = 180;

s = irepistruct; % copy into s for easy handling
s.tEvent = [];
s.EventSliceNo = []; % spatial/anatomical slice no
s.AcqSliceNo = []; % after inversion
s.FlipEvent = [];
s.IsReadOut = [];

t = 0;

% Dummies.
SliceOrderD = [1:s.nslices]; % Dummies do not permute
for nthtp = 1:s.ndummies
  if(s.Slice1PreInv==0)
    % Inversion
    t = t - s.PreInv;
    t = t + s.InvDur; % duration of inversion pulse
    tInv = t;
    s.tEvent = [s.tEvent; tInv];
    s.FlipEvent = [s.FlipEvent; InvFlip];
    s.IsReadOut = [s.IsReadOut; 0];
    s.TI = [s.TI; 0];
    s.AcqSliceNo = [s.AcqSliceNo; 0];
    s.EventSliceNo = [s.EventSliceNo; -1]; % Applies to all slices
    t = t + s.TI1;
  end
  % Readout (but no actual acq because these are dummies)
  nthslice = 0;
  for sliceno = SliceOrderD
    nthslice = nthslice + 1;
    s.tEvent = [s.tEvent; t];
    s.EventSliceNo = [s.EventSliceNo; sliceno];
    s.FlipEvent = [s.FlipEvent; s.ROFlip];
    s.IsReadOut = [s.IsReadOut; 0]; % 0 = no acq
    s.TI = [s.TI; 0];
    s.AcqSliceNo = [s.AcqSliceNo; 0];
    t = t + s.TBS;
    if(nthslice == 1 & s.Slice1PreInv)
      % Inversion
      t = t - s.PreInv;
      t = t + s.InvDur; % duration of inversion pulse
      tInv = t;
      s.tEvent = [s.tEvent; tInv];
      s.FlipEvent = [s.FlipEvent; InvFlip];
      s.IsReadOut = [s.IsReadOut; 0];
      s.TI = [s.TI; 0];
      s.AcqSliceNo = [s.AcqSliceNo; 0];
      s.EventSliceNo = [s.EventSliceNo; -1]; % Applies to all slices
      t = t + s.TI1;
    end
  end
end

% Non-dummies
for nthtp = 1:s.ntp
  if(s.Slice1PreInv==0)
    % Inversion before all slices
    t = t - s.PreInv;
    t = t + s.InvDur; % duration of inversion pulse
    tInv = t;
    s.tEvent = [s.tEvent; tInv];
    s.EventSliceNo = [s.EventSliceNo; -1]; % Applies to all slices
    s.FlipEvent = [s.FlipEvent; InvFlip];
    s.IsReadOut = [s.IsReadOut; 0];
    s.TI = [s.TI; 0];
    s.AcqSliceNo = [s.AcqSliceNo; 0];
    t = t + s.TI1;
  end
  % Read out
  SliceOrderR = circshift([1:s.nslices]',-(nthtp-1)*s.skip)';
  nthslice = 0;
  for sliceno = SliceOrderR
    nthslice = nthslice + 1;
    s.tEvent = [s.tEvent; t];
    s.EventSliceNo = [s.EventSliceNo; sliceno];
    s.FlipEvent = [s.FlipEvent; s.ROFlip];
    s.IsReadOut = [s.IsReadOut; 1];
    s.TI = [s.TI; t-tInv];
    s.AcqSliceNo = [s.AcqSliceNo; nthslice];
    t = t + s.TBS;
    if(nthslice == 1 & s.Slice1PreInv)
      % Inversion, when 1st slice occurs before inversion
      t = t - s.PreInv;
      t = t + s.InvDur;
      tInv = t;
      s.tEvent = [s.tEvent; tInv];
      s.EventSliceNo = [s.EventSliceNo; -1]; % Applies to all slices
      s.FlipEvent = [s.FlipEvent; InvFlip];
      s.IsReadOut = [s.IsReadOut; 0];
      s.TI = [s.TI; 0];
      s.AcqSliceNo = [s.AcqSliceNo; 0];
      t = t + s.TI1;
    end
  end % slice
end

irepistruct = s;

return;


%%% This script is used to read the binary file produced by the DCA1000
%%% and Mmwave Studio
%%% Command to run in Matlab GUI -readDCA1000('<ADC capture bin file>')
function [retVal] = readDCA1000(folder_locaion, numADCSamples)
%% global variables
% change based on sensor config
% numADCSamples = 128; % number of ADC samples per chirp should be variable
numADCBits = 16; % number of ADC bits per sample
numRX = 4; % number of receivers
numLanes = 2; % do not change. number of lanes is always 2
max_numChirps = 459000;
isReal = 0; % set to 1 if real only data, 0 if complex data0
adcData = [];
%% read file
% search all files under this folder
files = dir(folder_locaion); % find all the files under the folder
n_files = length(files);
processed_files = [3:n_files];

for index = 1:length(processed_files)
    inum = processed_files(index);
    file_name = files(inum).name;
    file_location = strcat(folder_locaion,'/',file_name);
    % read .bin file
    fid = fopen(file_location,'r');
    adcData_tmp = fread(fid, 'int16');
    adcData = [adcData; adcData_tmp];
end

% if 12 or 14 bits ADC per sample compensate for sign extension
if numADCBits ~= 16
    l_max = 2^(numADCBits-1)-1;
    adcData(adcData > l_max) = adcData(adcData > l_max) - 2^numADCBits;
end
fclose(fid);
fileSize = size(adcData, 1);
% real data reshape, filesize = numADCSamples*numChirps
if isReal
    numChirps = fileSize/numADCSamples/numRX;
    LVDS = zeros(1, fileSize);
    %create column for each chirp
    LVDS = reshape(adcData, numADCSamples*numRX, numChirps);
    %each row is data from one chirp
    LVDS = LVDS.';
else
    % for complex data
    % filesize = 2 * numADCSamples*numChirps
    numChirps = fileSize/2/numADCSamples/numRX;
    LVDS = zeros(1, fileSize/2);
    %combine real and imaginary part into complex data
    %read in file: 2I is followed by 2Q
    counter = 1;
    for i=1:4:fileSize-1
        LVDS(1,counter) = adcData(i) + sqrt(-1)*adcData(i+2);
        LVDS(1,counter+1) = adcData(i+1)+sqrt(-1)*adcData(i+3);
        counter = counter + 2;
    end
    % create column for each chirp
    LVDS = reshape(LVDS, numADCSamples*numRX, numChirps);
    %each row is data from one chirp
%     LVDS = LVDS.'; % make comment to avoid the 'out of memory'
end

% organize data per RX
clear adcData
clear adcData_tmp
if numChirps <= max_numChirps % 900 frames
    adcData = zeros(numRX,numChirps*numADCSamples);
    for row = 1:numRX
        for i = 1: numChirps
            adcData(row, (i-1)*numADCSamples+1:i*numADCSamples) = LVDS((row-1)*numADCSamples+1:row*numADCSamples,i);
        end
    end
    retVal = adcData;
else
    adcData1 = zeros(numRX,max_numChirps*numADCSamples);
    for row = 1:numRX
        for i = 1:max_numChirps
            adcData1(row, (i-1)*numADCSamples+1:i*numADCSamples) = LVDS((row-1)*numADCSamples+1:row*numADCSamples,i);
        end
    end

    left_numChirps = numChirps - max_numChirps;
    adcData2 = zeros(numRX,left_numChirps*numADCSamples);
    for row = 1:numRX
        for i = 1:left_numChirps
            adcData2(row, (i-1)*numADCSamples+1:i*numADCSamples) = LVDS((row-1)*numADCSamples+1:row*numADCSamples,i+max_numChirps);
        end
    end

    clear LVDS
    retVal = [adcData1, adcData2];

% return receiver data
% data format is [Rx; chirps]
end


function c = getColor(cidxs)

% http://colorbrewer2.org/

color = cell(8,4);

% qualitative
color{1}{1} = [55,126,184];
color{2}{1} = [255,127,0];
color{3}{1} = [255,255,51];%[178,223,138];
color{4}{1} = [0,0,0];
color{5}{1} = [77,175,74];
color{6}{1} = [228,26,28];
% color{6}{1} = [255,255,51];
color{7}{1} = [152,78,163];
color{8}{1} = [247,129,191];

% sequential
color{1}{2} = [253,141,60];
color{1}{3} = [254,204,92];
color{1}{4} = [255,255,178];
color{1}{5} = [254,240,217];

color{2}{2} = [107,174,214];
color{2}{3} = [189,215,231];
color{2}{4} = [117,107,177];

color{3}{2} = [194,230,153];

color{4}{2} = [140,150,198];
color{4}{3} = [179,205,227];
color{4}{4} = [237,248,251];

c = color{cidxs(1)}{cidxs(2)};

end


function grains = minus(grains,xy)
% shift grains in x/y direction
%
% Syntax
%
%   % shift in x direction
%   grains = grains - [100,0]
%
% Input
%  grains- @grain2d
%  xy - x and y coordinates of the shift
%
% Output
%  grains - @grain2d

grains = grains + (-xy);


function plot_circbootfitF()
    % plot_circbootfitF Selects earthquakes in the radius ra around a grid node and calculates the forecast
    % by using calc_bootfitF.m
    %
    % Jochen Woessner
    % turned into function by Celso G Reyes 2017

    ZG=ZmapGlobal.Data; % used by get_zmap_globals
    report_this_filefun();

    ShapeGeneral.clearplot(); % was axes h1, tag plos1

    % interactively get the circle of interest
    shape=ShapeCircle();
    [ZG.newt2, max_km] = selectCircle(newa, shape.toStruct());

    % Select radius in time
    newt3=ZG.newt2;
    vSel = (ZG.newt2.Date <= ZG.maepi.Date+days(time));
    ZG.newt2 = ZG.newt2.subset(vSel);
    R2 = ZG.newt2.Count;
    messtext = ['Number of selected events: ' num2str(ZG.newt2.Count)  ];
    disp(messtext)

    % Sort the catalog
    ZG.newt2.sort('Date');
    R2 = ra;

    % Plot selected earthquakes
    shape.plot([],ZG.newt2); % linespec was xk, tag was plos1

    % Compute and Plot the forecast
    calc_bootfitF(newt3.Date,time,timef,bootloops,ZG.maepi.Date)

    ZG.newcat = ZG.newt2;
    ctp=CumTimePlot(ZG.newt2);
    ctp.plot();

end


classdef ZmapFigureFunction < ZmapFunction
    % ZMAPFIGUREFUNCTION is an interactive figure that is reused
    %    - can be refreshed
    %    - has menu items
    properties(Constant,Abstract)
        FigTag % tag for this figure
    end

    properties
        FigureDetails; % cell containing figure parameters (other than tag)
    end

    properties(Dependent)
        hFig % handle to this figure
    end

    methods(Abstract)
        CreateMenu(obj)
        ClearFigure(obj)
    end

    methods
        function fig = get.hFig(obj)
            fig=findobj('Tag',obj.FigTag,'-and','Type','Figure');
        end

        function doIt(obj)
           CreateFigure(obj);
            % do it is redefined here
        end

        function CreateFigure(obj)
            fig = obj.hFig;
            if isempty(obj.hFig)
                fig=figure('Tag',obj.FigTag,obj.figureDetails{:});
                obj.CreateMenu();
                assert(~isempty(fig) && isvalid(fig),'problem creating figure');

                obj.Calculate();
                obj.plot();
            else
                assert(~isempty(fig) && isvalid(fig),'problem creating figure');
                % duplicated in case a refresh/clearplot is necessary first
                obj.Calculate();
                obj.plot();

            end
        end
    end
end


function event = read_brainvision_vmrk(filename)

% READ_BRAINVISION_VMRK reads the markers and latencies
% it returns the stimulus/response code and latency in ms.
%
% Use as
%   event = read_brainvision_vmrk(filename)
%
% See also READ_BRAINVISION_VHDR, READ_BRAINVISION_EEG

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

fid = fopen_or_error(filename, 'rt');

event = [];
line  = [];

readTime = ft_platform_supports('datetime');

while ischar(line) || isempty(line)
  line = fgetl(fid);
  if ~isempty(line) && ~(isnumeric(line) && line==-1)
    if startsWith(line, 'Mk')
      % this line starts with "Mk", so it probably contains a marker
      tok = strsplit(line, '=');
      if length(tok)~=2
        ft_warning('skipping unexpected formatted line in BrainVision marker file');
      else
        % the line looks like "MkXXX=YYY", which is ok
        % the interesting part now is in the YYY, i.e. the second token
        %tok = strsplit(tok{2}, ','); % this is not robust if there are
        %empty spaces between the ',', see github issue 2026
        tok = tokenize(tok{2}, ',');

        if isempty(tok{1})
          tok{1}  = [];
        end
        if isempty(tok{2})
          tok{2}  = [];
        end
        event(end+1).type     = tok{1};
        event(end  ).value    = tok{2};
        event(end  ).sample   = str2double(tok{3});
        event(end  ).duration = str2double(tok{4});
        if numel(tok)>5 && readTime
          try
            event(end).timestamp = datetime(tok{6}, 'InputFormat', 'yyyyMMddHHmmssSSSSSS');
          catch
            ft_warning('skipping invalid datetime in BrainVision marker file');
            readTime = false;
          end
        end
      end
    end
  end
end

fclose(fid);


function errorFlag=followFluxes(model, fluxesA, lowerFlux, upperFlux, fluxesB)
% followFluxes
%	Prints fluxes and reactions for each of the reactions that results in
%   fluxes in the specified interval.
%
%   model       a model structure
%   fluxesA     flux vector for the test case
%   lowerFlux	only reactions with fluxes above this cutoff
%               value are displayed
%   upperFlux   only reactions with fluxes below this cutoff
%               value are displayed (opt, default Inf)
%   fluxesB     flux vector for the reference case(opt)
%
%   Usage: errorFlag=followFluxes(model, fluxesA, lowerFlux, upperFlux,
%           fluxesB)

%Checks that the upper flux is larger than the lower flux
if nargin>3
    if upperFlux<=lowerFlux
        errorFlag=1;
        return;
    end
end

%Gets the fluxes for the reactions
if nargin<4
    fluxIndexes=find(fluxesA>=lowerFlux);
else
    fluxIndexes=find(fluxesA>=lowerFlux & fluxesA<=upperFlux);
end

%Finds the involved reactions
formulas = constructEquations(model,model.rxns(fluxIndexes));

if nargin>3
    fprintf('These reactions have flux values between %s and %s\n\n',num2str(lowerFlux),num2str(upperFlux));
else
    fprintf('These reactions have flux values above %s\n\n',num2str(lowerFlux));
end
for i=1:length(formulas)
    if nargin>4
        fluxText=['Flux: ' num2str(fluxesA(fluxIndexes(i))) ' Reference flux: ' num2str(fluxesB(fluxIndexes(i)))];
    else
        fluxText=['Flux: ' num2str(fluxesA(fluxIndexes(i)))];
    end
    fprintf('%s: %s\n\t%s\n\t%s\n', char(model.rxns(fluxIndexes(i))), char(formulas(i)),...
        char(model.rxnNames(fluxIndexes(i))),fluxText);
end
end


function [hdr, nameFlag] = read_buffer_v1_header(headerfile)
% function [hdr, nameFlag] = read_buffer_v1_header(headerfile)
%
% This function reads a FCDC buffer header from a binary file.
%
% On return, nameFlag has one of the following values:
%   0 = No labels were generated (fMRI etc.)
%   1 = Fake labels were generated
%   2 = Got channel labels from chunk information

% (C) 2010 S. Klanke

type = {
  'char'
  'uint8'
  'uint16'
  'uint32'
  'uint64'
  'int8'
  'int16'
  'int32'
  'int64'
  'single'
  'double'
};

wordsize = {
  1 % 'char'
  1 % 'uint8'
  2 % 'uint16'
  4 % 'uint32'
  8 % 'uint64'
  1 % 'int8'
  2 % 'int16'
  4 % 'int32'
  8 % 'int64'
  4 % 'single'
  8 % 'double'
};

hdr = [];
hdr.nSamples    = 0;
%hdr.nEvents     = 0;
hdr.nSamplesPre = 0;
hdr.nTrials     = 1;
hdr.orig =[];

nameFlag = 0;

FA = fopen([headerfile '.txt'], 'r');
while ~feof(FA);
  s = fgetl(FA);
  indEq = find(s=='=');
  if numel(indEq)==1
    key = s(1:(indEq-1));
    val = s((indEq+1):end);
    switch key
      case 'fSample'
        hdr.Fs = str2num(val);
      case 'nSamples'
        hdr.nSamples = str2num(val);
      case 'nEvents'
%        hdr.nEvents = str2num(val);
      case 'nChans'
        hdr.nChans = str2num(val);
        hdr.label = cell(hdr.nChans,1);
      case 'dataType'
        if strcmp(val,'float32')
           hdr.orig.data_type = 'single';
        elseif strcmp(val,'float64')
           hdr.orig.data_type = 'double';
        else
          hdr.orig.data_type = val;
        end
      case 'version'
        hdr.orig.version = str2num(val);
      case 'endian'
        if strcmp(val,'big')
          hdr.orig.endianness='ieee-be';
        elseif strcmp(val,'little')
          hdr.orig.endianness='ieee-le';
        else
          error('Invalid value for key ''endian''.');
        end
    end
    continue;
  end
  indCol = find(s==':');
  if numel(indCol)>=1
    ind = str2num(s(1:(indEq-1)));
    name = s((indEq+1):end);
    if ~isempty(ind) && ind>=1 && ind<=hdr.nChans
      hdr.label{ind} = name;
      nameFlag = 2;
    else
      error('Invalid channel name definition - broken header file?');
    end
  end
end

fclose(FA);

F = fopen(headerfile,'rb',hdr.orig.endianness);
bin=[];
bin.nChans    = double(fread(F,1,'uint32'));
bin.nSamples  = double(fread(F,1,'uint32'));
bin.nEvents   = double(fread(F,1,'uint32'));
bin.Fs        = double(fread(F,1,'single'));
bin.data_type = fread(F,1,'uint32');
bin.bufsize   = fread(F,1,'uint32');

if hdr.nChans ~= bin.nChans
   error('Number of channels in binary header does not match ASCII definition');
end
if hdr.nSamples ~= bin.nSamples
   warning('Number of samples in binary header does not match ASCII definition');
end
%if hdr.nEvents ~= bin.nEvents
%   error('Number of samples in binary header does not match ASCII definition');
%end
if strcmp(hdr.orig.data_type, type{bin.data_type+1})
   hdr.orig.wordsize = wordsize{bin.data_type+1};
else
   error('Data type in binary header does not match ASCII definition');
end

if hdr.nSamples == 0
  datafile = [headerfile(1:end-6) 'samples'];
  FD = fopen(datafile, 'rb');
  fseek(FD,0,'eof');
  fileSize = ftell(FD);
  fclose(FD);

  n = fileSize / hdr.orig.wordsize / hdr.nChans;
  hdr.nSamples = floor(n);
  if hdr.nSamples ~= n
    warning('Size of ''samples'' is not a multiple of the size of one sample');
  end
end

% TODO: add chunk handling
while ~feof(F)
	typeAndSize = fread(F, 2, 'uint32');
	if numel(typeAndSize) < 2
		break
	end
	switch typeAndSize(1)
		case 1 % channel names
			% already dealt with, TODO: maybe check consistency with ASCII stuff
			dummy = fread(F, typeAndSize(2), 'uint8=>uint8');
		case 2 % FT_CHUNK_CHANNEL_FLAGS
			% FIXME: ignored for now
			dummy = fread(F, typeAndSize(2), 'uint8=>uint8');
		case 3 % FT_CHUNK_RESOLUTIONS
			if typeAndSize(2) == 8*hdr.nChans
				hdr.resolutions = fread(F, [hdr.nChans, 1], 'double');
			else
				warning('Invalid size of RESOLUTIONS chunk - skipping');
				dummy = fread(F, typeAndSize(2), 'uint8=>uint8');
			end
		case 4 % FT_CHUNK_ASCII_KEYVAL
			dummy = fread(F, typeAndSize(2), 'uint8');
			% FIXME: ignore for now
		case 5 % FT_CHUNK_NIFTI1
			hdr.orig.nifti_1 = fread(F, [1, typeAndSize(2)], 'uint8=>uint8');
			if typeAndSize(2) == 348
				hdr.nifti_1 = decode_nifti1(hdr.orig.nifti_1);
			else
				warning('Invalid size of NIFTI_1 chunk - skipping');
			end
		case 6 % FT_CHUNK_SIEMENS_AP = 6
			hdr.orig.siemensap = fread(F, typeAndSize(2), 'uint8=>uint8');
			if exist('sap2matlab')==3
				hdr.siemensap = sap2matlab(hdr.orig.siemensap);
			end
		case 7 % FT_CHUNK_CTF_RES4 = 7
			hdr.orig.ctf_res4 = fread(F, typeAndSize(2), 'uint8=>uint8');
			tmp_name = tempname;
			FT = fopen(tmp_name, 'wb');
			fwrite(FT, orig.ctf_res4, 'uint8');
			fclose(FT);
			R4F = read_ctf_res4(tmp_name);
			delete(tmp_name);
			% copy over the labels
			hdr.label = R4F.label;
			% copy over the 'original' header
			hdr.orig = R4F;
	end
end

fclose(F);

if nameFlag < 2 && hdr.nChans < 2000
  nameFlag = 1; % fake labels generated - these are unique
  for i=1:hdr.nChans
    hdr.label{i} = sprintf('%d', i);
  end
end


function save_avw(img,fname,vtype,vsize)
% SAVE_AVW(img,fname,vtype,vsize)
%
%  Create and save an analyse header (.hdr) and image (.img) file
%   for either a 2D or 3D or 4D array (automatically determined).
%  fname is the filename (must be inside single quotes)
%
%  vtype is 1 character: 'b'=unsigned byte, 's'=short, 'i'=int, 'f'=float
%                        'd'=double or 'c'=complex
%  vsize is a vector [x y z tr] containing the voxel sizes in mm and
%  the tr in seconds  (defaults: [1 1 1 3])
%
%  See also: READ_AVW
%

   if ((~isreal(img)) & (vtype~='c')),
     disp('WARNING:: Overwriting type - saving as complex');
     save_avw_complex(img,fname,vsize);
   else
     if (vtype=='c'),
       save_avw_complex(img,fname,vsize);
     else
       save_avw_hdr(img,fname,vtype,vsize);
       save_avw_img(img,fname,vtype);
     end
   end


function model = multimodelExpandParam(model, params)

% MULTIMODELEXPANDPARAM Create model structure from MULTIMODEL model's parameters.
% FORMAT
% DESC returns a multi-task learning wrapper model structure filled with the
% parameters in the given vector. This is used as a helper function to
% enable parameters to be optimised in, for example, the NETLAB
% optimisation functions.
% ARG model : the model structure in which the parameters are to be
% placed.
% ARG param : vector of parameters which are to be placed in the
% model structure.
% RETURN model : model structure with the given parameters in the
% relevant locations.
%
% SEEALSO : multimodelCreate, multimodelExtractParam, modelExpandParam
%
% COPYRIGHT : Neil D. Lawrence, 2007, 2008
%
% MODIFICATIONS: Mauricio Alvarez, 2008, 2009

% MLTOOLS

if numel(model.outputDim) == 1
    endVal = model.numParams - model.numModels*model.numSep;
    baseParams = params(1:endVal);
    passParams(model.sharedIndices) = baseParams;
    if ~isempty(model.separateIndices)
        for i = 1:length(model.comp)
            startVal = endVal + 1;
            endVal = endVal + model.numSep;
            passParams(model.separateIndices) = params(startVal:endVal);
            model.comp{i} = modelExpandParam(model.comp{i}, passParams);
        end
    else
        for i = 1:length(model.comp)
            model.comp{i} = modelExpandParam(model.comp{i}, passParams);
        end
    end
else
    startVal = 1;
    endVal = 0;
    for i = 1:length(model.comp)
        endVal = endVal + model.comp{i}.nParams;
        model.comp{i} = modelExpandParam(model.comp{i}, params(startVal:endVal));
        startVal = endVal + 1;
    end
end


function [net, info] = cnn_dicnn_of(varargin)
%CNN_DICNN_OF Fine-tunes a pre-trained CNN with dynamic images on optical
% (DOF in pami journal) flow frames on UCF101 dataset

run(fullfile(fileparts(mfilename('fullpath')), ...
  '..', 'matconvnet', 'matlab', 'vl_setupnn.m')) ;

run(fullfile(fileparts(mfilename('fullpath')), ...
  '..', 'matconvnet', 'contrib', 'mcnExtraLayers', 'setup_mcnExtraLayers.m')) ;

run(fullfile(fileparts(mfilename('fullpath')), ...
  '..', 'matconvnet', 'contrib', 'autonn', 'setup_autonn.m')) ;

addpath Layers Datasets

opts.dataDir = fullfile('data','UCF101') ;
opts.expDir  = fullfile('exp', 'UCF101') ;
opts.modelPath = fullfile('models','resnext_50_32x4d-pt-mcn.mat.mat') ;
[opts, varargin] = vl_argparse(opts, varargin) ;

opts.numFetchThreads = 8 ;

opts.lite = false ;
opts.imdbPath = fullfile(opts.dataDir, 'imdb-of.mat');
opts.pool1Layer = 'conv0'; % before conv1
opts.pool1Type = 'arpool'; % before conv1
opts.pool2Layer = 'fc6'; % before conv1
opts.DropOutRate = 0.85 ;
opts.datasetFn = @cnn_ucf101_of_setup_data ;
opts.networkFn = @cnn_init_resnext ;
opts.network = [] ;

opts.split = 1; % data split
opts.reverseDyn = 0; % reverse video frames e.g.[N:-1:1]
opts.numDynImgs = 10 ;
opts.epochFactor = 5 ;

opts.train = struct() ;
opts.train.gpus = [];
opts.train.batchSize = 128 ;
opts.train.numSubBatches = 32 ;
opts.train.solver = [] ;
opts.train.prefetch = true ;
opts.train.learningRate = 1e-2 ;
opts.train.numEpochs = 30 ;
% opts.train.savePreds = true ;
opts.train.randomSeed = 0 ;

opts = vl_argparse(opts, varargin) ;
if ~isfield(opts.train, 'gpus'), opts.train.gpus = []; end;

% -------------------------------------------------------------------------
%                                                              Prepare data
% -------------------------------------------------------------------------

if exist(opts.imdbPath,'file')
  imdb = load(opts.imdbPath) ;
else
  imdb = opts.datasetFn('dataDir', opts.dataDir, 'lite', opts.lite) ;
  mkdir(opts.expDir) ;
  save(opts.imdbPath, '-struct', 'imdb') ;
end

% UCF101 has 3 data splits
if opts.split>3
  error('split should be <=3');
end
imdb.images.set = imdb.images.sets(opts.split,:);

% reverse frame order
if opts.reverseDyn
  for i=1:numel(imdb.images.names)
    imdb.images.names{i} = imdb.images.names{i}(end:-1:1);
  end
end
% -------------------------------------------------------------------------
%                                                             Prepare model
% -------------------------------------------------------------------------
if isempty(opts.network)
  net = load(opts.modelPath);
  if isfield(net,'net')
    net = net.net;
  end
  opts.nCls = max(imdb.images.label) ;
  % net = dagnn.DagNN.loadobj(net) ;
  net = opts.networkFn(net,opts) ;

  % two channels instead of 3 RGB
  net.params(1).value = net.params(1).value(:,:,1:2,:) ;

  % Set the class names in the network
  net.meta.classes.name = imdb.classes.name ;
  net.meta.classes.description = imdb.classes.name ;
else
  assert(isa(opts.network,'dagnn.DagNN')) ;
  net = opts.network ;
end

% -------------------------------------------------------------------------
%                                                                     Learn
% -------------------------------------------------------------------------
if opts.epochFactor>0
  opts.train.train = repmat(find(imdb.images.set==1),[1 opts.epochFactor]) ;
else
  opts.train.train = NaN ;
  opts.train.numEpochs = 1 ;
end
opts.train.val = find(imdb.images.set==3) ;

[net, info] = cnn_train_dicnn_dag(net, imdb, getBatchFn(opts, net.meta), ...
                      'expDir', opts.expDir, ...
                      opts.train) ;

% -------------------------------------------------------------------------
%                                                          Report accuracy
% -------------------------------------------------------------------------
errlayer = net.getLayerIndex('errMC') ;

if ~isnan(errlayer)
  cats = imdb.classes.name ;
  accs = net.layers(errlayer).block.accuracy ;

  if numel(cats)~=numel(accs)
    error('wrong number of classes\n') ;
  end

  for i=1:numel(cats)
    fprintf('%s acc %.1f\n',cats{i},100*accs(i)) ;
  end
  fprintf('Mean accuracy %.1f\n',100*mean(accs)) ;
end
% -------------------------------------------------------------------------
function fn = getBatchFn(opts, meta)
% -------------------------------------------------------------------------
useGpu = numel(opts.train.gpus) > 0 ;

bopts.numThreads = opts.numFetchThreads ;
bopts.imageSize = meta.normalization.imageSize ;
if isfield(meta.normalization,'border')
  bopts.border = meta.normalization.border ;
else
  bopts.border = meta.normalization.imageSize(1:2) ./ ...
    meta.normalization.cropSize - meta.normalization.imageSize(1:2);
end

bopts.averageImage = 128 * ones([1 1 2],'single') ;
bopts.numDynImgs = opts.numDynImgs ;

fn = @(x,y) getDagNNBatch(bopts,useGpu,x,y) ;

% -------------------------------------------------------------------------
function inputs = getDagNNBatch(opts, useGpu, imdb, batch)
% -------------------------------------------------------------------------

% batch refers to videos (not for frames)
if isempty(batch)
  inputs = {'input', [], 'label', [], 'VideoId1', [], 'VideoId2', []};
  return;
end

isVal = ~isempty(batch) && imdb.images.set(batch(1)) ~= 1 ;

if ~isVal, transformation='multiScaleRegular'; else transformation='none';end

names = imdb.images.names(batch);

% images = strcat([imdb.imageDir filesep], imdb.images.name(batch)) ;

namesM = {};
nVids = numel(batch);

VideoId1 = [];
VideoId2 = [];

% step-size
stepSize = 6;

% pool nFrames into a dynamic image
nFrames = 10;
% number of dynamic images to be max pooled later
nDynImgs = opts.numDynImgs ;
opts = rmfield(opts,'numDynImgs') ;

c1 = 1;
for v=1:nVids

  name = names{v};
  nFrms = numel(name)/2;

  nSample = nFrames;

  if isVal
    startF = 1 ;
  else
    startF = ceil(stepSize/2) ;
  end
  nr = numel(startF:stepSize:nFrms);

  % jitter by removing 50 % and limit a batch to nMaxs * nSamples images
  if nr > 1 && (~isVal && nr>nDynImgs)
    rat = min(nDynImgs,ceil(0.50*nr));
    ri = randperm(nr);
    ri = ri(1:rat);
    r = zeros(1,nr);
    r(ri) = 1;
  else
    r = ones(1,nr);
  end

  c3 = 1;
  c2 = 0;

  for f=startF:stepSize:nFrms
    if r(c3)
      idx = f:min(f+nSample-1,nFrms) ;
      if numel(idx)<nFrames
        idx = [idx idx(end) * ones(1,nFrames-numel(idx))];
      end
      idxu = 2*idx - 1;
      idxv = 2*idx;
      idxuv = zeros(1,2 * numel(idxu)) ;
      idxuv(1:2:end) = idxu ;
      idxuv(2:2:end) = idxv ;

      namesM{end+1} = name(idxuv);
      VideoId1 = [VideoId1 c1 * ones(1,numel(idx))];
      c1 = c1 + 1;
      c2 = c2 + 1;
    end
    c3 = c3 + 1;
  end
  VideoId2 = [VideoId2 v * ones(1,c2) ] ;
end

images = strcat([imdb.imageDir filesep], horzcat(namesM{:}) ) ;

im = cnn_video_of_get_batch(images, VideoId1, opts, ...
  'transformation', transformation, 'prefetch', nargout == 0) ;

if nargout > 0
  if useGpu
    im = gpuArray(im) ;
  end
  inputs = {'input', im, 'label', imdb.images.label(batch), ...
    'VideoId1', VideoId1, 'VideoId2', VideoId2};

end


function [ correct_samples, total_samples, correct_un_samples, total_un_samples ] = rcnn_test_idpr_predictions( expidx, image_set, firstidx, nImgs, bVis )

fprintf('rcnn_test_idpr_predictions()\n');

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

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

imdb = exp2imdb(expidx, image_set);

if (nargin < 4)
    nImgs = length(imdb.image_ids);
elseif ischar(nImgs)
    nImgs = str2num(nImgs);
end

if (nargin < 5)
    bVis = false;
end

fprintf('expidx: %d\n',expidx);
fprintf('firstidx: %d\n',firstidx);
fprintf('nImgs: %d\n',nImgs);

p = exp_params(expidx);
exp_dir = [p.expDir '/' p.shortName];
fprintf('exp_dir: %s\n',exp_dir);

if (isfield(p, 'featExpDir'))
    feat_exp_dir = p.featExpDir;
else
    feat_exp_dir = exp_dir;
end

cache_name   = 'v1_finetune_iter_70k';

if (isfield(p,'pwModelExpDir'))
    model_exp_dir = p.pwModelExpDir;
else
    model_exp_dir = exp_dir;
end

conf = rcnn_config('sub_dir', '/cachedir/train', 'exp_dir', model_exp_dir);
net_file = rcnn_get_net_filename(p.netsDir);
assert(~isempty(net_file));

lastidx = firstidx + nImgs - 1;
if (lastidx > length(imdb.image_ids))
    lastidx = length(imdb.image_ids);
end

if (firstidx > lastidx)
    return;
end

conf = rcnn_config('sub_dir', ['/cachedir/' imdb.image_set], 'exp_dir', exp_dir);

joints = zeros(length(firstidx:lastidx), length(p.pidxs), 2);

num_classes = sum(p.idpr_num_clusters)+1;
skip_class = num_classes;

top_k = 2;

total_samples = zeros(num_classes, 1);
correct_samples = zeros(num_classes, 1);
correct_topk_samples = zeros(num_classes, 1);

num_joints = 14;
total_un_samples = zeros(num_joints+1, 1);
correct_un_samples = zeros(num_joints+1, 1);

cumul_num_clusters = zeros(1, length(p.idpr_num_clusters));
for i = 1:length(p.idpr_num_clusters)
    cumul_num_clusters(i) = sum(p.idpr_num_clusters(1:i));
end

for i = firstidx:lastidx

    tic
    fprintf('%s: test (%s) %d/%d\n', procid(), imdb.name, i, length(imdb.image_ids));
    file = sprintf('%s/feat_cache/%s/%s/%s', feat_exp_dir, cache_name, imdb.image_set, imdb.image_ids{i});
    d = rcnn_load_cached_pool5_features(file);

    assert(~isempty(d.feat));
    %if isempty(d.feat)
    %    continue;
    %end

    feat_len = size(d.feat, 2);
    if feat_len == 9216
        featFC8 = rcnn_pool5_to_fcX(d.feat, 8, rcnn_model);
        featFC8 = rcnn_softmax(featFC8);
    else
        featFC8 = d.feat;
    end
    featFC8_score = featFC8(:,2:end);

    overlap = d.overlap;

    boxes = d.boxes;

    num_boxes = size(boxes, 1);
    for j = 1:num_boxes
        [ov, gt_label] = max(overlap(j,:));
        % zero overlap => label = 0 (background)
        if gt_label == skip_class
            continue;
        end
        if ov < 0.5
          gt_label = 0;
        end
        [~, pred_label] = max(featFC8(j,:));
        pred_label = pred_label-1;

        if gt_label == 0
            gt_un_label = 0;
        else
            gt_un_label =  find(cumul_num_clusters >= gt_label, 1);
        end
        if pred_label == 0
            pred_un_label = 0;
        else
            pred_un_label =  find(cumul_num_clusters >= pred_label, 1);
        end

        total_un_samples(gt_un_label+1) = total_un_samples(gt_un_label+1) + 1;
        total_samples(gt_label+1) = total_samples(gt_label+1) + 1;

        if pred_label == gt_label
            correct_samples(gt_label+1) = correct_samples(gt_label+1) + 1;
        end
        if pred_un_label == gt_un_label
            correct_un_samples(gt_un_label+1) = correct_un_samples(gt_un_label+1) + 1;
        end

        [~, max_labels] = sort(featFC8(j,:), 'descend');
        for k = 1:top_k
            pred_k_label = max_labels(k)-1;
            if pred_k_label == gt_label
                correct_topk_samples(gt_label+1) = correct_topk_samples(gt_label+1) + 1;
                break;
            end
        end

    end
end

toc

fprintf('accuracy for positives idpr %f\n', sum(correct_samples(2:end))/sum(total_samples(2:end)));
fprintf('accuracy for positives top k idpr %f\n', sum(correct_topk_samples(2:end))/sum(total_samples(2:end)));
fprintf('accuracy for positives unary %f\n', sum(correct_un_samples(2:end))/sum(total_un_samples(2:end)));

fprintf('done\n');

if (isdeployed)
    close all;
end

end


function [curv] = write_curv(fname, curv, fnum)
% [curv] = write_curv(fname, curv, fnum)
%
% writes a curvature vector into a binary file
%				fname - name of file to write to
%				curv  - vector of curvatures
%				fnum  - # of faces in surface.
%

%
% write_curv.m
%
% Original Author: Bruce Fischl
% CVS Revision Info:
%    $Author: nicks $
%    $Date: 2011/03/02 00:04:13 $
%    $Revision: 1.3 $
%
% Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH"
%
% Terms and conditions for use, reproduction, distribution and contribution
% are found in the 'FreeSurfer Software License Agreement' contained
% in the file 'LICENSE' found in the FreeSurfer distribution, and here:
%
% https://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferSoftwareLicense
%
% Reporting: freesurfer@nmr.mgh.harvard.edu
%

% open it as a big-endian file
fid = fopen(fname, 'wb', 'b') ;
vnum = length(curv) ;
NEW_VERSION_MAGIC_NUMBER = 16777215;
fwrite3(fid, NEW_VERSION_MAGIC_NUMBER ) ;
fwrite(fid, vnum,'int32') ;
fwrite(fid, fnum,'int32') ;
fwrite(fid, 1, 'int32');
fwrite(fid, curv, 'float') ;
fclose(fid) ;


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

%%
clear; close all; clc;

%% Syntax
% |P=ricianpdf(A,M,S);|

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


function gen_caffe_validation_imageset

% only validation images
% don't worry about padding. Use small batch size for p5 feat extraction

conf = config;

images_v = load(fullfile(conf.root_path, ...
    'validation_images_crop15_square256.mat'), 'validation_images');
images_v = images_v.validation_images;

images = cat(4, images_v.img);

validation_filenames = {images_v.filename};

assert(length(images) == length(validation_filenames));

% images must be (height x width x channels x num)
assert(ndims(images) == 4);
% assume square images
assert(size(images, 1) == size(images, 2));
% images must have 3 channels
assert(size(images, 3) == 3);
% Convert to BGR
images = images(:,:,[3 2 1],:);
% Switch width and height
images = permute(images, [2 1 3 4]);

savefilename = conf.validation_set_path;
imageset_to_leveldb(images, savefilename);
fprintf('Done writing level db\n');

save(fullfile(conf.cache_path, 'validation_filenames.mat'), 'validation_filenames');


% This .m file, "view_mcgrid.m", plots ratechanges calculated with mcgrid.m
% needs re3, gx, gy
%
% define size of the plot etc.
%
if isempty(name) >  0
    name = '  '
end
think
report_this_filefun(mfilename('fullpath'));
%co = 'w';

% This is the info window text
%
ttlStr='The b and p -Value Map Window                 ';
hlpStr1zmap= ...
    ['                                                '
    ' This window displays b-values and p-values     '
    ' using a color code.                            '
    ' Some of the menu-bar options are               '
    ' described below:                               '
    '                                                '
    ' Threshold: You can set the maximum size that   '
    '   a volume is allowed to have in order to be   '
    '   displayed in the map. Therefore, areas with  '
    '   a low seismicity rate are not displayed.     '
    '   edit the size (in km) and click the mouse    '
    '   outside the edit window.                     '
    'FixAx: You can chose the minimum and maximum    '
    '        values of the color-legend used.        '
    'Polygon: You can select earthquakes in a        '
    ' polygon either by entering the coordinates or  '
    ' defining the corners with the mouse            '];
hlpStr2zmap= ...
    ['                                                '
    'Circle: Select earthquakes in a circular volume:'
    '      Ni, the number of selected earthquakes can'
    '      be edited in the upper right corner of the'
    '      window.                                   '
    ' Refresh Window: Redraws the figure, erases     '
    '       selected events.                         '

    ' zoom: Selecting Axis -> zoom on allows you to  '
    '       zoom into a region. Click and drag with  '
    '       the left mouse button. type <help zoom>  '
    '       for details.                             '
    ' Aspect: select one of the aspect ratio options '
    ' Text: You can select text items by clicking.The'
    '       selected text can be rotated, moved, you '
    '       can change the font size etc.            '
    '       Double click on text allows editing it.  '
    '                                                '
    '                                                '];

% Set up the Seismicity Map window Enviroment
%

% Find out of figure already exists
%
[existFlag,figNumber]=figure_exists('rc-value-map',1);
newrcmapWindowFlag=~existFlag;

if newrcmapWindowFlag
    oldfig_button = 0
end

if oldfig_button == 0
    rcmap = figure_w_normalized_uicontrolunits( ...
        'Name','rc-value-map',...
        'NumberTitle','off', ...
        'MenuBar','none', ...
        'NextPlot','new', ...
        'backingstore','on',...
        'Visible','off', ...
        'Position',[ (fipo(3:4) - [600 400]) ZmapGlobal.Data.map_len]);
    % make menu bar
    matdraw

    %lab1 = 'p-value:';

    add_symbol_menu('eq_plot');

    %    uicontrol('Units','normal',...
    %       'Position',[.0 .93 .08 .06],'String','Info ',...
    %        'Callback',' web([''file:'' hodi ''/zmapwww/chp11.htm#996756'']) ');

    options = uimenu('Label',' Analyze ');
    uimenu(options,'Label','Refresh ', 'Callback','view_tcgrid')
    %    uimenu(options,'Label','Select EQ in Circle',...
    %        'Callback','h1 = gca;met = ''ni''; ho=false;cirpva;watchoff(rcmap)')
    uimenu(options,'Label','Select EQ in Circle - Constant R',...
         'Callback','h1 = gca;met = ''ra''; ho=false;plot_circ_FMD2Periods;watchoff(rcmap)')
    uimenu(options,'Label','Select EQ with const. number',...
         'Callback','h1 = gca;ho2=true;ho=true;plot_constnrbootfit_a2;watchoff(rcmap)')

    op1 = uimenu('Label',' Maps ');

    %Menu for adjusting several parameters.
    adjmenu =  uimenu(op1,'Label','Adjust Map Display Parameters'),...
        uimenu(adjmenu,'Label','Adjust Mmin cut',...
         'Callback','asel = ''mag''; adju2; view_mcgrid ')
    uimenu(adjmenu,'Label','Adjust Rmax cut',...
         'Callback','asel = ''rmax''; adju2; view_mcgrid')
    uimenu(adjmenu,'Label','Adjust goodness of fit cut',...
         'Callback','asel = ''gofi''; adju2; view_mcgrid ')
    uimenu(adjmenu,'Label','Adjust p-value st. dev. cut',...
         'Callback','asel = ''pstdc''; adju2; view_mcgrid ')
    % Menu MAPS
    uimenu(op1,'Label','Magnitude shift',...
         'Callback',' lab1=''dM'';re3 = mMagShift; view_mcgrid')
    uimenu(op1,'Label','KS-Test result',...
         'Callback','lab1=''H'';re3 = mHkstest; view_mcgrid')
    uimenu(op1,'Label','Magnitude shift validated',...
         'Callback',' lab1=''dM'';re3 = mMagShift_valid; view_mcgrid')
    uimenu(op1,'Label','Normalized \Delta_{FMD}',...
         'Callback','lab1=''\Delta_{FMD}'';re3 = mChFMD; view_mcgrid')
    uimenu(op1,'Label','Resolution Map (Number of events period 1)',...
         'Callback','lab1=''Number of events'';re3 = mNumevents1; view_mcgrid')
    uimenu(op1,'Label','Resolution Map (Number of events period 2)',...
         'Callback','lab1=''Number of events'';re3 = mNumevents2; view_mcgrid')
    uimenu(op1,'Label','Mc period 1',...
         'Callback','lab1=''Mc'';re3 = mMc1; view_mcgrid')
    uimenu(op1,'Label','Mc period 2',...
         'Callback','lab1=''Mc'';re3 = mMc2; view_mcgrid')
    uimenu(op1,'Label','Mc change',...
         'Callback','lab1=''dMc'';re3 = mdMc; view_mcgrid')
    uimenu(op1,'Label','Mc change validated',...
         'Callback','lab1=''dMc'';re3 = mdMc_val; view_mcgrid')
    uimenu(op1,'Label','AIC difference Utsu',...
         'Callback','lab1=''dAIC'';re3 = mdAIC_Utsu; view_mcgrid')
    uimenu(op1,'Label','Probability of stationarity (favoring stationarity)',...
         'Callback','lab1=''Mc'';re3 = mStationary1_Utsu; view_mcgrid')
    uimenu(op1,'Label','Probability of stationarity (favoring non-stationarity)',...
         'Callback','lab1=''Prob'';re3 = mStationary2_Utsu; view_mcgrid')

    % Menu DISPLAY
    add_display_menu(1);

    %re3 = pvalg;
    tresh = nan; re4 = re3;
    oldfig_button = 1;

    colormap(jet)
    tresh = nan; minpe = nan; Mmin = nan; minsd = nan;

end   % This is the end of the figure setup.

% Now lets plot the color-map!
%
figure_w_normalized_uicontrolunits(rcmap)
delete(gca)
delete(gca)
delete(gca)
dele = 'delete(sizmap)';er = 'disp('' '')'; eval(dele,er);
reset(gca)
cla
hold off
watchon;
set(gca,'visible','off','FontSize',ZmapGlobal.Data.fontsz.s,'FontWeight','bold',...
    'FontWeight','bold','LineWidth',1.5,...
    'Box','on','SortMethod','childorder')

rect = [0.18,  0.10, 0.7, 0.75];
rect1 = rect;

% find max and min of data for automatic scaling
maxc = max(max(re3));
maxc = fix(maxc)+1;
minc = min(min(re3));
minc = fix(minc)-1;

% set values greater tresh = nan
%
re4 = re3;

% plot image
%
orient landscape
%set(gcf,'PaperPosition', [0.5 1 9.0 4.0])

%Plots re4, which contains the filtered values.
axes('position',rect)
hold on
pco1 = pcolor(gx,gy,re4);

axis([ min(gx) max(gx) min(gy) max(gy)])
axis image
hold on
if sha == 'fl'
    shading flat
else
    shading interp
end
% make the scaling for the recurrence time map reasonable
if lab1(1) =='T'
    l = isnan(re3);
    re = re3;
    re(l) = [];
    caxis([min(re) 5*min(re)]);
end

%If the colorbar is freezed.
if fre == 1
    caxis([fix1 fix2])
end

title2([name ';  '   num2str(t0b) ' to ' num2str(teb) ],'FontSize',ZmapGlobal.Data.fontsz.s,...
    'Color','r','FontWeight','bold')

xlabel('Longitude [deg]','FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.s)
ylabel('Latitude [deg]','FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.s)

% plot overlay
%
hold on
overlay_
ploeq = plot(a.Longitude,a.Latitude,'k.');
set(ploeq,'Tag','eq_plot','MarkerSize',ms6,'Marker',ty,'Color',co,'Visible',vi)

set(gca,'visible','on','FontSize',ZmapGlobal.Data.fontsz.s,'FontWeight','bold',...
    'FontWeight','bold','LineWidth',1.5,...
    'Box','on','TickDir','out')
h1 = gca;
hzma = gca;

% Create a colorbar
%
h5 = colorbar('horiz');
set(h5,'Pos',[0.35 0.05 0.4 0.02],...
    'FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.s,'TickDir','out')

rect = [0.00,  0.0, 1 1];
axes('position',rect)
axis('off')
%  Text Object Creation
txt1 = text(...
    'Color',[ 0 0 0 ],...
    'EraseMode','normal',...
    'Units','normalized',...
    'Position',[ 0.33 0.06 0 ],...
    'HorizontalAlignment','right',...
    'Rotation',[ 0 ],...
    'FontSize',ZmapGlobal.Data.fontsz.s,....
    'FontWeight','bold',...
    'String',lab1);

% Make the figure visible
%
set(gca,'FontSize',ZmapGlobal.Data.fontsz.s,'FontWeight','bold',...
    'FontWeight','bold','LineWidth',1.5,...
    'Box','on','TickDir','out')
figure_w_normalized_uicontrolunits(rcmap);
%sizmap = signatur('ZMAP','',[0.01 0.04]);
%set(sizmap,'Color','k')
axes(h1)
watchoff(rcmap)
%whitebg(gcf,[ 0 0 0 ])
done