classdef ConstraintEnum < matlab.mixin.SetGet
    %ConstraintEnum Summary of this class goes here
    %   Detailed explanation goes here

    enumeration
        UniversalTime('Universal Time','GenericMAConstraint','Universal Time')

        PosX('Position Vector (X)','GenericMAConstraint','Position Vector (X)')
        PosY('Position Vector (Y)','GenericMAConstraint','Position Vector (Y)')
        PosZ('Position Vector (Z)','GenericMAConstraint','Position Vector (Z)')
        VelX('Velocity Vector (X)','GenericMAConstraint','Velocity Vector (X)')
        VelY('Velocity Vector (Y)','GenericMAConstraint','Velocity Vector (Y)')
        VelZ('Velocity Vector (Z)','GenericMAConstraint','Velocity Vector (Z)')

        PosVectMag('Position Vector Magnitude','GenericMAConstraint','Position Vector Magnitude')
        VelVectMag('Velocity Vector Magnitude','GenericMAConstraint','Velocity Vector Magnitude')

        SMA('Semi-major Axis','GenericMAConstraint','Semi-major Axis')
        Ecc('Eccentricity','GenericMAConstraint','Eccentricity')
        Inc('Inclination','GenericMAConstraint','Inclination')
        RAAN('Right Asc. of the Asc. Node','GenericMAConstraint','Right Asc. of the Asc. Node')
        ArgPeri('Argument of Periapsis','GenericMAConstraint','Argument of Periapsis')
        TrueAnom('True Anomaly','GenericMAConstraint','True Anomaly')
        MeanAnom('Mean Anomaly','GenericMAConstraint','Mean Anomaly')
        OrbitPeriod('Orbital Period','GenericMAConstraint','Orbital Period')

        RadiusPeriapsis('Radius of Periapsis','GenericMAConstraint','Radius of Periapsis')
        RadiusApoapsis('Radius of Apoapsis','GenericMAConstraint','Radius of Apoapsis')
        AltitudeApoapsis('Altitude of Apoapsis','GenericMAConstraint','Altitude of Apoapsis')
        AltitudePeriapsis('Altitude of Periapsis','GenericMAConstraint','Altitude of Periapsis')

        H1('Equinoctial H1','GenericMAConstraint','Equinoctial H1')
        K1('Equinoctial K1','GenericMAConstraint','Equinoctial K1')
        H2('Equinoctial H2','GenericMAConstraint','Equinoctial H2')
        K2('Equinoctial K2','GenericMAConstraint','Equinoctial K2')

        FlightPathAngle('Flight Path Angle','GenericMAConstraint','Flight Path Angle');
        Longitude('Longitude (East)','GenericMAConstraint','Longitude (East)')
        Latitude('Latitude (North)','GenericMAConstraint','Latitude (North)')
        Altitude('Altitude','GenericMAConstraint','Altitude')
        VelAz('Velocity Azimuth','GenericMAConstraint','Velocity Azimuth')
        VelEl('Velocity Elevation','GenericMAConstraint','Velocity Elevation')
        LongitudeDriftRate('Longitudinal Drift Rate','GenericMAConstraint','Longitudinal Drift Rate')

        C3Energy('C3 Energy','GenericMAConstraint','C3 Energy');
        SecPastPeri('Seconds Past Periapsis','GenericMAConstraint','Seconds Past Periapsis');

        SurfaceVelocity('Surface Velocity','GenericMAConstraint','Surface Velocity')
        VerticalVel('Vertical Velocity','GenericMAConstraint','Vertical Velocity')

        HyperVelUnitX('Hyperbolic Velocity Unit Vector X','GenericMAConstraint','Hyperbolic Velocity Unit Vector X')
        HyperVelUnitY('Hyperbolic Velocity Unit Vector Y','GenericMAConstraint','Hyperbolic Velocity Unit Vector Y')
        HyperVelUnitZ('Hyperbolic Velocity Unit Vector Z','GenericMAConstraint','Hyperbolic Velocity Unit Vector Z')
        HyperVelRA('Hyperbolic Velocity Vector Right Ascension','GenericMAConstraint','Hyperbolic Velocity Vector Right Ascension')
        HyperVelDec('Hyperbolic Velocity Vector Declination','GenericMAConstraint','Hyperbolic Velocity Vector Declination')
        HyperVelMag('Hyperbolic Velocity Magnitude','GenericMAConstraint','Hyperbolic Velocity Magnitude')

        SolarBetaAngle('Solar Beta Angle','GenericMAConstraint','Solar Beta Angle')
        TotalScMass('Total Spacecraft Mass','GenericMAConstraint','Total Spacecraft Mass')

        PitchAngle('Pitch Angle','PitchAngleConstraint',[]);
        RollAngle('Roll Angle','RollAngleConstraint',[]);
        YawAngle('Yaw Angle','YawAngleConstraint',[]);
        Throttle('Throttle','ThrottleConstraint',[]);

        BankAngle('Bank Angle','BankAngleConstraint',[]);
        AngleOfAttack('Angle of Attack','AngleOfAttackConstraint',[]);
        SideSlipAngle('Side Slip Angle','SideSlipAngleConstraint',[]);

        InertialAngleOfAttack('Inertial Angle of Attack','InertialAngleOfAttackConstraint',[]);
        InertialBankAngle('Inertial Bank Angle','InertialBankAngleConstraint',[]);
        InertialSideSlipAngle('Inertial Side Slip Angle','InertialSideSlipAngleConstraint',[]);

        TotalThrust('Total Thrust','TotalThrustConstraint',[]);
        Thrust2Weight('Sea Level Thrust to Weight','ThrustToWeightConstraint',[]);

        StopwatchValue('Stopwatch Value','StopwatchValueConstraint',[]);
        ExtremumValue('Extremum Value','ExtremumValueConstraint',[]);

        TwoBodyImpactTime('Two-Body Time To Impact','TwoBodyImpactPointTime',[]);
        TwoBodyImpactLong('Two-Body Impact Longitude','TwoBodyImpactPointLongitude',[]);
        TwoBodyImpactLat('Two-Body Impact Latitude','TwoBodyImpactPointLatitude',[]);

        EventDeltaVExpended('Event Delta-V Expended','EventDeltaVExpendedConstraint',[]);

        CalculusCalculation('Calculus Calculation','CalculusCalculationValueConstraint',[]);

        CumulativePwrStorageStateOfCharge('Electrical Power Cumulative Storage State of Charge', 'CumPwrStorageStateOfChargeConstraint', []);

        GroundObjAz('Ground Object Azimuth', 'GroundObjAzConstraint', []);
        GroundObjEl('Ground Object Elevation', 'GroundObjElConstraint', []);
        GroundObjRng('Ground Object Range', 'GroundObjRangeConstraint', []);

        GeoVectorMagntide('Geometric Vector Magnitude', 'GeometricVectorMagConstraint', []);
        GeoVectorXComponent('Geometric Vector X', 'GeometricVectorXConstraint', []);
        GeoVectorYComponent('Geometric Vector Y', 'GeometricVectorYConstraint', []);
        GeoVectorZComponent('Geometric Vector Z', 'GeometricVectorZConstraint', []);

        GeoAngleMagnitude('Geometric Angle Magnitude', 'GeometricAngleMagConstraint', []);

        TankMass('Tank Mass', 'TankMassConstraint', []);
        TankMassFlowRate('Tank Mass Flow Rate', 'TankMassFlowRateConstraint', []);

        Plugin('Plugin Value', 'PluginConstraint', []);
    end

    enumeration(Hidden)
        BodyCentricPositionX('Body-centric Position (X)','GenericMAConstraint','Body-centric Position (X)')
        BodyCentricPositionY('Body-centric Position (Y)','GenericMAConstraint','Body-centric Position (Y)')
        BodyCentricPositionZ('Body-centric Position (Z)','GenericMAConstraint','Body-centric Position (Z)')
        BodyCentricVelocityX('Body-centric Velocity (X)','GenericMAConstraint','Body-centric Velocity (X)')
        BodyCentricVelocityY('Body-centric Velocity (Y)','GenericMAConstraint','Body-centric Velocity (Y)')
        BodyCentricVelocityZ('Body-centric Velocity (Z)','GenericMAConstraint','Body-centric Velocity (Z)')
        SunCentricPositionX('Sun-centric Position (X)','GenericMAConstraint','Sun-centric Position (X)')
        SunCentricPositionY('Sun-centric Position (Y)','GenericMAConstraint','Sun-centric Position (Y)')
        SunCentricpositionZ('Sun-centric Position (Z)','GenericMAConstraint','Sun-centric Position (Z)')

        RadiusSpacecraft('Radius of Spacecraft','GenericMAConstraint','Radius of Spacecraft')
        SpeedOfSpacecraft('Speed of Spacecraft','GenericMAConstraint','Speed of Spacecraft')

        DistToRefCelBody('Distance to Ref. Celestial Body','GenericMAConstraint','Distance to Ref. Celestial Body')

        CentralBodyId('Central Body ID','GenericMAConstraint','Central Body ID')
        FuelOxMass('Liquid Fuel/Ox Mass','GenericMAConstraint','Liquid Fuel/Ox Mass')
        MonopropMass('Monopropellant Mass','GenericMAConstraint','Monopropellant Mass')
        XenonMass('Xenon Mass','GenericMAConstraint','Xenon Mass')

        TimeContinuity('Time Continuity','TimeContinuityConstraint',[]);
        PositionContinuityX('Position Continuity (X)','PositionContinuityConstraintX',[]);
        PositionContinuityY('Position Continuity (Y)','PositionContinuityConstraintY',[]);
        PositionContinuityZ('Position Continuity (Z)','PositionContinuityConstraintZ',[]);
        VelocityContinuityX('Velocity Continuity (X)','VelocityContinuityConstraintX',[]);
        VelocityContinuityY('Velocity Continuity (Y)','VelocityContinuityConstraintY',[]);
        VelocityContinuityZ('Velocity Continuity (Z)','VelocityContinuityConstraintZ',[]);
    end

    properties
        name char = '';
        class char = '';
        constructorInput1
    end

    methods
        function obj = ConstraintEnum(name, class, constructorInput1)
            obj.name = name;
            obj.class = class;
            obj.constructorInput1 = constructorInput1;
        end
    end

    methods(Static)
        function listBoxStr = getListBoxStr()
            m = enumeration('ConstraintEnum');
            [~,I] = sort({m.name});
            listBoxStr = {m(I).name};
        end

        function [ind, enum] = getIndForName(name)
            m = enumeration('ConstraintEnum');
            [~,I] = sort({m.name});
            m = m(I);
            ind = find(ismember({m.name},name),1,'first');
            enum = m(ind);
        end
    end
end


function computeAllModelChoice_HN(pathSet,pathModels,training,param,maxOrder,nBoot,imbalance,seed)
% -------------------------------------------------------------------------
% function computeAllModelChoice_HN(pathSet,pathModels,training,param,maxOrder,nBoot,imbalance,batchNum)
% -------------------------------------------------------------------------
% DESCRIPTION:
% This function computes feature set selection for a given feature set type
% and for all experiments with different degrees of freedom. See ref. [1,2]
% for more details.
% -------------------------------------------------------------------------
% REFERENCES:
% [1] Vallieres, M. et al. (2015). FDG-PET/CT radiomics models for the
%     early prediction of different tumour outcomes in head and neck cancer.
%     The Journal of Nuclear Medicine, aa(bb), xxx-yyy.
%     doi:
% [2] Vallieres, M. et al. (2015). A radiomics model from joint FDG-PET and
%     MRI texture features for the prediction of lung metastases in soft-tissue
%     sarcomas of the extremities. Physics in Medicine and Biology, 60(14),
%     5471-5496. doi:10.1088/0031-9155/60/14/5471
% -------------------------------------------------------------------------
% INPUTS:
% 1. pathSet: Full path to the Feature Set folder of the corresponding experiment.
%             --> Ex: '/myProject/WORKSPACE/COHORT-BASED-RESULTS/Experiment1/FSET'
% 2. pathModels: Full path to the Models folder of the corresponding experiment.
%                --> Ex: '/myProject/WORKSPACE/COHORT-BASED-RESULTS/Experiment1/MODELS'
% 3. training: Structure defining all parameters for the given experiment
%              to perform. See masterScript_HN.m for more details.
% 4. param: Cell of two strings, defining 1) The feature set type/name; and
%           2) the outcome to model
% 5. maxOrder: Integer specifying the maximal model order to construct.
%              --> Ex: 10
% 6. nBoot: Number of bootstrap samples to use.
%           --> Ex: 100
% 7. imbalance: String specifying the type of imbalance-adjustement strategy
%               employed. Either 'IABR' for imbalance-adjusted bootstrap
%               resampling (see ref.[1]), or 'IALR' for imbalance-adjusted
%               logistic regression (see ref.[2]).
%               --> Ex: 'IALR'
% 8. batchNum: (optional input). If present, integer that specifies the
%              batch number for parallelization purposes.
%              --> Ex: 6
% -------------------------------------------------------------------------
% OUTPUTS: Mutivariable models are saved in a folder named 'MODELS' in the
% corresponding folder of "pathExperiment"
% -------------------------------------------------------------------------
% AUTHOR(S): Martin Vallieres <mart.vallieres@gmail.com>
% -------------------------------------------------------------------------
% HISTORY:
% - Creation: March 2016
%--------------------------------------------------------------------------
% STATEMENT:
% This file is part of <https://github.com/mvallieres/radiomics/>,
% a package providing MATLAB programming tools for radiomics analysis.
% --> Copyright (C) 2015  Martin Vallieres
%
%    This package 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 package 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 package.  If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------

startpath = pwd;
warning off

cd(pathSet)
fSetName = param{1};
outcomeName = param{2};
outcome = training.(outcomeName).outcome;
fSet = load(['FSET_',fSetName,'_',outcomeName]); fSet = struct2cell(fSet); fSet = fSet{1};

tic
fprintf(['\n--> SELECTING FEATURES (MODEL ORDERS OF 1 to % u) FOR "',fSetName,'" FEATURE SET AND "',outcomeName,'" OUTCOME ... '],maxOrder)
[models] = featureSelection_HN(fSet.Data,outcome,maxOrder,nBoot,fSet.Info,imbalance,seed);
cd(pathModels), save(['MODELS_',fSetName,'_',outcomeName],'models')
fprintf('DONE!\n'), toc

cd(startpath)
end


function [ err_outline, err_no_outline ] = Run_OF_on_images(output_loc, database_root, varargin)

dataset_dirs = {};

if(any(strcmp(varargin, 'use_afw')))
    afw_loc = [database_root '/AFW/'];
    dataset_dirs = cat(1, dataset_dirs, afw_loc);
end
if(any(strcmp(varargin, 'use_lfpw')))
    lfpw_loc = [database_root 'lfpw/testset/'];
    dataset_dirs = cat(1, dataset_dirs, lfpw_loc);
end
if(any(strcmp(varargin, 'use_ibug')))
    ibug_loc = [database_root 'ibug/'];
    dataset_dirs = cat(1, dataset_dirs, ibug_loc);
end
if(any(strcmp(varargin, 'use_helen')))
    helen_loc = [database_root '/helen/testset/'];
    dataset_dirs = cat(1, dataset_dirs, helen_loc);
end

if(any(strcmp(varargin, 'verbose')))
    verbose = true;
else
    verbose = false;
end

if(isunix)
    executable = '"../../build/bin/FaceLandmarkImg"';
else
    executable = '"../../x64/Release/FaceLandmarkImg.exe"';
end

if(any(strcmp(varargin, 'model')))
    model = varargin{find(strcmp(varargin, 'model')) + 1};
else
    % the default model is the 68 point in the wild one
    model = '"model/main_wild.txt"';
end

if(any(strcmp(varargin, 'multi_view')))
    multi_view = varargin{find(strcmp(varargin, 'multi_view')) + 1};
else
    multi_view = 0;
end

command = sprintf('%s -mloc %s -multi_view %s -2Dfp ', executable, model, num2str(multi_view));

tic
for i=1:numel(dataset_dirs)

    command_c = sprintf('%s -fdir "%s" -bboxdir "%s" -out_dir "%s" -wild ',...
        command, dataset_dirs{i},  dataset_dirs{i}, output_loc);

    if(isunix)
        unix(command_c, '-echo');
    else
        dos(command_c);
    end

end
toc

%%

% Extract the error sizes
dirs = {[database_root '/AFW/'];
    [database_root '/ibug/'];
    [database_root '/helen/testset/'];
    [database_root 'lfpw/testset/'];};

landmark_dets = dir([output_loc '/*.csv']);

landmark_det_dir = [output_loc '/'];

num_imgs = size(landmark_dets,1);

labels = zeros(68,2,num_imgs);

shapes = zeros(68,2,num_imgs);

curr = 0;

% work out which columns in the csv file are relevant
tab = readtable([landmark_det_dir, landmark_dets(1).name]);
column_names = tab.Properties.VariableNames;
landmark_inds_x = cellfun(@(x) ~isempty(x) && x==1, strfind(column_names, 'x_'));
landmark_inds_y = cellfun(@(x) ~isempty(x) && x==1, strfind(column_names, 'y_'));

for i=1:numel(dirs)

    gt_labels = dir([dirs{i}, '*.pts']);

    for g=1:numel(gt_labels)
        curr = curr+1;

        gt_landmarks = dlmread([dirs{i}, gt_labels(g).name], ' ', 'A4..B71');
        [~, name, ~] = fileparts(gt_labels(g).name);
        % find the corresponding detection
        all_params  = dlmread([landmark_det_dir, name, '.csv'], ',', 1, 0);

        landmark_det = [all_params(landmark_inds_x); all_params(landmark_inds_y)]';

        labels(:,:,curr) = gt_landmarks;

        if(size(landmark_det,1) == 66)
            inds_66 = [[1:60],[62:64],[66:68]];
            shapes(inds_66,:,curr) = landmark_det;
        else
            shapes(:,:,curr) = landmark_det;
        end
    end

end

% Convert to correct format, so as to have same feature points in ground
% truth and detections
if(size(shapes,2) == 66 && size(labels,2) == 68)
    inds_66 = [[1:60],[62:64],[66:68]];

    labels = labels(inds_66,:,:);
    shapes = shapes(inds_66,:,:);
end

% Center the pixel, and convert to OCV format
labels = labels - 2.0;

err_outline = compute_error(labels, shapes);

labels_no_out = labels(18:end,:,:);
shapes_no_out = shapes(18:end,:,:);

err_no_outline = compute_error(labels_no_out, shapes_no_out);

%%

save([output_loc, 'res.mat'], 'labels', 'shapes', 'err_outline', 'err_no_outline');

end


classdef TestPutText
    %TestPutText

    methods (Static)
        function test_simple
            im = 255*ones(64,64,3,'uint8');
            out = cv.putText(im, 'foo', [5,30]);
            validateattributes(out, {class(im)}, {'size',size(im)});
        end

        function test_options
            im = zeros([128,128,3],'uint8');
            out = cv.putText(im, 'foo', [40,70], ...
                'FontFace','HersheyComplex', 'FontStyle','Italic',...
                'Color',[255 0 0], 'Thickness',2, 'LineType','AA');
            validateattributes(out, {class(im)}, {'size',size(im)});
        end

        function test_error_argnum
            try
                cv.putText();
                throw('UnitTest:Fail');
            catch e
                assert(strcmp(e.identifier,'mexopencv:error'));
            end
        end
    end

end


function launch = ma_createLaunch(name, launchEpoch, launchLat, launchLong, launchAlt, ...
                                        launchToF, burnoutLat, burnoutLong, burnoutAlt, ...
                                        lineColor, lineStyle, lineWidth, bodyId)

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % vars = [bool bool bool bool bool bool bool bool;
    %         lower lower lower lower lower lower lower lower;
    %         upper upper upper upper upper upper upper upper]
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    launch = struct();
    launch.name = name;
    launch.type = 'Launch';
    launch.bodyId = bodyId;
    launch.launchValue = [launchEpoch, launchLat, launchLong, launchAlt, launchToF, burnoutLat, burnoutLong, burnoutAlt];
    launch.lineColor = lineColor;
    launch.lineStyle = lineStyle;
    launch.lineWidth = lineWidth;
    launch.id = rand(1);
end


function [Xtrain, Ytrain, Xtest, Ytest, imageDim] = slaveLoadCIFAR(cifarFileDir, numSlaves, slaveIndex)

  % params
  samplesPerFile = 10000;
  numTrainFiles=5;
  numTestFiles=1;

  % compute numbers of samples
  trainSamplesPerSlave = samplesPerFile * numTrainFiles / numSlaves;
  trainIndex = 1:samplesPerFile*numTrainFiles;
  testSamplesPerSlave = samplesPerFile * numTestFiles / numSlaves;
  testIndex = 1:samplesPerFile*numTestFiles;

  % choose indices for this slave
  firstTrainSample = floor(trainSamplesPerSlave * (slaveIndex-1))+1;
  lastTrainSample = floor(trainSamplesPerSlave * (slaveIndex));
  myTrainIndices = trainIndex(firstTrainSample:lastTrainSample);

  firstTestSample = floor(testSamplesPerSlave * (slaveIndex-1))+1;
  lastTestSample = floor(testSamplesPerSlave * (slaveIndex));
  myTestIndices = testIndex(firstTestSample:lastTestSample);

  % load training data
  Xtrain = zeros(length(myTrainIndices), 3072);
  Ytrain = zeros(length(myTrainIndices), 1);
  for i=1:numTrainFiles
    firstFileSample = samplesPerFile*(i-1)+1;
    fileIndices = firstFileSample : samplesPerFile*i;
    myFileIndices = intersect(fileIndices, myTrainIndices);

    if (length(myFileIndices) > 0)
      fname = sprintf('%s/data_batch_%d.mat', cifarFileDir, i);
      f = load(fname);
      Xtrain(myFileIndices - firstTrainSample + 1, :) = f.data(myFileIndices - firstFileSample + 1, :);
      Ytrain(myFileIndices - firstTrainSample + 1) = double(f.labels(myFileIndices - firstFileSample + 1)) + 1;
    end
  end

  % load test data
  fname = sprintf('%s/test_batch.mat', cifarFileDir);
  f = load(fname);
  Xtest = double(f.data(myTestIndices, :));
  Ytest = double(f.labels(myTestIndices)) + 1;

  imageDim = [32 32 3];

  Xtrain=slaveRef(Xtrain);
  Ytrain=slaveRef(Ytrain);
  Xtest=slaveRef(Xtest);
  Ytest=slaveRef(Ytest);


% readSPE.m
function image = readSPE(dirPath, filename)
% readSPE.m  Read princeton instrument *.SPE image file
%
% image = readSPE(filename)
%       = readSPE(dirPath, filename)
%
% where: image - 3D array of image(s)
%     filename - path and filename (string)
%      dirPath - optional directory path (string)
%
% Image is returned as a 3D array, where each image is the first 2
% dimensions, and successive images are stored along the 3rd dimension.
%
% The image is stored as it is shown in WinVIEW; the first two dimensions
% are stored as [pixel,stripe]
%
% returns -1 if unsuccessful, though if any of the low level access
% functions error out, this method will just fail with their error
% descriptions. Only the uint16 pixel datatype feature has been tested, so
% be more cautious than usual if using other datatypes.
%
% There is far more information stored in the SPE header (4100 bytes).
% This simple method only pulls the information that is required for the
% author's data processing. For further documentation of the header byte
% structure, seek the sources I used:
%
%  Matt Clarke's Python Script Description:
%   http://www.scipy.org/Cookbook/Reading_SPE_files
%
%  Stuart B. Wilkins's Python Code:
%   https://pyspec.svn.sourceforge.net/svnroot/pyspec/trunk/pyspec/ccd/files.py
%
%  ImageJ's plugin to import SPE files, written in Java:
%   http://rsbweb.nih.gov/ij/
%

% Author: Carl Hall
% Date: June 2012

% Modification History
%  April 2012 - Original Code
%   June 2012 - Modified to maintain output array as same datatype as SPE
%               file

%% SPE Header byte Structure (not fully checked)
%
% Offset    Bytes    Type     Description
% 0x0000    2        int      Controller Version
% 0x0002    2        int      Logic Output
% 0x0004    2        int      AppHiCapLowNoise
% 0x0006    2        int      dxDim
% 0x0008    2        int      timingMode
% 0x000A    4        float    Exposure
% 0x000E    2        int      vxDim
% 0x0010    2        int      vyDim
% 0x0012    2        int      dyDim
% 0x0014    10       string   Date
% 0x0024    4        float    DetTemperature
% 0x0028    2        int      DectectorType
% 0x002A    2        int      xDim
% 0x002C    2        int      TriggerDiode
% 0x002E    4        float    DelayTime
% 0x0032    2        int      ShutterControl
% 0x0034    2        int      AbsorbLive
% 0x0036    2        int      AbsorbMode
% 0x0038    2        int      canDoVirtualChip
% 0x003A    2        int      thresholdMinLive
% 0x003C    4        float    threshholdMin
% 0x0040    2        int      thresholdMaxLive
% 0x0042    4        float    threshholdMax
% 0x006C    2        int      Data Type
% 0x00AC    7        string   Time
% 0x00BC    2        int      ADCOffset
% 0x00BE    2        int      ADCRate
% 0x00C0    2        int      ADCType
% 0x00C2    2        int      ADCRes
% 0x00C4    2        int      ADCBitAdj
% 0x00C6    2        int      Gain
% 0x00C8    80       string   Comments
% 0x0118    80       string   Comments
% 0x0168    80       string   Comments
% 0x01B8    80       string   Comments
% 0x0208    80       string   Comments
% 0x0258    2        int      GeometricOps
% 0x0290    2        int      ydim
% 0x05A6    2        uint32   zdim
% 0x05D0    2        int      NumROIExperiment
% 0x05D2    2        int      NumROI
% 0x05D4    60       int[]    allROI
%
% 0x1004    ...      datatype   Image Data

%% Start of Code

% parse optional input
if nargin>1
    filename = strcat(dirPath,filename);
else
    filename = dirPath;
end

% Open the file
fd = fopen(filename,'r');
if(fd < 0)
    error('Could not open file, bad filename')
end

% Get the image dimensions:
stripDim = getData(fd, '2A', 'uint16');     %first dim
pixelDim = getData(fd, '290', 'uint16');    %second dim
nDim = getData(fd, '5A6', 'uint32');        %third dim

% Get the pixel data type
dataType = getData(fd, '6C', 'uint16');

% Get the image
fseek(fd, hex2dec('1004'), 'bof');

image = zeros([pixelDim,stripDim,nDim]);
switch dataType
    case 0     % single precision float (4 bytes)
        image = single(image);      %maintain datatype in function output
        for i=1:nDim
            image(:,:,i) = fread(fd, [stripDim,pixelDim], 'float32')';
        end

    case 1    % long int (4 bytes)
        image = int32(image);
        for i=1:nDim
            image(:,:,i) = fread(fd, [stripDim,pixelDim], 'int32')';
        end

    case 2    % short int (2 bytes)
        image = int16(image);
        for i=1:nDim
            image(:,:,i) = fread(fd, [stripDim,pixelDim], 'int16')';
        end

    case 3    % short unsigned int (2 bytes)
        image = uint16(image);
        for i=1:nDim
            image(:,:,i) = fread(fd, [stripDim,pixelDim], 'uint16')';
        end

    otherwise
        image = -1;
end
end

%%
% getData() reads one piece of data at a specific location
%
function data = getData(fd, hexLoc, dataType)
% Inputs: fd - int    - file descriptor
%     hexLoc - string - location of data relative to beginning of file
%   dataType - string - type of data to be read
%
fseek(fd, hex2dec(hexLoc), 'bof');
data = fread(fd, 1, dataType);
end


function string=implode(pieces,delimiter)
% IMPLODE    Joins strings with delimiter in between.
%
% IMPLODE(PIECES,DELIMITER) returns a string containing all the
% strings in PIECES joined with the DELIMITER string in between.
%
% :Inputs:
%
%   **PIECES:**
%        the pieces of string to join (cell array), each cell is a piece
%
%   **DELIMITER:**
%        the delimiter string to put between the pieces (string)
%
% :Output:
%
%   **STRING:**
%        all the pieces joined with the delimiter in between (string)
%
% :Examples:
% ::
%
%    PIECES = {'ab','c','d','e fgh'}
%    DELIMITER = '->'
%    STRING = IMPLODE(PIECES,DELIMITER)
%    STRING = ab->c->d->e fgh
%
% :See also:
% EXPLODE, STRCAT
%
% ..
%   Created: Sara Silva (sara@itqb.unl.pt) - 2002.08.25
% ..

if isempty(pieces) % no pieces to join, return empty string
   string='';

else % no need for delimiters yet, so far there's only one piece
   string=pieces{1};
end

l=length(pieces);
p=1;
while p<l % more than one piece to join with the delimiter, the interesting case
   p=p+1;
   string=[string delimiter pieces{p}];
end


% Eric, please check this out.
%
%

function [signal, time, chanlabels, pnts, nchan, serror] = loadtxterp(fullname, transpose, timex, elabel)

signal=[]; time=[]; chanlabels=''; pnts=[]; nchan=[];
serror = 0; % no errors
delimiter  = '\t';

%if transpose == 0; % data matrix is point x elec  (normal, no transpose)
if elabel==1
        nheaderlines = 1;
else
        nheaderlines = 0;
end
%else   % data matrix is elec x points  (transposed. should be corrected)
%    nheaderlines = 0;  %changed from 0 to 3
%end

% try
%  if transpose==1
%         fid = fopen(fullname,'rt');
%         nLines = 0;
%         while (fgets(fid) ~= -1)
%             nLines = nLines+1;
%         end
%         fclose(fid);
%         fid = fopen(fullname,'rt');
%         [A, count]=fscanf(fid, '%s');
%         fclose(fid);
%
%         if timex==1
%         columns_of_header=count/nLines; %counts the number of channels +1 (time header)
%         num_of_col=columns_of_header-1; %stores number of columns (time points)
%         signal_trans=signal(:,2:end);
%         signal=signal_trans;
%         time= dlmread(fullname, '', [0 1 0 num_of_col]);
%         else
%             signal=dlmread(fullname, '', [0 1 nLines num_of_col]);
%             time=[];
%         end
%  end

if nheaderlines==1
        values     = importdata(fullname);
        signal     = values.data;

        if transpose==1
                signal=signal';
                if timex==1
                        time=signal(:,1);
                        signal=signal(:,2:end);
                else
                        time=[];
                end
        else
                if timex==1
                        time = signal(:,1);
                        signal = signal(:,2:end);
                else
                        time = [];
                end
        end
else
        values=importdata(fullname);
        signal=values;
        if transpose==1
                signal=signal';
                if timex==1
                        time=signal(:,1);
                        signal=signal(:,2:end);
                else
                        time=[];
                end
        else
                signal = dlmread(fullname);

                if timex==1
                        time=signal(:,1);
                        signal=signal(:,2:end);
                else
                        time=[];
                end
                if transpose==1
                        signal=signal';
                end
        end
end

%  if nheaderlines==1
%      values     = importdata(fullname);
%      signal     = values.data;
%
%
%      if timex==1
%          time = signal(:,1);
%          signal = signal(:,2:end);
%      else
%          time = [];
%      end
%
%
%      if transpose==1
%          signal = signal'; % corrected
%      end
%  else
%      signal = dlmread(fullname);
%
%      if timex==1
%          time=signal(:,1);
%          signal=signal(:,2:end);
%      else
%          time=[];
%      end
%
%      if transpose==1
%          signal=signal';
%      end
%
%  end

pnts  = size(signal,1);
nchan = size(signal,2);

%       try
if elabel==1
        chanlabels = values.textdata;
        if size(chanlabels,1)==1 && size(chanlabels,2)==1
                %                         try
                chanlabels=regexp(chanlabels,'.*?\s+', 'match');
                chanlabels = [chanlabels{:}];
                chanlabels=strtrim(chanlabels);
                %                         catch
                %                               fprintf('Oops...Please check ERP.chanlocs.labels. Is it fine?');
                %                         end
        end
        if timex==1
                chanlabels = chanlabels(~ismember_bc2(chanlabels,{'time'}));
        end
else
        chanlabels = '';
end

%       catch
%             chanlabels = '';
%       end

if isempty(char(chanlabels))
        chanlabels = cell(1);
        for e=1:nchan
                chanlabels{e} = ['Ch' num2str(e)];
        end
end

% catch
%       serror = 1; % error found
% end


function DCM = spm_dcm_csd_data(DCM)
% gets cross-spectral density data-features using a VAR model
% FORMAT DCM = spm_dcm_csd_data(DCM)
% DCM    -  DCM structure
% requires
%
%    DCM.xY.Dfile        - name of data file
%    DCM.M.U             - channel subspace
%    DCM.options.trials  - trial to evaluate
%    DCM.options.Tdcm    - time limits
%    DCM.options.Fdcm    - frequency limits
%    DCM.options.D       - Down-sampling
%
% sets
%
%    DCM.xY.pst     - Peristimulus Time [ms] sampled
%    DCM.xY.dt      - sampling in seconds [s] (down-sampled)
%    DCM.xY.U       - channel subspace
%    DCM.xY.y       - cross spectral density over sources
%    DCM.xY.csd     - cross spectral density over sources
%    DCM.xY.It      - Indices of time bins
%    DCM.xY.Ic      - Indices of good channels
%    DCM.xY.Hz      - Frequency bins
%    DCM.xY.code    - trial codes evaluated
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_dcm_csd_data.m 6481 2015-06-16 17:01:47Z karl $

% Set defaults and Get D filename
%-------------------------------------------------------------------------
try
    Dfile = DCM.xY.Dfile;
catch
    errordlg('Please specify data and trials');
    error('')
end

% ensure spatial modes have been computed (see spm_dcm_csd)
%-------------------------------------------------------------------------
try
    DCM.M.U;
catch
    Nm      = DCM.options.Nmodes;
    DCM.M.U = spm_dcm_eeg_channelmodes(DCM.M.dipfit,Nm);
end

% load D
%--------------------------------------------------------------------------
try
    D = spm_eeg_load(Dfile);
catch
    try
        [p,f]        = fileparts(Dfile);
        D            = spm_eeg_load(f);
        DCM.xY.Dfile = fullfile(pwd,f);
    catch
        try
            [f,p]        = uigetfile('*.mat','please select data file');
            name         = fullfile(p,f);
            D            = spm_eeg_load(name);
            DCM.xY.Dfile = fullfile(name);
        catch
            warndlg([Dfile ' could not be found'])
            return
        end
    end
end

% indices of EEG channel (excluding bad channels)
%--------------------------------------------------------------------------
if ~isfield(DCM.xY, 'modality')
    [mod, list] = modality(D, 0, 1);

    if isequal(mod, 'Multimodal')
        qstr = 'Only one modality can be modelled at a time. Please select.';
        if numel(list) < 4

            % Nice looking dialog
            %--------------------------------------------------------------
            options = [];
            options.Default = list{1};
            options.Interpreter = 'none';
            DCM.xY.modality = questdlg(qstr, 'Select modality', list{:}, options);
        else

            % accomodate more buttons
            %--------------------------------------------------------------
            ind = menu(qstr, list);
            DCM.xY.modality = list{ind};
        end
    else
        DCM.xY.modality = mod;
    end
end

if ~isfield(DCM.xY, 'Ic')
    DCM.xY.Ic  = D.indchantype(DCM.xY.modality,'GOOD');
end

Ic        = DCM.xY.Ic;
Nm        = size(DCM.M.U,2);
DCM.xY.Ic = Ic;

% options
%--------------------------------------------------------------------------
try
    DT    = DCM.options.D;
catch
    DT    = 1;
end
try
    trial = DCM.options.trials;
catch
    trial = 1:D.nconditions;
end

% check data are not oversampled (< 4ms)
%--------------------------------------------------------------------------
if DT/D.fsample < 0.004
    DT            = ceil(0.004*D.fsample);
    DCM.options.D = DT;
end

% get peristimulus times
%--------------------------------------------------------------------------
try

    % time window and bins for modelling
    %----------------------------------------------------------------------
    DCM.xY.Time = time(D, [], 'ms');
    T1          = DCM.options.Tdcm(1);
    T2          = DCM.options.Tdcm(2);
    [i, T1]     = min(abs(DCM.xY.Time - T1));
    [i, T2]     = min(abs(DCM.xY.Time - T2));

    % Time [ms] of down-sampled data
    %----------------------------------------------------------------------
    It          = [T1:DT:T2]';               % indices - bins
    DCM.xY.pst  = DCM.xY.Time(It);           % PST
    DCM.xY.It   = It;                        % Indices of time bins
    DCM.xY.dt   = DT/D.fsample;              % sampling in seconds
    Nb          = length(It);                % number of bins

catch
    errordlg('Please specify time window');
    error('')
end

% get frequency range
%--------------------------------------------------------------------------
try
    Hz1     = DCM.options.Fdcm(1);          % lower frequency
    Hz2     = DCM.options.Fdcm(2);          % upper frequency
catch
    pst     = DCM.xY.pst(end) - DCM.xY.pst(1);
    Hz1     = max(ceil(2*1000/pst),4);
    if Hz1 < 8;
        Hz2 = 48;
    else
        Hz2 = 128;
    end
end

% Frequencies
%--------------------------------------------------------------------------
DCM.xY.Hz  = fix(Hz1:Hz2);             % Frequencies
Nf         = length(DCM.xY.Hz);        % number of frequencies
Ne         = length(trial);            % number of trial types

% Cross spectral density for each trial type
%==========================================================================
condlabels = D.condlist;               % condition or trial type labels
DCM.xY.csd = cell(1,Ne);               % CSD for each condition

w     = min(fix(2/DCM.xY.dt),Nb);      % window length (bins)
m     = 1;                             % retain principal mode
for i = 1:Ne;

    % trial indices
    %----------------------------------------------------------------------
    c = D.indtrial(condlabels(trial(i)), 'GOOD');
    fprintf('\nevaluating CSD for condition %i\n',i)

    % use only the first 512 trial
    %----------------------------------------------------------------------
    try c = c(1:512); end
    Nt    = length(c);

    % Get data
    %----------------------------------------------------------------------
    Nw    = max(8*(fix(Nb/w) - 1),1);
    K     = zeros(Nf*Nm*Nm,Nw);
    for k = 1:Nw
        P     = zeros(Nf,Nm,Nm);
        for j = 1:Nt
            Iw  = It((1:w) + fix((k - 1)*w/8));
            Y   = full(double(D(Ic,Iw,c(j))'*DCM.M.U));
            mar = spm_mar(Y,8);
            mar = spm_mar_spectra(mar,DCM.xY.Hz,1/DCM.xY.dt);
            P   = P + mar.P;
        end

        % store
        %------------------------------------------------------------------
        K(:,k) = spm_vec(P/Nt);
    end

    % retain principal eigenmode
    %----------------------------------------------------------------------
    [u s v]       = spm_svd(K,1);
    P             = u(:,m)*s(m,m)*mean(v(:,m));
    DCM.xY.csd{i} = spm_unvec(P,mar.P);

end

% place cross-spectral density in xY.y
%==========================================================================
DCM.xY.y    = DCM.xY.csd;
DCM.xY.U    = DCM.M.U;
DCM.xY.code = condlabels(trial);


function [nx, cx, done, rollback, evnts, cb_data, results] = cpf_nose_event_cb(...
        k, nx, cx, px, done, rollback, evnts, cb_data, cb_args, results)
%CPF_NOSE_EVENT_CB  Callback to handle NOSE events
%   [NX, CX, DONE, ROLLBACK, EVNTS, CB_DATA, RESULTS] =
%       CPF_NOSE_EVENT_CB(K, NX, CX, PX, DONE, ROLLBACK, EVNTS, ...
%                               CB_DATA, CB_ARGS, RESULTS)
%
%   Callback to handle NOSE events, triggered by event function
%   CPF_NOSE_EVENT to indicate the nose point of the continuation curve.
%
%   This function sets the msg field of the event when the nose point has
%   been found, raises the DONE.flag and sets the DONE.msg.
%
%   See CPF_DEFAULT_CALLBACK for details of the input and output arguments.

%   MATPOWER
%   Copyright (c) 2016, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%   and Shrirang Abhyankar, Argonne National Laboratory
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

%% skip if initialize, finalize or done
if k <= 0 || done.flag
    return;
end

%% initialize return value
stop_at = cb_data.mpopt.cpf.stop_at;

%% handle event
if ~rollback || nx.step == 0
    for i = 1:length(evnts)
        if strcmp(evnts(i).name, 'NOSE') && evnts(i).zero
            if nx.step == 0
                evnts(i).msg = ...
                    sprintf('Nose point eliminated by limit induced bifurcation at %d continuation steps, lambda = %.4g.', k, nx.lam);
            else
                evnts(i).msg = ...
                    sprintf('Reached steady state loading limit in %d continuation steps, lambda = %.4g.', k, nx.lam);
            end

            %% the following conditional is only necessary if we also allow
            %% finding the location of the nose-point without terminating
            if ischar(stop_at) && strcmp(stop_at, 'NOSE');
                done.flag = 1;
                done.msg = evnts(i).msg;
            end
            break;
        end
    end
end


function lvmClassVisualise(call)

% LVMCLASSVISUALISE Callback function for visualising data.
% FORMAT
% DESC contains the callback functions for visualizing points from the
% latent space in the higher dimension space.
% ARG call : either 'click', 'move', 'toggleDynamics',
% 'dynamicsSliderChange'
%
% COPYRIGHT : Neil D. Lawrence, 2003, 2009
%
% SEEALSO : lvmResultsDynamic

% MLTOOLS

global visualiseInfo

switch call
 case 'click'
  [x, y]  = localCheckPointPosition(visualiseInfo);
  if ~isempty(x)
    visualiseInfo.latentPos(visualiseInfo.dim1) = x;
    visualiseInfo.latentPos(visualiseInfo.dim2) = y;
  end
  visualiseInfo.clicked = ~visualiseInfo.clicked;
  if isfield(visualiseInfo.model, 'dynamics') & ~isempty(visualiseInfo.model.dynamics)
    if visualiseInfo.runDynamics
      visualiseInfo.dynamicsRunning = 1;
      fhandle = str2func([visualiseInfo.model.type 'DynamicsRun']);
      feval(fhandle);
      visualiseInfo.dynamicsRunning = 0;
    end
  else
    visualiseInfo.dynamicsRunning = 0;
  end
 case 'move'
  if visualiseInfo.clicked & ~visualiseInfo.runDynamics
    [x, y]  = localCheckPointPosition(visualiseInfo);
    if ~isempty(x)
      % This should be changed to a model specific visualisation.
      visualiseInfo.latentPos(visualiseInfo.dim1) = x;
      visualiseInfo.latentPos(visualiseInfo.dim2) = y;
      set(visualiseInfo.latentHandle, 'xdata', x, 'ydata', y);
      fhandle = str2func([visualiseInfo.model.type 'PosteriorMeanVar']);
      [mu, varsigma] = fhandle(visualiseInfo.model, visualiseInfo.latentPos);
      if isfield(visualiseInfo.model, 'noise')
        Y = noiseOut(visualiseInfo.model.noise, mu, varsigma);
      else
        Y = mu;
      end
      visualiseInfo.visualiseModify(visualiseInfo.visHandle, ...
                                    Y, visualiseInfo.varargin{:});
    end
  end
 case 'toggleDynamics'
  visualiseInfo.runDynamics = ~visualiseInfo.runDynamics;
  set(visualiseInfo.dynamicsRadio, 'value', visualiseInfo.runDynamics);

 case 'dynamicsSliderChange'
  X = modelOut(visualiseInfo.model.dynamics, get(visualiseInfo.dynamicsSlider, 'value'));
  x = X(1);
  y = X(2);
  visualiseInfo.latentPos(visualiseInfo.dim1) = x;
  visualiseInfo.latentPos(visualiseInfo.dim2) = y;
  set(visualiseInfo.latentHandle, 'xdata', x, 'ydata', y);
  fhandle = str2func([visualiseInfo.model.type 'PosteriorMeanVar']);
  [mu, varsigma] = fhandle(visualiseInfo.model, visualiseInfo.latentPos);
  if isfield(visualiseInfo.model, 'noise')
    Y = noiseOut(visualiseInfo.model.noise, mu, varsigma);
  else
    Y = mu;
  end
  visualiseInfo.visualiseModify(visualiseInfo.visHandle, ...
                                Y, visualiseInfo.varargin{:});

 case 'latentSliderChange'
  counter = 0;
  for i = size(visualiseInfo.latentPos, 2):-1:1
    % Go through setting latent positions to slider positions.
    if i ~= visualiseInfo.dim1 && i ~= visualiseInfo.dim2
      counter = counter + 1;
      visualiseInfo.latentPos(i) = get(visualiseInfo.latentSlider(counter), 'value');
      set(visualiseInfo.sliderTextVal(counter), 'string', num2str(visualiseInfo.latentPos(i)));
    end
  end
  lvmSetPlot;
  fhandle = str2func([visualiseInfo.model.type 'PosteriorMeanVar']);
  [mu, varsigma] = fhandle(visualiseInfo.model, visualiseInfo.latentPos);
  if isfield(visualiseInfo.model, 'noise')
    Y = noiseOut(visualiseInfo.model.noise, mu, varsigma);
  else
    Y = mu;
  end
  visualiseInfo.visualiseModify(visualiseInfo.visHandle, ...
                                    Y, visualiseInfo.varargin{:});
  if verLessThan('matlab', 'R2014a')
    visualiseInfo.latentHandle = line(visualiseInfo.latentPos(visualiseInfo.dim1), ...
                                      visualiseInfo.latentPos(visualiseInfo.dim2), ...
                                      'markersize', 20, 'color', [0.5 0.5 0.5], ...
                                      'marker', '.', 'visible', 'on', ...
                                      'erasemode', 'xor');
  else
    visualiseInfo.latentHandle = line(visualiseInfo.latentPos(visualiseInfo.dim1), ...
                                      visualiseInfo.latentPos(visualiseInfo.dim2), ...
                                      'markersize', 20, 'color', [0.5 0.5 0.5], ...
                                      'marker', '.', 'visible', ...
                                      'on');
  end

 case 'updateLatentRepresentation'
  visualiseInfo.dim1 = get(visualiseInfo.xDimension, 'value');
  visualiseInfo.dim2 = get(visualiseInfo.yDimension, 'value');
  lvmSetPlot;
  if verLessThan('matlab', 'R2014a')
    visualiseInfo.latentHandle = line(visualiseInfo.latentPos(visualiseInfo.dim1), ...
                                      visualiseInfo.latentPos(visualiseInfo.dim2), ...
                                      'markersize', 20, 'color', [0.5 0.5 0.5], ...
                                      'marker', '.', 'visible', 'on', ...
                                      'erasemode', 'xor');
  else
    visualiseInfo.latentHandle = line(visualiseInfo.latentPos(visualiseInfo.dim1), ...
                                      visualiseInfo.latentPos(visualiseInfo.dim2), ...
                                      'markersize', 20, 'color', [0.5 0.5 0.5], ...
                                      'marker', '.', 'visible', 'on');
  end

end

function point = localGetNormCursorPoint(figHandle)

point = get(figHandle, 'currentPoint');
figPos = get(figHandle, 'Position');
% Normalise the point of the curstor
point(1) = point(1)/figPos(3);
point(2) = point(2)/figPos(4);

function [x, y] = localGetNormAxesPoint(point, axesHandle)

position = get(axesHandle, 'Position');
x = (point(1) - position(1))/position(3);
y = (point(2) - position(2))/position(4);
lim = get(axesHandle, 'XLim');
x = x*(lim(2) - lim(1));
x = x + lim(1);
lim = get(axesHandle, 'YLim');
y = y*(lim(2) - lim(1));
y = y + lim(1);

function [x, y] = localCheckPointPosition(visualiseInfo)

% Get the point of the cursor
point = localGetNormCursorPoint(gcf);

% get the position of the axes
position = get(visualiseInfo.plotAxes, 'Position');

% Check if the pointer is in the axes
if point(1) > position(1) ...
      & point(1) < position(1) + position(3) ...
      & point(2) > position(2) ...
      & point(2) < position(2) + position(4);

  % Rescale the point according to the axes
  [x y] = localGetNormAxesPoint(point, visualiseInfo.plotAxes);

  % Find the nearest point
else
  % Return nothing
  x = [];
  y = [];
end


classdef EvoXBenchProblem < PROBLEM
%EvoXBenchProblem - The base problems of Multiobjective Neural Architecture Search.
%
%   EvoXBenchProblem is a subclass of PROBLEM. In EvoXBench, offspring
%   generated by algorithms are always evaluated on the training set.When
%   saving the results, it is necessary to re-evaluate on the test set,
%   which can also obtain accurate objective values.
%   Before running the EvoXBench test suite, you need to install evoxbench,
%   the installation tutorial address is: https://github.com/EMI-Group/evoxbench.git
%
% EvoXBenchProblem properties:
%   conn            <class>     the TCP/IP object
%   true_eval       <scalar>    true is validation pthase or test phase, false is training phase
%
% EvoXBenchProblem methods:
%   delete          <public>    release resources in Python
%   InitRemoteObj   <public>    initializes the TCP/IP object
%   Setting         <public>    default settings of the problem
%   CalDec          <public>    repair invalid solutions
%   CalObj          <public>    calculate the objective values of solutions
%   Sample          <public>    sample the network architectures
%   GetOptimum      <public>    generate the optimal objective values of the problem
%   GetPF          	<public>    generate the image of the Pareto front
%   CalMetric       <public>    calculate the metric value of a population
%   DrawObj         <public>    display solutions in the objective space
%   SetValid        <public>    set to validation phase
%   SetTest         <public>    set to test phase
%
%   Example:
%
%       platemo()
%
%   displays the GUI of PlatEMO.When users need to save the population on
%   EvoXBench, the objective value of the population needs to be
%   recalculated on the test set. Since the saved results are evaluated on
%   the training set, the decision variables are accurate, but objective
%   values are less accurate.
%
%       pro = @C10MOP1;
%       problem = pro();
%       [decs, objs, cons] = platemo('algorithm',@NSGAII,'problem',pro,'N',100,'maxFE',10000)
%       population = SOLUTION(decs, objs, cons);
%       igd = problem.CalMetric('IGD', population);
%   runs NSGAII with a population size of 100 on C10MOP1 for 10000
%   evaluations and calculate the IGD value. If the users want to save the
%   population, repair invalid solutions and recalculate the objective
%   value.

%------------------------------- Reference --------------------------------
% Z. Lu, R. Cheng, Y. Jin, K. C. Tan, and K. Deb, Neural architecture
% search as multiobjective optimization benchmarks: Problem formulation and
% performance assessment, IEEE Transactions on Evolutionary Computation,
% 2023.
%--------------------------------------------------------------------------

    properties (Access = private)
        conn;
        true_eval;
    end
    methods
        %% Release resources in Python
        function delete(obj)
            if ~isempty(obj.conn)
                request.operation = 'delete';
                try
                    obj.conn.writeline(jsonencode(request));
                    obj.conn.flush('output');
                catch
                end
            end
        end
        %% Initializes the TCP/IP object
        function InitRemoteObj(obj, config)
            try
                request.config = config;
                request.operation = 'create';
                obj.conn = tcpclient('127.0.0.1', 9876, 'timeout', 30);
                obj.conn.writeline(jsonencode(request));
                obj.conn.flush('output');
                response = jsondecode(obj.conn.readline());
                assert(strcmp(response.status,'ok'),'Failed to connect to the remote server.');
            catch err
                error('EvoXBench:createFailed','%s\nPlease visit https://github.com/EMI-Group/evoxbench for details.',err.message);
            end
        end
        %% Default settings of the problem
        function Setting(obj, config)
            obj.InitRemoteObj(config);
            query.operation = 'settings';
            obj.conn.writeline(jsonencode(query));
            obj.conn.flush('output');
            response = jsondecode(obj.conn.readline());
            if strcmp(response.status, 'ok')
                basicinfo = response.result;
            else
                exception = MException('TestFunction:queryFailed','Failed to query');
                throw(exception);
            end
            obj.M = basicinfo.n_obj;
            if isempty(obj.D); obj.D = basicinfo.n_var; end
            obj.lower    = reshape(basicinfo.lb, 1, []);
            obj.upper    = reshape(basicinfo.ub, 1, []);
            obj.encoding = ones(1,obj.D);
            obj.true_eval = false;
        end
        %% Repair invalid solutions
        function PopDec = CalDec(obj, PopDec)
            % clip and round, because evoxbench uses discrete encoding
            PopDec = min(PopDec, repmat(obj.upper, size(PopDec,1), 1));
            PopDec = max(PopDec, repmat(obj.lower, size(PopDec,1), 1));
            PopDec = round(PopDec);

            % deduplicate
            TotalLen = size(PopDec, 1);
            [~, ia] = unique(PopDec, 'rows');
            NonDupLen = size(ia, 1);
            DupLen = TotalLen - NonDupLen;
            DupIndex = true(TotalLen, 1);
            DupIndex(ia) = false;
            PopDec(DupIndex, :) = obj.Sample(DupLen);
        end
        %% calculate the objective values
        function PopObj = CalObj(obj, x)
            query.operation = 'query';
            query.encoding = x;
            query.true_eval = obj.true_eval;
            obj.conn.writeline(jsonencode(query));
            obj.conn.flush('output');
            response = jsondecode(obj.conn.readline());
            if strcmp(response.status, 'ok')
                PopObj = response.result;
            else
                exception = MException('EvoXBench:queryFailed','Failed to query');
                throw(exception);
            end
        end
        %% Sample the network architectures
        function R = Sample(obj, n_samples)
            query.operation = 'sample';
            query.n_samples = n_samples;
            obj.conn.writeline(jsonencode(query));
            obj.conn.flush('output');
            response = jsondecode(obj.conn.readline());
            if strcmp(response.status, 'ok')
                R = response.result;
            else
                exception = MException('EvoXBench:queryFailed','Failed to query');
                throw(exception);
            end
        end
        %% Generate points on the Pareto front
        function R = GetOptimum(obj, N)
            query.operation = 'pareto_front';
            query.n_samples = N;
            obj.conn.writeline(jsonencode(query));
            obj.conn.flush('output');
            response = jsondecode(obj.conn.readline());
            if strcmp(response.status, 'ok')
                R = response.result;
            else
                exception = MException('EvoXBench:queryFailed','Failed to query');
                throw(exception);
            end
        end
        %% Generate the image of Pareto front
        function R = GetPF(obj)
            % -1 will get all points
            R = obj.GetOptimum(-1);
        end
        function score = CalMetric(obj,metName,Population)
        %CalMetric - calculate the metric value of a population
        %
        %   value = obj.CalMetric(Met,P) returns the metric value of a
        %   population P, where Met is a string denoting the name of a
        %   metric function. If Met is 'HV', 'IGD' or 'normalized_hv', the
        %   metric value is calculate through the Python side. Before the
        %   metric value is calculated, the test phase is set and the
        %   objective value is recalculated. Also, invalid solutions are
        %   removed.
        %
        %   Example:
        %       value = Problem.CalMetric('HV',Population);

            obj.true_eval = true;
            PopDec = obj.CalDec(Population.decs());
            PopObj = obj.CalObj(PopDec);
            PopCon = obj.CalCon(PopDec);
            invalidSolutions = any(PopObj == inf, 2);
            validSolutions = ~invalidSolutions;
            PopDec = PopDec(validSolutions, :);
            indicator = lower(metName);
            if strcmp(indicator, 'hv') || strcmp(indicator, 'igd') || strcmp(indicator, 'normalized_hv')
                query.operation = 'calc_perf_indicator';
                query.inputs = PopDec;
                query.indicator = indicator;
                obj.conn.writeline(jsonencode(query));
                obj.conn.flush('output');
                response = jsondecode(obj.conn.readline());
                if strcmp(response.status, 'ok')
                    score = response.result;
                else
                    exception = MException('EvoXBench:queryFailed','Failed to query');
                    throw(exception);
                end
            else
                Population = SOLUTION(PopDec,PopObj,PopCon);
                score = feval(metName,Population,obj.optimum);
            end
        end
        function DrawObj(obj,Population)
            %DrawObj - Display a population in the objective space.
            %
            %   To display the results of test phase in real time in the
            %   GUI, set to validation phase. Then recalculate the
            %   objective value and create a new SOLUTION object.
            %
            %	This function is usually called by the GUI.
            obj.true_eval = true;
            PopDec = obj.CalDec(Population.decs());
            PopObj = obj.CalObj(PopDec);
            PopCon = obj.CalCon(PopDec);
            Population = SOLUTION(PopDec,PopObj,PopCon);

            ax = Draw(Population.objs,{'\it f\rm_1','\it f\rm_2','\it f\rm_3'});
            if ~isempty(obj.PF)
                if ~iscell(obj.PF)
                    if obj.M == 2
                        plot(ax,obj.PF(:,1),obj.PF(:,2),'-k','LineWidth',1);
                    elseif obj.M == 3
                        plot3(ax,obj.PF(:,1),obj.PF(:,2),obj.PF(:,3),'-k','LineWidth',1);
                    end
                else
                    if obj.M == 2
                        surf(ax,obj.PF{1},obj.PF{2},obj.PF{3},'EdgeColor','none','FaceColor',[.85 .85 .85]);
                    elseif obj.M == 3
                        surf(ax,obj.PF{1},obj.PF{2},obj.PF{3},'EdgeColor',[.8 .8 .8],'FaceColor','none');
                    end
                    set(ax,'Children',ax.Children(flip(1:end)));
                end
            elseif size(obj.optimum,1) > 1 && obj.M < 4
                if obj.M == 2
                    plot(ax,obj.optimum(:,1),obj.optimum(:,2),'.k');
                elseif obj.M == 3
                    plot3(ax,obj.optimum(:,1),obj.optimum(:,2),obj.optimum(:,3),'.k');
                end
            end
            obj.true_eval = false;
        end
        %% Set to validation phase
        function SetValid(obj)
            obj.true_eval = true;
        end
        %% Set to test phase
        function SetTest(obj)
            obj.true_eval = true;
        end
    end
end


function dig = fif_read_headpoints(fid, tree)
% FIF_READ_HEADPOINTS: Read digitized head points from a FIF file.

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@

% FIFF Constants
global FIFF;
if isempty(FIFF)
   FIFF = fiff_define_constants();
end

% Get DIG points
isotrak = fiff_dir_tree_find(tree, FIFF.FIFFB_ISOTRAK);
dig=struct('kind',{},'ident',{},'r',{},'coord_frame',{});
if length(isotrak) == 1
    p = 0;
    for k = 1:isotrak.nent
        kind = isotrak.dir(k).kind;
        pos  = isotrak.dir(k).pos;
        if kind == FIFF.FIFF_DIG_POINT
            p = p + 1;
            tag = fiff_read_tag(fid,pos);
            dig(p) = tag.data;
	    dig(p).coord_frame = FIFF.FIFFV_COORD_HEAD;
        end
    end
end


function HDR=openeep(HDR,arg2,arg3,arg4,arg5,arg6)
% OPENEEP opens EEProbe files (but does not read the data).
% However, it is recommended to use SOPEN instead of OPENEEP.
%
% see also: SLOAD, SOPEN, SREAD, SCLOSE, SEOF, STELL, SSEEK.

%	$Id: openeep.m 2205 2009-10-27 12:18:15Z schloegl $
%	Copyright (c) 2007 by Alois Schloegl <a.schloegl@ieee.org>
%    	This is part of the BIOSIG-toolbox http://biosig.sf.net/

% 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.

if strcmp(HDR.TYPE,'EEProbe-CNT'),

       	HDR.FILE.FID = fopen(HDR.FileName,'rb');
	H = openiff(HDR.FILE.FID);

	if isfield(H,'RIFF');
                HDR.RIFF      = H.RIFF;
                HDR.FILE.OPEN = 1;
                HDR.Label     = {};
                HDR.PhysDim   = {};
                HDR.SPR       = inf;
                HDR.NRec      = 1;
                HDR.FILE.POS  = 0;
                if ~isfield(HDR.RIFF,'CNT');
                	HDR.TYPE = 'unknown';
                elseif ~isfield(HDR.RIFF.CNT,'eeph') | ~isfield(HDR.RIFF.CNT,'LIST');
                	HDR.TYPE = 'unknown';
                else
			s = char(HDR.RIFF.CNT.eeph);
			field = '';
			while ~isempty(s)
				[line,s] = strtok(s,[10,13]);
				if strncmp(line,'[Sampling Rate]',15);
					field = 'SampleRate';
				elseif strncmp(line,'[Samples]',9);
					field = 'SPR';
				elseif strncmp(line,'[Channels]',10);
					field = 'NS';
				elseif strncmp(line,'[Basic Channel Data]',20);
					k = 0;
					while (k<HDR.NS),
						[line,s] = strtok(s,[10,13]);
						if ~strncmp(line,';',1);
							k = k+1;
							[num,status,sa]=str2double(line);
							HDR.Label{k} = sa{1};
							HDR.PhysDim{k,1} = sa{4};
							HDR.Cal(k) = num(2)*num(3);
						end;
					end;
				elseif strncmp(line,'[History]',9);
					[t,s] = strtok(s,[10,13]);
					while ~strncmp(t,'EOH',3)
						[t,s] = strtok(s,[10,13]);
					end;
				elseif strncmp(line,';',1);
				elseif strncmp(line,'[',1);
					field = '';
				elseif ~isempty(field);
					[num,status,sa] = str2double(line);
					if ~status,
						HDR = setfield(HDR,field,num);
						field = '';
					end;
				end;
			end;

			% decode data block
			HDR.SPR = H.RIFF.CNT.LIST.raw3.ep(1);
			HDR.NRec = length(H.RIFF.CNT.LIST.raw3.ep)-2;

if 0, %try
	%%% ### FIXME ### %%%
	%%% decoding of data block
	%%% this is work in progress.
			HDR.EEP.epoch_length = H.RIFF.CNT.LIST.raw3.ep(1);
			HDR.EEP.epoch_start  = [H.RIFF.CNT.LIST.raw3.ep(2:end),length(H.RIFF.CNT.LIST.raw3.data)];
			n = [HDR.EEP.epoch_length,length(H.RIFF.CNT.LIST.raw3.chan)];
%dec2bin(double(HDR.RIFF.CNT.LIST.raw3.data(HDR.EEP.epoch_start(1:end-1)+1)),8)
			%n=n([2,1]);
			accu  = zeros(1,HDR.NS);
			for k = 1:HDR.NRec,
				ix1 = HDR.EEP.epoch_start(k)+1;
				bytes = double(H.RIFF.CNT.LIST.raw3.data(HDR.EEP.epoch_start(k)+1:HDR.EEP.epoch_start(k+1)));
				ix1 = 1;
			for ch= 1:HDR.NS,
				ix1 = ceil(ix1);
				byte1 = H.RIFF.CNT.LIST.raw3.data(HDR.EEP.epoch_start(k)+ix1);
				meth  = double(bitshift(byte1,-4));

				if any(meth==[1:3])
					nbits = bitand(bytes(1),15);
					nexcbits = bitshift(bytes(2),4);
					if ~nexcbits, nexcbits = 16; end;
					y = repmat(NaN,HDR.SPR,1);
					y(1) = bitshift(bitand(bytes(2),15)*256+bytes(3),4)+bitshift(bytes(4),-4);
					bitpos = 28;
					ix1 = ix1 + 3.5;
					for k1 = 2:HDR.SPR,
						%ix1 = bitpos/8;
						ix2 = ix1 + nbits/8;
						i1 = ceil(ix1);
						r1 = (ix1-i1+1)*8;
						i2 = ceil(ix2);
						r2 = (ix2-i2+1)*8;
%[r1,i1,r2,i2],
						a = bitand(bytes(i1),2^r1-1);
						a = bitshift(a,16) + bitshift(bytes(i1+1),8) + bytes(i1+2);
						a = bitshift(a,r2-16-r1);
						ix1 = ix2;
						if a>2^(nbits-1)
							a=a-2^nbits;
						elseif a==2^(nbits-1)
							ix2 = ix1 + nexcbits/8;
							i1 = ceil(ix1);
							r1 = (ix1-i1+1)*8;
							i2 = ceil(ix2);
							r2 = (ix2-i2+1)*8;
							a = bitand(bytes(i1),2^r1-1);
							a = bitshift(a,16) + bitshift(bytes(i1+1),8) + bytes(i1+2);
							a = bitshift(a,r2-16-r1);
							ix1 = ix2;
							if a>2^(nexcbits-1)
								a=a-2^nexcbits;
							end;
						end;
						y(k1)=a;
					end;
					%fprintf(HDR.FILE.stderr,'Warning SOPEN(EEProbe): decompression method %i not implented\n',meth);
				elseif any(meth==[9:11])
					nbits = bitshift(bitand(bytes(1),15),2) + bitshift(bytes(2),-6);
					nexcbits = bitand(bytes(2),63);
					y = repmat(NaN,HDR.SPR,1);
					y(1) = bytes(3:6)*(256.^[3,2,1,0]');
					bitpos = 48;
					ix1 = ix1 + 6;
					for k1 = 2:HDR.SPR,
						%ix1 = bitpos/8;
						ix2 = ix1 + nbits/8;
						i1 = ceil(ix1);
						r1 = (ix1-i1+1)*8;
						i2 = ceil(ix2);
						r2 = (ix2-i2+1)*8;
%[r1,i1,r2,i2],
						a = bitand(bytes(i1),2^r1-1);
						a = bitshift(a,32) + bitshift(bytes(i1+1),24) + bitshift(bytes(i1+2),16) + bitshift(bytes(i1+3),8) + bytes(i1+4);
						a = bitshift(a,r2-32-r1);
						ix1 = ix2;
						if a>2^(nbits-1)
							a=a-2^nbits;
						elseif a==2^(nbits-1)
							ix2 = ix1 + nexcbits/8;
							i1 = ceil(ix1);
							r1 = (ix1-i1+1)*8;
							i2 = ceil(ix2);
							r2 = (ix2-i2+1)*8;
							a = bitand(bytes(i1),2^r1-1);
							a = bitshift(a,16) + bitshift(bytes(i1+1),8) + bytes(i1+2);
							a = bitshift(a,r2-16-r1);
							ix1 = ix2;
							if a>2^(nexcbits-1)
								a=a-2^nexcbits;
							end;
						end;
						y(k1)=a;
					end;
					fprintf(HDR.FILE.stderr,'Warning SOPEN(EEProbe): decompression method %i not implemented\n',meth);
					error('####');
				elseif meth==0,
					y = bytes(ix1+(1:2:HDR.SPR*2));
					y = y - 256*(y>127);
					y = 256*y + bytes(ix1+(2:2:HDR.SPR*2));
					ix1 = ix1 + 1 + 2 * HDR.SPR;
				elseif meth==8,
					y = bytes(ix1+(1:HDR.SPR*4));
					y(1:4:end) = y(1:4:end) - 256*(y(1:4:end)>127);
					y = reshape(y,[4,length(y)/4])'*(256.^[3;2;1;0]);
					ix1 = ix1 + 1 + 4 * HDR.SPR;
				else
					y = repmat(NaN,HDR.SPR,1);
					%fprintf(HDR.FILE.stderr,'ERROR SOPEN(EEProbe): decompression method %i not supported\n',double(meth));
					error(sprintf('EEProbe: decompression method %d not supported\n',double(meth)));
				end;

				if any(meth==[1,9]);
					y = reshape(y,[HDR.SPR,1]);
					y(1,:) = accu(ch)+y(1,:);
					y = cumsum(y,1);
					accu(ch) = y(end,:);
				elseif any(meth==[2,10]);
					y = reshape(y,[HDR.SPR,1]);
					y(2,:) = accu(ch)+y(1,:);
					y(2:end,:) = cumsum(y(2:end,:),1);
					accu(ch) = y(end,:);
				elseif any(meth==[3,11]);
					y = cumsum(reshape(y,[HDR.SPR,1]),2);
				elseif any(meth==[0,8]);
					%y = reshape(y,n([2,1]))';
					y = reshape(y,[HDR.SPR,1]);
				end;
				HDR.data(HDR.SPR*(k-1)+1:HDR.SPR*k,H.RIFF.CNT.LIST.raw3.chan(ch)+1) = y;
			end;
			end;
			HDR.Calib = sparse(2:HDR.NS+1,1:HDR.NS,HDR.Cal);
			HDR.TYPE = 'native';
else %catch
			HDR.Calib = sparse(2:HDR.NS+1,1:HDR.NS,1); % because SREAD uses READ_EEP_CNT.MEX
end;
                end
                HDR.SPR = HDR.SPR*HDR.NRec;
                HDR.NRec = 1;
        end
end;

	% read event file, if applicable
	fid = 0;
	if strcmp(HDR.TYPE,'EEProbe-TRG'),
	        fid = fopen(HDR.FileName,'rt');
        elseif strcmp(HDR.TYPE,'EEProbe-CNT')
	        fid = fopen(fullfile(HDR.FILE.Path,[HDR.FILE.Name,'.trg']),'rt');
	end;
	if fid>0,
                tmp = str2double(fgetl(fid));
                if ~isnan(tmp(1))
                	HDR.EVENT.SampleRate = 1/tmp(1);
	                N = 0;
	                while ~feof(fid),
	                        tmp = fscanf(fid, '%f %d %s', 3);
	                        if ~isempty(tmp)
	                                N = N + 1;
	                                HDR.EVENT.POS(N,1)  = round(tmp(1)*HDR.EVENT.SampleRate);
	                                HDR.EVENT.TYP(N,1)  = 0;
	                                %HDR.EVENT.DUR(N,1) = 0;
	                                %HDR.EVENT.CHN(N,1) = 0;

	                                HDR.EVENT.TeegType{N,1} = char(tmp(3:end));
	                                HDR.EVENT.TYP(N,1)  = str2double(HDR.EVENT.TeegType{N,1});		% numeric
	                        end
	                end;
	                HDR.EVENT.TYP(isnan(HDR.EVENT.TYP))=0;
	                HDR.TRIG = HDR.EVENT.POS(HDR.EVENT.TYP>0);
	%                HDR.EVENT.POS = HDR.EVENT.POS(HDR.EVENT.TYP>0);
	%                HDR.EVENT.TYP = HDR.EVENT.TYP(HDR.EVENT.TYP>0);
	%                HDR.EVENT = rmfield(HDR.EVENT,'TeegType');
		end;
                fclose(fid);
        end;

	if strcmp(HDR.TYPE,'EEProbe-AVR'),
	        % it appears to be a EEProbe file with an averaged ERP
        	try
        	        tmp = read_eep_avr(HDR.FileName);
        	catch
        	        fprintf(HDR.FILE.stderr,'ERROR SOPEN (EEProbe): Cannot open EEProbe-file, because read_eep_avr.mex not installed. \n');
        	        fprintf(HDR.FILE.stderr,'ERROR SOPEN (EEProbe): see http://www.smi.auc.dk/~roberto/eeprobe/\n');
        	        return;
	        end

        	% convert the header information to BIOSIG standards
	        HDR.FILE.FID = 1;               % ?
        	HDR.FILE.POS = 0;
	        HDR.NS = tmp.nchan;             % number of channels
        	HDR.SampleRate = tmp.rate;      % sampling rate
	        HDR.NRec  = 1;                   % it is an averaged ERP, therefore one record
        	HDR.SPR   = tmp.npnt;             % total number of samples in the file
	        HDR.Dur   = tmp.npnt/tmp.rate;    % total duration in seconds
        	HDR.Calib = [zeros(1,HDR.NS) ; eye(HDR.NS, HDR.NS)];  % is this correct?
	        HDR.Label = char(tmp.label);
	        HDR.PhysDim   = 'uV';
	        HDR.FLAG.UCAL = 1;
	        HDR.FILE.POS  = 0;
	        HDR.AS.endpos = HDR.SPR;
	        HDR.Label = tmp.label;
	        HDR.TriggerOffset = 0;

	        HDR.EEP.data = tmp.data';
	end;


function img = pgmread(filename)
% function img = pgmread(filename)
%   this is my version of pgmread for the pgm file created by XV.
%
%  this program also corrects for the shifts in the image from pm file.

fid = fopen(filename,'r');
fscanf(fid, 'P5\n');
cmt = '#';
while findstr(cmt, '#'),
  cmt = fgets(fid);
   if length(findstr(cmt, '#')) ~= 1,
      YX = sscanf(cmt, '%d %d');
      y = YX(1); x = YX(2);
   end
end

%fgets(fid);

%img = fscanf(fid,'%d',size);
%img = img';

img = fread(fid,[y,x],'uint8');
img = img';
fclose(fid);


% PENDING
%
%
%
%
%
%

function [ERP serror] = importerpss(filename, format, transpose)

serror = 0;
if nargin<2
      error('ERPLAB says: error, filename and pathname are needed as inputs.')
end

%%%taken from asc2erp.m%%%
fullname = filename;
fid = fopen(fullname);

%used to verify whether it is an ERPSS file
C = textscan(fid, '%s', 5);
fclose(fid);

G = [C{1:end}];

disp('hola')

%if strcmpi(G{5}, 'nchans') % then it is ERPSS

      % %       #
      % %       #	binno          1
      % %       #
      % %       bindesc="Cue LSF "
      % %       condesc="Cue LSF "
      % %       npoints      613
      % %       sampleperiod      1953
      % %       presampling     199219
      % %       sums        1181
      % %       procfuncs   "avg"
      % %       arejects    819
      % %

      %
      % Getting bin descriptors
      %
      fid = fopen(fullname);
      BD  = textscan(fid, '%s', 'delimiter','\n');
      fclose(fid);

      BDesc = regexpi(BD{:}, 'bindesc="(.*)"','tokens');
      BDesc = BDesc(~cellfun(@isempty, BDesc));
      BDesc = [BDesc{:}];
      BDesc = [BDesc{:}];
      % %       C   = regexprep(C{:}, '"(.*)"','"${strrep($1,'' '',''_'')}"');
      % %
      % %       [pathproc fnameproc ext] = fileparts(fullname);
      % %
      % %       fullfile(pathproc, [fnameproc '_procerplab' ext])
      % %
      % %       fid = fopen(fullfile(pathproc, [fnameproc '_procerplab' ext]), 'w');
      % %       fprintf(fid, '%s\n', C{:});
      % %       fclose(fid);
      % %
      % %       fid = fopen([ fnameproc '_procerplab' ext]);
      % %       C   = textscan(fid, '%s');
      % %       fclose(fid);

      fid = fopen(fullname);
      C   = textscan(fid, '%s');
      fclose(fid);

      D   = [C{1:end}];
      m   = length(D);
      count=1; x=0; a=0; b=0; c=0; d=0; e=0; f=0; j=1; k=0;

      %Explicit Format (header for bins and channels)
      if format==0  % explicit
            fprintf('\nPlease wait, loading ERPset from ERPSS ascii file (explicit format)...\n');
            i=1;

            while i<=m-5
                  %x = D{i};
                  a = D{i};
                  b = D{i+1};
                  d = str2num(D{i+3});
                  f = D{i+5};
                  err = 0;

                  if (a=='#' & b=='#' & d>=0 & d<=256 & f=='#' )
                        k = i+6;
                        j = 1;

                        while (D{k} ~= '#' & err==0)
                              E(j,1,count) = str2num(D{k});
                              j = j+1;
                              k = k+1;
                              if k==m
                                    err=1;
                              end
                        end
                        count = count+1; % bin counter
                        i = k-1;
                  else
                        i = i+1;
                  end
            end

            %to get very last data point
            E(j,1, count-1) = str2num(D{m});
            %fclose(fid);

            %finding channel numbers and bin numbers
            ERP       = buildERPstruct;
            numofchan = str2num(D{6});
            numofbins = ((count-1)/numofchan)-1;

            for binnumber=1:numofbins
                  k = (binnumber*numofchan) + 1;
                  for n=1:numofchan
                        ERP.bindata(n,:,binnumber) = E(:,1,k)';
                        k = k+1;
                  end
            end
            %Need to fill ERP.bindata, numofchans, numofbins
      elseif format ==1     % implicit
            fprintf('\nPlease wait, loading ERPset from ERPSS ascii file (implicit format, ');

            %rows are channels, columns are samples
            if transpose ==0
                  fprintf('untransposed)...\n')
                  i=1;

                  while i<=m-5
                        %x = D{i};
                        a = D{i};
                        b = D{i+2};
                        d = str2num(D{i+3});
                        err = 0;

                        if (strcmp(a,'procfuncs') & strcmp(b,'arejects') & d>=0) % JLC: "d" might not necessarily be zero
                              k=i+4;
                              j=1;

                              while (D{k} ~= '#' & err==0)
                                    E(j,1,count) = str2num(D{k});
                                    j = j+1;
                                    k = k+1;
                                    if k==m
                                          err=1;
                                    end
                              end
                              count = count+1;
                              i = k-1;
                        else
                              i = i+1;
                        end
                  end
                  %to get very last data point
                  E(j,1, count-1) = str2num(D{m});
                  %fclose(fid);

                  %finding channel numbers and bin numbers
                  ERP = buildERPstruct;
                  numofchan  = str2num(D{6});
                  numofbins  = count-1;
                  sigperchan = j/numofchan; %number of signals per channel
                  k=1;
                  m=1;

                  for binnumber = 1:numofbins
                        for n = 1:numofchan
                              for j=1:sigperchan
                                    x = E(m,1,k);
                                    ERP.bindata(n,j,binnumber) = x;
                                    m = m+1;
                              end
                        end
                        k = k+1;
                        m=1;
                  end
                  %columns are channels, rows are samples
            else
                  fprintf('transposed)...\n')
                  i=1;

                  while i<=m-5
                        %x = D{i};
                        a = D{i};
                        b = D{i+2};
                        d = str2num(D{i+3});
                        err =0;

                        if (strcmp(a,'procfuncs') & strcmp(b,'arejects') & d>=0) %JLC: "d" might not necessarily be zero
                              k = i+4;
                              j=1;

                              while (D{k} ~= '#' & err==0)
                                    E(j,1,count) = str2num(D{k});
                                    j = j+1;
                                    k = k+1;
                                    if k==m
                                          err=1;
                                    end
                              end
                              count = count+1;
                              i = k-1;
                        else
                              i = i+1;
                        end
                  end
                  %to get very last data point
                  E(j,1, count-1) = str2num(D{m});
                  %fclose(fid);

                  %finding channel numbers and bin numbers
                  ERP = buildERPstruct;
                  numofchan  = str2num(D{6});
                  numofbins  = (count-1);
                  sigperchan = j/numofchan; %number of signals per channel
                  k=1;

                  for binnumber=1:numofbins
                        for n=1:numofchan
                              m=n;
                              for j=1:sigperchan
                                    x = E(m,1,k);
                                    ERP.bindata(n,j,binnumber) = x;
                                    m = m+numofchan;
                              end
                        end
                        k = k+1;
                        m=1;
                  end
            end
      end

      ERP.nbin     = numofbins; %number of bins
      ERP.nchan    = numofchan; %number of channels
      ERP.binerror = [];
      ERP.isfilt   = 0;
      [a numberofpoints] = size(ERP.bindata(1,:,1));
      ERP.pnts  = numberofpoints;

      % ################# NO contrast against OPTIONS #################### JLC
      %ERP.xmin  = xlim(1)/1000;
      %ERP.xmax  = xlim(2)/1000;

      %error if fs and estimated fs are not within 10% of each other
      %sdistance = (xlim(2)-xlim(1))/numberofpoints;  %distance between points
      %est_fs=1/sdistance*1000;
      %srdiff = abs((fs-est_fs)/est_fs);
      %if srdiff>0 && srdiff>=0.1
      %        serror=3;
      %end
      %###########################  JLC

      %now if the srate from the erpss is offf another error
      %now take the value of ERP.srate= the one from ERPSS

      for i=1:500 %because the sample period will be located somewhere in between here
            if strcmp(D{i},'sampleperiod')
                  sam_per  = str2num(D{i+1});
                  fs_ERPSS = round((1/sam_per)*10^6);
                  break % JLC
            end
      end

      % #######  JLC  ##############
      for i=1:500 %because the sample period will be located somewhere in between here
            if strcmp(D{i},'presampling')
                  pre_sam = str2num(D{i+1});
                  pre_sam = -pre_sam/1000; % usec to msec
                  break % JLC
            end
      end

      %Create ERP structure

      % JLC Remainder:  presampling     200000
      %
      % @Eric : ERPSS text file has ALL info you need to load it. It is NOT necessary to contrast fs, xmin, xmax, pnts, etc
      % against what the user entered in OPTIONS at the IMPORT GUI. OPTIONS must work only for universal text.
      %
      % ####################

      %####### no fs test for ERPSS #######  JLC
      %if abs(((fs-fs_ERPSS)/fs_ERPSS)*100)>10
      %        serror=3;
      %end
      %###################################

      %ERP.srate     = fs;
      %ERP.srate=(1/sdistance)*1000;
      ERP.srate = fs_ERPSS;  % JLC

      %times= round(linspace(xlim(1), xlim(2), numberofpoints));

      % JLC  ######
      times = pre_sam:(1000/fs_ERPSS):numberofpoints*(1000/fs_ERPSS)+(pre_sam)-1;
      ERP.times = times;
      ERP.xmin  = min(times)/1000;
      ERP.xmax  = max(times)/1000;
      % JLC ###########

      %channel locations
      fid = fopen(fullname);
      C   = textscan(fid, '%d %s', 256, 'headerLines', 6);
      fclose(fid);

      channelnames = cellstr(C{2});
      [a b] = size(channelnames);

      for i=1:a
            k = channelnames{i};
            j = regexp(k,'"(\w*)"', 'tokens');
            channelnames{i} = char(j{:});
      end

      b = int2str(C{1});
      channelnumbers = cellstr(b);

      for i=1:a
            x = channelnumbers{i};
            tempchannum = str2num(x);
            tempchannum = tempchannum+1;
            channelnumbers{i} = int2str(tempchannum);
      end
      if isfield(ERP, 'chanlocs')
            ERP=rmfield(ERP, 'chanlocs');
      end
      %channelnames
      for i=1:a
            ERP.chanlocs(1,i) = struct('labels', channelnames{i});
      end
      %ERP.erpname
      g = D{1};
      g = strtrim(strrep(g,' ','_'));
      g = strrep(g,'-','_');
      %g(ismember_bc2(double(g),[45])) = ''; %removes '-'   %%If name starts with numbers, will not work

      a = regexp(g,'"(.*)"', 'tokens');
      a = strrep(a{:},'"','');
      %     if double(b(1))==48:57
      %         strcat('A_', b);
      %     end

      ERP.erpname = char(a{:});    %char(a{:}) converts cell to character

% %       %bindescriptor name
% %       if format ==0 % explicit
% %             i=1; j=1; k=1;
% %
% %             while i<=(m-numberofpoints)
% %                   if strcmp(D{i}, 'Bin') & strcmp(D{i+1}, 'desc:')
% %                         i=i+2;
% %
% %                         while strcmp(D{i},'#') ~= 1
% %                               binnames{j,k} = [blanks(1) D{i} ];
% %                               k = k+1;
% %                               i = i+1;
% %                         end
% %                         j = j+1;
% %                         k=1;
% %                   else
% %                         i = i+1;
% %                   end
% %             end
% %             for i=1:numofbins
% %                   ERP.bindescr{1,i} = strtrim(strcat(binnames{i+1,:}));
% %             end
% %       else % implicit
% %             i=1;j=1;
% %             m = length(D);
% %
% %             while i<= m %JLC
% %                   if D{i}=='#' & strcmp(D{i+1}, 'binno') & D{i+3}=='#'
% %                         i = i+4;
% %                         h = D{i}
% %                         %h = strtrim(strrep(h,' ','_'));
% %                         h = strrep(h,'-','_')
% %                         %h(ismember_bc2(double(h),[45])) = '';   %removes '-'
% %                         %h
% %                         b = regexp(h,'bindesc=(.*)', 'tokens')  %if there is a space between binname and last ", will not work
% %                         b = strrep(b{:},'"','')
% %
% %                         ERP.bindescr{1,j} = char(b{:});
% %                         j = j+1;
% %                   else
% %                         i = i+1;
% %                   end
% %             end
% %       end
      ERP.bindescr = BDesc;
      ERP = sorterpstruct(ERP);

      % Implicit format (bin header but no channel header)

% else %if not ERPSS file
%       msgboxText =  ['Something went wrong. '...
%             'Please, verify the file format.'...
%             ' For ERPSS text file, please check the organization of the data values,'...
%             ' as well as channel headers between channels.'];
%       %title = 'ERPLAB: pop_importerpss() error:';
%       error('Error:importerpss', msgboxText);
%       return
% end


function varargout = process_matlab_eval2( varargin )
% PROCESS_MATLAB_EVAL2: Evaluate a matlab script.

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2013

eval(macro_method);
end

%% ===== GET DESCRIPTION =====
function sProcess = GetDescription() %#ok<DEFNU>
    % Description the process
    sProcess.Comment     = 'Run Matlab command';
    sProcess.FileTag     = 'matlab';
    sProcess.Category    = 'Filter2';
    sProcess.SubGroup    = 'Other';
    sProcess.Index       = 902;
    sProcess.Description = 'https://neuroimage.usc.edu/brainstorm/Tutorials/TutUserProcess#Alternative';
    % Definition of the input accepted by this process
    sProcess.InputTypes  = {'data', 'results', 'timefreq', 'raw', 'matrix'};
    sProcess.OutputTypes = {'data', 'results', 'timefreq', 'raw', 'matrix'};
    sProcess.nInputs     = 2;
    sProcess.nMinFiles   = 1;
    sProcess.isPaired    = 1;
    % Default values for some options
    sProcess.isSourceAbsolute = -1;
    sProcess.processDim  = [];
    % === Matlab command
    sProcess.options.matlab.Comment = 'Type your Matlab script below: ';
    sProcess.options.matlab.Type    = 'textarea';
    sProcess.options.matlab.Value   = ['% Input variables: DataA, DataB, TimeVector' 10  ...
                                       '% Output variables: Data, Comment, Condition', 10 ...
                                       'Data = DataA - DataB;' 10 ...
                                       'Comment = ''New file'';' 10 ...
                                       'Condition = ''NewCondition'';'];
    % === Sensor types
    sProcess.options.sensortypes.Comment = 'Sensor types or names (empty=all): ';
    sProcess.options.sensortypes.Type    = 'text';
    sProcess.options.sensortypes.Value   = 'MEG, EEG';
    sProcess.options.sensortypes.InputTypes = {'data', 'raw'};
end

%% ===== FORMAT COMMENT =====
function Comment = FormatComment(sProcess) %#ok<DEFNU>
    Comment = sProcess.Comment;
end

%% ===== RUN =====
function sOutput = Run(sProcess, sInputA, sInputB) %#ok<DEFNU>
    % Prepare input
    DataA = sInputA.A;
    DataB = sInputB.A;
    TimeVector = sInputA.TimeVector;
    Comment    = sInputA.Comment;
    Condition  = [];

    % Evaluate Matlab code
    try
        eval(sProcess.options.matlab.Value);
    catch
        % Get error message
        e = lasterror();
        if ~isempty(e)
            % Remove HTML tags
            errMsg = str_striptag(e.message);
            % Strip "Error:"
            errMsg = strrep(errMsg, 'Error: ', '');
            % Strip first line
            iNewLine = find(errMsg == 10);
            if ~isempty(iNewLine)
                errMsg = errMsg(iNewLine(1)+1:end);
            end
            errMsg = ['Error while executing Matlab command:' 10 errMsg];
        else
            errMsg = 'Error while executing Matlab command.';
        end
        % Report error
        bst_report('Error', sProcess, sInputA, errMsg);
        sOutput = [];
        return;
    end

    % Check if time was modified with only a few sensors selected
    if isfield(sProcess.options, 'sensortypes') && isfield(sProcess.options.sensortypes, 'Value') && ~isempty(sProcess.options.sensortypes.Value) && (length(TimeVector) ~= length(sInputA.TimeVector))
        sInputA = [];
        bst_report('Error', sProcess, sInputA, ...
            ['This process can modify the time definition only if all the channels are processed at once.' 10 ...
             'Either you leave the option "Sensor types or names" empty to process all the channels at once,' 10 ...
             'or your keep the number of time points of the original file.']);
        return;
    end

    % Output structure
    sOutput = sInputA;
    % Output condition name
    sOutput.A         = Data;
    sOutput.Condition = Condition;
    sOutput.Comment   = Comment;
end


classdef prtUiClassLabeler < hgsetget

    properties

        useClassifier = true;

        dataSet
        classifier = prtClassMap;
        handles

        onClickDisplayFunction = @(ds, obsInd, featureInds)plotAsTimeSeries(ds.retainObservations(obsInd));
    end
    methods
        function self = prtUiClassLabeler(varargin)
            self = prtUtilAssignStringValuePairs(self, varargin{:});

            if isempty(self.dataSet)
                error('dataSet must be defined on input');
            end

            if isempty(self.dataSet.Y)
                self.dataSet.Y = nan(self.dataSet.nObservations,1);
            end

            self.init();
        end
        function init(self)
            self.handles.mainFigure = figure;
            gca;
            if self.useClassifier
                self.handles.classifierFigure = figure;
            end

            self.udpate();
        end
        function udpate(self)
            axesObj = findobj(self.handles.mainFigure,'type','axes');
            %oldView = view(axesObj);
            oldXlim = xlim(axesObj);
            oldYlim = ylim(axesObj);
            oldZlim = zlim(axesObj);
            figure(self.handles.mainFigure)
            explore(self.dataSet, @(ds,obsInd,featureInd)self.onClick(ds,obsInd,featureInd));

            %view(axesObj,oldView);
            xlim(axesObj,oldXlim);
            ylim(axesObj,oldYlim);
            zlim(axesObj,oldZlim);

            if self.useClassifier && self.dataSet.nClasses > 1 && all(self.dataSet.nObservationsByClass > 2*self.dataSet.nFeatures)
                self.classifier = train(self.classifier, self.dataSet);
                figure(self.handles.classifierFigure)
                plot(self.classifier);
            end
        end

        function onClick(self,ds,obsInd, featureInd)
            self.handles.secondaryFigure = figure;
            self.handles.secondaryFigure.KeyPressFcn = @(h,e)self.onClickKeypress(h,e,obsInd);
            self.handles.secondaryFigure.WindowStyle = 'modal';

            self.onClickDisplayFunction(ds, obsInd, featureInd);

        end
        function onClickKeypress(self, h, e, obsInd)
            key = e.Key;
            switch key
                case {'0','1','2','3','4','5','6','7','8','9'}
                    newY = str2double(key);
                    self.dataSet.Y(obsInd) = newY;

                    close(self.handles.secondaryFigure);
                    self.udpate();
                otherwise
                    title('Invalid key')
            end

        end
    end
end


function layer = genNetworkLSTMEncoderDecoderScale2(para)

layer = genNetworkLSTMEncoderDecoder2(para);

layerScale.name = 'Input';
layerScale.inputIdx = 3;
layerScale.dim = [1 1];
layerScale.next = 1;

layer = [layer(1:end-1) layerScale layer(end)];

layer{end-3}.next = 3;
layer{end-2}.next = 2;
layer{end}.prev = [-3 -2 -1];
% layer{end} = rmfield(layer{end}, 'costFrameSelection');

end


function experiments = stack_votlt2018()

set_global_variable('bundle', 'http://data.votchallenge.net/vot2018/longterm/description.json');

baseline.name = 'longterm';
baseline.converter = [];
baseline.type = 'unsupervised';
baseline.tags = {};

baseline.parameters.repetitions = 1;
baseline.parameters.burnin = 0;

baseline.analysis = {'precision_recall', 'speed'};

redetect.name = 'redetection';
redetect.converter = @(sequence) sequence_test_redetection(sequence, ...
    'Length', 200, 'Initialization', 5, 'Padding',2, ...
    'Scaling', 3);

redetect.type = 'unsupervised';
redetect.tags = {};

redetect.parameters.repetitions = 1;
redetect.parameters.burnin = 0;

redetect.analysis = {'redetection'};

experiments = {redetect, baseline};

end


function pot = rescale_pot(pot, s)
% RESCALE_POT Add a constant to the mpot scale factor.
% pot = rescale_pot(pot, s)

pot.p = pot.p*s;


T_10 = readtable('/Users/lbasek/image-denoising-benchmark/results/final_results_sigma10.csv');
T_10(:,'WNNM') = [];
T_10(:,'NCSR') = [];

T_15 = readtable('/Users/lbasek/image-denoising-benchmark/results/final_results_sigma15.csv');
T_15(:,'WNNM') = [];
T_15(:,'NCSR') = [];

T_20 = readtable('/Users/lbasek/image-denoising-benchmark/results/final_results_sigma20.csv');
T_20(:,'WNNM') = [];
T_20(:,'NCSR') = [];

T_25 = readtable('/Users/lbasek/image-denoising-benchmark/results/final_results_sigma25.csv');
T_25(:,'WNNM') = [];
T_25(:,'NCSR') = [];

T_50 = readtable('/Users/lbasek/image-denoising-benchmark/results/final_results_sigma50.csv');
T_50(:,'WNNM') = [];
T_50(:,'NCSR') = [];

time_row_10 = T_10(4,:);
time_row_15 = T_15(4,:);
time_row_20 = T_20(4,:);
time_row_25 = T_25(4,:);
time_row_50 = T_50(4,:);

x = [0,10,15,20,25,50];

bm3d_10 = time_row_10{1,3};
bm3d_15 = time_row_15{1,3};
bm3d_20 = time_row_20{1,3};
bm3d_25 = time_row_25{1,3};
bm3d_50 = time_row_50{1,3};

ksvd_10 = time_row_10{1,4};
ksvd_15 = time_row_15{1,4};
ksvd_20 = time_row_20{1,4};
ksvd_25 = time_row_25{1,4};
ksvd_50 = time_row_50{1,4};

foe_10 = time_row_10{1,5};
foe_15 = ssim_row_15{1,5};
foe_20 = time_row_20{1,5};
foe_25 = time_row_25{1,5};
foe_50 = time_row_50{1,5};

epll_10 = time_row_10{1,6};
epll_15 = time_row_20{1,6};
epll_20 = ssim_row_20{1,6};
epll_25 = time_row_25{1,6};
epll_50 = time_row_50{1,6};

y1 = [time_row_10{1,2}, bm3d_10,bm3d_15,bm3d_20,bm3d_25,bm3d_50];
y2 = [time_row_10{1,2}, ksvd_10,ksvd_15,ksvd_20,ksvd_25,ksvd_50];
y3 = [time_row_10{1,2}, foe_10,foe_15,foe_20,foe_25,foe_50];
y4 = [time_row_10{1,2}, epll_10,epll_15,epll_20,epll_25,epll_50];

h = figure;
hold on
h1 = plot(x,y1,'-s','MarkerSize',10);
h2 = plot(x,y2,'-s','MarkerSize',10);
h3 = plot(x,y3,'-s','MarkerSize',10);
h4 = plot(x,y4,'-s','MarkerSize',10);
hold off
set([h1,h2,h3,h4],'LineWidth',2)
ylabel('Time (sec)')
xlabel('Noise Power')
legend('BM3D','KSVD','FOE','EPLL');
grid on
saveas(h,'./graphs/time','png');


function xyr = Xr(s)

x = 1 ;

y = s ;

xyr = [x ; y] ;


function y = eq(a, b, same)
%EQ Overloaded equality operator, or test for Layer instance equality
%   EQ(A, B), A == B returns a Layer that tests equality of the outputs of
%   two Layers (one of them may be constant).
%
%   EQ(A, B, 'sameInstance') checks if two variables refer to the same
%   Layer instance (i.e., calls the == operator for handle classes).

  if nargin <= 2
    y = Layer(@eq, a, b) ;
    y.numInputDer = 0 ;  % non-differentiable
  else
    assert(isequal(same, 'sameInstance'), ...
      'The only accepted extra flag for EQ is ''sameInstance''.') ;

    if ~isa(a, 'Layer') || ~isa(b, 'Layer')
      y = false ;
    else
      y = eq@handle(a, b) ;
    end
  end
end