function [par_TIR] = read_tireparameters(filepath_tireparameters)

    %#codegen

    %% Import

    fid = fopen(filepath_tireparameters, 'r');

    % Alle relevanten Zeilen auslesen und in Cell Array "content" speichern
    content = {};

    bool_isavailable_mfsimple = false;
    bool_isavailable_mfextended = false;

    while ~feof(fid)
        line = fgetl(fid);
        if ~isempty(line)
            if strcmp(line(1), '!') == 0 && strcmp(line(1), '$') == 0 && strcmp(line(1), '[') == 0 && strcmp(line(1), '{') == 0 && strcmp(line(1), '''') == 0
                content = [content; line];
            end
        end

        % get which tire model parameters are available
        % options: five parameter MF, extended MF, both

        if contains(line, "[MFSIMPLE]")
            bool_isavailable_mfsimple = true;

        elseif contains(line, "[UNITS]")
            bool_isavailable_mfextended = true;
        end

    end

    fclose(fid);

    %% Bearbeitung: Struct erstellen und befuellen

    % Alle Leerzeichen aus den einzelnen Zellen entfernen
    for i = 1 : length(content)
        content{i} = strrep(content{i}, ' ', '');       % Leerzeichen loeschen
        content{i} = regexprep(content{i}, '\t', '');   % Tabs loeschen
    end

    if bool_isavailable_mfsimple

        % [MFSIMPLE]
        % read parameters for 5 param Pacejka tire model
        par_TIR.MFSIMPLE.PacLong_B                  = read_parameters_sub(content,'PacLong_B',filepath_tireparameters);
        par_TIR.MFSIMPLE.PacLong_C                  = read_parameters_sub(content,'PacLong_C',filepath_tireparameters);
        par_TIR.MFSIMPLE.PacLong_D                  = read_parameters_sub(content,'PacLong_D',filepath_tireparameters);
        par_TIR.MFSIMPLE.PacLong_E                  = read_parameters_sub(content,'PacLong_E',filepath_tireparameters);
        par_TIR.MFSIMPLE.PacLong_Fznom            	= read_parameters_sub(content,'PacLong_Fznom',filepath_tireparameters);
        par_TIR.MFSIMPLE.PacLong_eps_load        	= read_parameters_sub(content,'PacLong_eps_load',filepath_tireparameters);

        par_TIR.MFSIMPLE.PacLat_B                   = read_parameters_sub(content,'PacLat_B',filepath_tireparameters);
        par_TIR.MFSIMPLE.PacLat_C                   = read_parameters_sub(content,'PacLat_C',filepath_tireparameters);
        par_TIR.MFSIMPLE.PacLat_D                   = read_parameters_sub(content,'PacLat_D',filepath_tireparameters);
        par_TIR.MFSIMPLE.PacLat_E                   = read_parameters_sub(content,'PacLat_E',filepath_tireparameters);
        par_TIR.MFSIMPLE.PacLat_Fznom               = read_parameters_sub(content,'PacLat_Fznom',filepath_tireparameters);
        par_TIR.MFSIMPLE.PacLat_eps_load           	= read_parameters_sub(content,'PacLat_eps_load',filepath_tireparameters);

        par_TIR.MFSIMPLE.r_tire_m                   = read_parameters_sub(content,'r_tire_m',filepath_tireparameters);
        par_TIR.MFSIMPLE.Iyy_Wheel_kgm2             = read_parameters_sub(content,'Iyy_Wheel_kgm2',filepath_tireparameters);

    end

    if bool_isavailable_mfextended

        % [UNITS]
        ANGLE_temp                      = read_parameters_sub(content,'ANGLE',filepath_tireparameters);

        switch lower(ANGLE_temp)
            case ('degrees')
                par_TIR.ANGLE = 180 / pi;                   % unit conversion [rad] -> [degree]
            case ('radians')
                par_TIR.ANGLE = 1;
            otherwise
                error('Winkeleinheit konnte nicht bestimmt werden!');
        end

        % [MODEL]
        TYRESIDE_temp                    = read_parameters_sub(content,'TYRESIDE',filepath_tireparameters);

        switch lower(TYRESIDE_temp)
            case ('left')
                par_TIR.TYRESIDE = 1;
            case ('right')
                par_TIR.TYRESIDE = -1;
            case ('symmetric')
                par_TIR.TYRESIDE = 0;
            otherwise
                error('TYRESIDE konnte nicht bestimmt werden!');
        end

        par_TIR.USE_MODE                 = read_parameters_sub(content,'USE_MODE',filepath_tireparameters);
        par_TIR.LONGVL                              = read_parameters_sub(content,'LONGVL',filepath_tireparameters);

        % [INERTIAL]
        par_TIR.INERTIAL.m_Wheel_kg                 = read_parameters_sub(content,'m_Wheel_kg',filepath_tireparameters);
        par_TIR.INERTIAL.Iyy_Wheel_kgm2             = read_parameters_sub(content,'Iyy_Wheel_kgm2',filepath_tireparameters);

        % [WHEEL]
        par_TIR.WHEEL.br_Nmsprad                    = read_parameters_sub(content,'br_Nmsprad',filepath_tireparameters);
        par_TIR.WHEEL.FNOMIN                        = read_parameters_sub(content,'FNOMIN',filepath_tireparameters);
        par_TIR.WHEEL.NORMPRES                      = read_parameters_sub(content,'NORMPRES',filepath_tireparameters);
        par_TIR.WHEEL.TYRE_RADIUS_MOD           	= read_parameters_sub(content,'TYRE_RADIUS_MOD',filepath_tireparameters);
        par_TIR.WHEEL.T_RelaxationLong           	= read_parameters_sub(content,'T_RelaxationLong',filepath_tireparameters);
        par_TIR.WHEEL.T_RelaxationLat           	= read_parameters_sub(content,'T_RelaxationLat',filepath_tireparameters);
        par_TIR.WHEEL.T_RelaxationMy           	    = read_parameters_sub(content,'T_RelaxationMy',filepath_tireparameters);

        % [DIMENSION]
        par_TIR.DIMENSION.UNLOADED_RADIUS           = read_parameters_sub(content,'UNLOADED_RADIUS',filepath_tireparameters);
        par_TIR.DIMENSION.WIDTH                     = read_parameters_sub(content,'WIDTH',filepath_tireparameters);
        par_TIR.DIMENSION.ASPECT_RATIO              = read_parameters_sub(content,'ASPECT_RATIO',filepath_tireparameters);
        par_TIR.DIMENSION.RIM_RADIUS                = read_parameters_sub(content,'RIM_RADIUS',filepath_tireparameters);
        par_TIR.DIMENSION.RIM_WIDTH                 = read_parameters_sub(content,'RIM_WIDTH',filepath_tireparameters);

        % [VERTICAL]
        par_TIR.VERTICAL.VERTICAL_STIFFNESS         = read_parameters_sub(content,'VERTICAL_STIFFNESS',filepath_tireparameters);
        par_TIR.VERTICAL.VERTICAL_DAMPING           = read_parameters_sub(content,'VERTICAL_DAMPING',filepath_tireparameters);
        par_TIR.VERTICAL.BREFF                      = read_parameters_sub(content,'BREFF',filepath_tireparameters);
        par_TIR.VERTICAL.DREFF                      = read_parameters_sub(content,'DREFF',filepath_tireparameters);
        par_TIR.VERTICAL.FREFF                      = read_parameters_sub(content,'FREFF',filepath_tireparameters);
        % added for matlab tire model
        par_TIR.VERTICAL.Q_RE0                      = read_parameters_sub(content,'Q_RE0',filepath_tireparameters);
        par_TIR.VERTICAL.Q_V1                       = read_parameters_sub(content,'Q_V1',filepath_tireparameters);
        par_TIR.VERTICAL.Q_V2                       = read_parameters_sub(content,'Q_V2',filepath_tireparameters);
        par_TIR.VERTICAL.Q_FZ1                      = read_parameters_sub(content,'Q_FZ1',filepath_tireparameters);
        par_TIR.VERTICAL.Q_FZ2                      = read_parameters_sub(content,'Q_FZ2',filepath_tireparameters);
        par_TIR.VERTICAL.Q_FZ3                      = read_parameters_sub(content,'Q_FZ3',filepath_tireparameters);
        par_TIR.VERTICAL.Q_FCX                      = read_parameters_sub(content,'Q_FCX',filepath_tireparameters);
        par_TIR.VERTICAL.Q_FCY                      = read_parameters_sub(content,'Q_FCY',filepath_tireparameters);
        par_TIR.VERTICAL.Q_FCY2                     = read_parameters_sub(content,'Q_FCY2',filepath_tireparameters);
        par_TIR.VERTICAL.PFZ1                       = read_parameters_sub(content,'PFZ1',filepath_tireparameters);

        % [SIMULATION]
        par_TIR.SIMULATION.KPUMIN                   = read_parameters_sub(content,'KPUMIN',filepath_tireparameters);
        par_TIR.SIMULATION.KPUMAX                   = read_parameters_sub(content,'KPUMAX',filepath_tireparameters);
        par_TIR.SIMULATION.ALPMIN                   = read_parameters_sub(content,'ALPMIN',filepath_tireparameters);
        par_TIR.SIMULATION.ALPMAX                   = read_parameters_sub(content,'ALPMAX',filepath_tireparameters);
        par_TIR.SIMULATION.CAMMIN                   = read_parameters_sub(content,'CAMMIN',filepath_tireparameters);
        par_TIR.SIMULATION.CAMMAX                   = read_parameters_sub(content,'CAMMAX',filepath_tireparameters);
        par_TIR.SIMULATION.FZMIN                    = read_parameters_sub(content,'FZMIN',filepath_tireparameters);
        par_TIR.SIMULATION.FZMAX                    = read_parameters_sub(content,'FZMAX',filepath_tireparameters);
        par_TIR.SIMULATION.LONGVL                   = read_parameters_sub(content,'LONGVL',filepath_tireparameters);
        % added for matlab tire model
        par_TIR.SIMULATION.VXLOW                    = read_parameters_sub(content,'VXLOW',filepath_tireparameters);
        par_TIR.SIMULATION.PRESMIN               	= read_parameters_sub(content,'PRESMIN',filepath_tireparameters);
        par_TIR.SIMULATION.PRESMAX               	= read_parameters_sub(content,'PRESMAX',filepath_tireparameters);

        % [SCALING_COEFFICIENTS]
        par_TIR.SCALING.LFZO                     = read_parameters_sub(content,'LFZO',filepath_tireparameters);
        par_TIR.SCALING.LCX                      = read_parameters_sub(content,'LCX',filepath_tireparameters);
        par_TIR.SCALING.LMUX                     = read_parameters_sub(content,'LMUX',filepath_tireparameters);
        par_TIR.SCALING.LEX                      = read_parameters_sub(content,'LEX',filepath_tireparameters);
        par_TIR.SCALING.LKX                      = read_parameters_sub(content,'LKX',filepath_tireparameters);
        par_TIR.SCALING.LHX                      = read_parameters_sub(content,'LHX',filepath_tireparameters);
        par_TIR.SCALING.LVX                      = read_parameters_sub(content,'LVX',filepath_tireparameters);
        par_TIR.SCALING.LGAX                     = read_parameters_sub(content,'LGAX',filepath_tireparameters);
        par_TIR.SCALING.LCY                      = read_parameters_sub(content,'LCY',filepath_tireparameters);
        par_TIR.SCALING.LMUY                     = read_parameters_sub(content,'LMUY',filepath_tireparameters);
        par_TIR.SCALING.LEY                      = read_parameters_sub(content,'LEY',filepath_tireparameters);
        par_TIR.SCALING.LKY                      = read_parameters_sub(content,'LKY',filepath_tireparameters);
        par_TIR.SCALING.LHY                      = read_parameters_sub(content,'LHY',filepath_tireparameters);
        par_TIR.SCALING.LVY                      = read_parameters_sub(content,'LVY',filepath_tireparameters);
        par_TIR.SCALING.LGAY                     = read_parameters_sub(content,'LGAY',filepath_tireparameters);
        par_TIR.SCALING.LTR                      = read_parameters_sub(content,'LTR',filepath_tireparameters);
        par_TIR.SCALING.LRES                     = read_parameters_sub(content,'LRES',filepath_tireparameters);
        par_TIR.SCALING.LGAZ                     = read_parameters_sub(content,'LGAZ',filepath_tireparameters);
        par_TIR.SCALING.LXAL                     = read_parameters_sub(content,'LXAL',filepath_tireparameters);
        par_TIR.SCALING.LYKA                     = read_parameters_sub(content,'LYKA',filepath_tireparameters);
        par_TIR.SCALING.LVYKA                    = read_parameters_sub(content,'LVYKA',filepath_tireparameters);
        par_TIR.SCALING.LS                       = read_parameters_sub(content,'LS',filepath_tireparameters);
        par_TIR.SCALING.LSGKP                    = read_parameters_sub(content,'LSGKP',filepath_tireparameters);
        par_TIR.SCALING.LSGAL                    = read_parameters_sub(content,'LSGAL',filepath_tireparameters);
        par_TIR.SCALING.LGYR                     = read_parameters_sub(content,'LGYR',filepath_tireparameters);
        par_TIR.SCALING.LMX                      = read_parameters_sub(content,'LMX',filepath_tireparameters);
        par_TIR.SCALING.LVMX                     = read_parameters_sub(content,'LVMX',filepath_tireparameters);
        par_TIR.SCALING.LMY                      = read_parameters_sub(content,'LMY',filepath_tireparameters);
        % added for matlab tire model
        par_TIR.SCALING.LMUV                     = read_parameters_sub(content,'LMUV',filepath_tireparameters);
        par_TIR.SCALING.LCZ                      = read_parameters_sub(content,'LCZ',filepath_tireparameters);
        par_TIR.SCALING.LMPHI                    = read_parameters_sub(content,'LMPHI',filepath_tireparameters);

        % [LONGITUDINAL_COEFFICIENTS]
        par_TIR.LONGITUDINAL.PCX1                     = read_parameters_sub(content,'PCX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PDX1                     = read_parameters_sub(content,'PDX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PDX2                     = read_parameters_sub(content,'PDX2',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PDX3                     = read_parameters_sub(content,'PDX3',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PEX1                     = read_parameters_sub(content,'PEX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PEX2                     = read_parameters_sub(content,'PEX2',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PEX3                     = read_parameters_sub(content,'PEX3',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PEX4                     = read_parameters_sub(content,'PEX4',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PKX1                     = read_parameters_sub(content,'PKX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PKX2                     = read_parameters_sub(content,'PKX2',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PKX3                     = read_parameters_sub(content,'PKX3',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PHX1                     = read_parameters_sub(content,'PHX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PHX2                     = read_parameters_sub(content,'PHX2',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PVX1                     = read_parameters_sub(content,'PVX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PVX2                     = read_parameters_sub(content,'PVX2',filepath_tireparameters);
        par_TIR.LONGITUDINAL.RBX1                     = read_parameters_sub(content,'RBX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.RBX2                     = read_parameters_sub(content,'RBX2',filepath_tireparameters);
        par_TIR.LONGITUDINAL.RCX1                     = read_parameters_sub(content,'RCX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.REX1                     = read_parameters_sub(content,'REX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.REX2                     = read_parameters_sub(content,'REX2',filepath_tireparameters);
        par_TIR.LONGITUDINAL.RHX1                     = read_parameters_sub(content,'RHX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PTX1                     = read_parameters_sub(content,'PTX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PTX2                     = read_parameters_sub(content,'PTX2',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PTX3                     = read_parameters_sub(content,'PTX3',filepath_tireparameters);
        % added for matlab tire model
        par_TIR.LONGITUDINAL.PPX1                     = read_parameters_sub(content,'PPX1',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PPX2                     = read_parameters_sub(content,'PPX2',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PPX3                     = read_parameters_sub(content,'PPX3',filepath_tireparameters);
        par_TIR.LONGITUDINAL.PPX4                     = read_parameters_sub(content,'PPX4',filepath_tireparameters);
        par_TIR.LONGITUDINAL.RBX3                     = read_parameters_sub(content,'RBX3',filepath_tireparameters);

        % [OVERTURNING_COEFFICIENTS]
        par_TIR.OVERTURNING.QSX1                     = read_parameters_sub(content,'QSX1',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX2                     = read_parameters_sub(content,'QSX2',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX3                     = read_parameters_sub(content,'QSX3',filepath_tireparameters);
        % added for matlab tire model
        par_TIR.OVERTURNING.QSX4                     = read_parameters_sub(content,'QSX4',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX5                     = read_parameters_sub(content,'QSX5',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX6                     = read_parameters_sub(content,'QSX6',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX7                     = read_parameters_sub(content,'QSX7',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX8                     = read_parameters_sub(content,'QSX8',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX9                     = read_parameters_sub(content,'QSX9',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX10                    = read_parameters_sub(content,'QSX10',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX11                    = read_parameters_sub(content,'QSX11',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX12                    = read_parameters_sub(content,'QSX12',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX13                    = read_parameters_sub(content,'QSX13',filepath_tireparameters);
        par_TIR.OVERTURNING.QSX14                    = read_parameters_sub(content,'QSX14',filepath_tireparameters);
        par_TIR.OVERTURNING.PPMX1                    = read_parameters_sub(content,'PPMX1',filepath_tireparameters);

        % [LATERAL_COEFFICIENTS]
        par_TIR.LATERAL.PCY1                     = read_parameters_sub(content,'PCY1',filepath_tireparameters);
        par_TIR.LATERAL.PDY1                     = read_parameters_sub(content,'PDY1',filepath_tireparameters);
        par_TIR.LATERAL.PDY2                     = read_parameters_sub(content,'PDY2',filepath_tireparameters);
        par_TIR.LATERAL.PDY3                     = read_parameters_sub(content,'PDY3',filepath_tireparameters);
        par_TIR.LATERAL.PEY1                     = read_parameters_sub(content,'PEY1',filepath_tireparameters);
        par_TIR.LATERAL.PEY2                     = read_parameters_sub(content,'PEY2',filepath_tireparameters);
        par_TIR.LATERAL.PEY3                     = read_parameters_sub(content,'PEY3',filepath_tireparameters);
        par_TIR.LATERAL.PEY4                     = read_parameters_sub(content,'PEY4',filepath_tireparameters);
        par_TIR.LATERAL.PKY1                     = read_parameters_sub(content,'PKY1',filepath_tireparameters);
        par_TIR.LATERAL.PKY2                     = read_parameters_sub(content,'PKY2',filepath_tireparameters);
        par_TIR.LATERAL.PKY3                     = read_parameters_sub(content,'PKY3',filepath_tireparameters);
        par_TIR.LATERAL.PHY1                     = read_parameters_sub(content,'PHY1',filepath_tireparameters);
        par_TIR.LATERAL.PHY2                     = read_parameters_sub(content,'PHY2',filepath_tireparameters);
        par_TIR.LATERAL.PHY3                     = read_parameters_sub(content,'PHY3',filepath_tireparameters);
        par_TIR.LATERAL.PVY1                     = read_parameters_sub(content,'PVY1',filepath_tireparameters);
        par_TIR.LATERAL.PVY2                     = read_parameters_sub(content,'PVY2',filepath_tireparameters);
        par_TIR.LATERAL.PVY3                     = read_parameters_sub(content,'PVY3',filepath_tireparameters);
        par_TIR.LATERAL.PVY4                     = read_parameters_sub(content,'PVY4',filepath_tireparameters);
        par_TIR.LATERAL.RBY1                     = read_parameters_sub(content,'RBY1',filepath_tireparameters);
        par_TIR.LATERAL.RBY2                     = read_parameters_sub(content,'RBY2',filepath_tireparameters);
        par_TIR.LATERAL.RBY3                     = read_parameters_sub(content,'RBY3',filepath_tireparameters);
        par_TIR.LATERAL.RCY1                     = read_parameters_sub(content,'RCY1',filepath_tireparameters);
        par_TIR.LATERAL.REY1                     = read_parameters_sub(content,'REY1',filepath_tireparameters);
        par_TIR.LATERAL.REY2                     = read_parameters_sub(content,'REY2',filepath_tireparameters);
        par_TIR.LATERAL.RHY1                     = read_parameters_sub(content,'RHY1',filepath_tireparameters);
        par_TIR.LATERAL.RHY2                     = read_parameters_sub(content,'RHY2',filepath_tireparameters);
        par_TIR.LATERAL.RVY1                     = read_parameters_sub(content,'RVY1',filepath_tireparameters);
        par_TIR.LATERAL.RVY2                     = read_parameters_sub(content,'RVY2',filepath_tireparameters);
        par_TIR.LATERAL.RVY3                     = read_parameters_sub(content,'RVY3',filepath_tireparameters);
        par_TIR.LATERAL.RVY4                     = read_parameters_sub(content,'RVY4',filepath_tireparameters);
        par_TIR.LATERAL.RVY5                     = read_parameters_sub(content,'RVY5',filepath_tireparameters);
        par_TIR.LATERAL.RVY6                     = read_parameters_sub(content,'RVY6',filepath_tireparameters);
        par_TIR.LATERAL.PTY1                     = read_parameters_sub(content,'PTY1',filepath_tireparameters);
        par_TIR.LATERAL.PTY2                     = read_parameters_sub(content,'PTY2',filepath_tireparameters);
        % added for matlab tire model
        par_TIR.LATERAL.PEY5                     = read_parameters_sub(content,'PEY5',filepath_tireparameters);
        par_TIR.LATERAL.PKY4                     = read_parameters_sub(content,'PKY4',filepath_tireparameters);
        par_TIR.LATERAL.PKY5                     = read_parameters_sub(content,'PKY5',filepath_tireparameters);
        par_TIR.LATERAL.PKY6                     = read_parameters_sub(content,'PKY6',filepath_tireparameters);
        par_TIR.LATERAL.PKY7                     = read_parameters_sub(content,'PKY7',filepath_tireparameters);
        par_TIR.LATERAL.PPY1                     = read_parameters_sub(content,'PPY1',filepath_tireparameters);
        par_TIR.LATERAL.PPY2                     = read_parameters_sub(content,'PPY2',filepath_tireparameters);
        par_TIR.LATERAL.PPY3                     = read_parameters_sub(content,'PPY3',filepath_tireparameters);
        par_TIR.LATERAL.PPY4                     = read_parameters_sub(content,'PPY4',filepath_tireparameters);
        par_TIR.LATERAL.PPY5                     = read_parameters_sub(content,'PPY5',filepath_tireparameters);
        par_TIR.LATERAL.RBY4                     = read_parameters_sub(content,'RBY4',filepath_tireparameters);

        % [ROLLING_COEFFICIENTS]
        par_TIR.ROLLING.QSY1                     = read_parameters_sub(content,'QSY1',filepath_tireparameters);
        par_TIR.ROLLING.QSY2                     = read_parameters_sub(content,'QSY2',filepath_tireparameters);
        par_TIR.ROLLING.QSY3                     = read_parameters_sub(content,'QSY3',filepath_tireparameters);
        par_TIR.ROLLING.QSY4                     = read_parameters_sub(content,'QSY4',filepath_tireparameters);
        % added for matlab tire model
        par_TIR.ROLLING.QSY5                     = read_parameters_sub(content,'QSY5',filepath_tireparameters);
        par_TIR.ROLLING.QSY6                     = read_parameters_sub(content,'QSY6',filepath_tireparameters);
        par_TIR.ROLLING.QSY7                     = read_parameters_sub(content,'QSY7',filepath_tireparameters);
        par_TIR.ROLLING.QSY8                     = read_parameters_sub(content,'QSY8',filepath_tireparameters);

        % [ALIGNING_COEFFICIENTS]
        par_TIR.ALIGNING.QBZ1                     = read_parameters_sub(content,'QBZ1',filepath_tireparameters);
        par_TIR.ALIGNING.QBZ2                     = read_parameters_sub(content,'QBZ2',filepath_tireparameters);
        par_TIR.ALIGNING.QBZ3                     = read_parameters_sub(content,'QBZ3',filepath_tireparameters);
        par_TIR.ALIGNING.QBZ4                     = read_parameters_sub(content,'QBZ4',filepath_tireparameters);
        par_TIR.ALIGNING.QBZ5                     = read_parameters_sub(content,'QBZ5',filepath_tireparameters);
        par_TIR.ALIGNING.QBZ9                     = read_parameters_sub(content,'QBZ9',filepath_tireparameters);
        par_TIR.ALIGNING.QBZ10                    = read_parameters_sub(content,'QBZ10',filepath_tireparameters);
        par_TIR.ALIGNING.QCZ1                     = read_parameters_sub(content,'QCZ1',filepath_tireparameters);
        par_TIR.ALIGNING.QDZ1                     = read_parameters_sub(content,'QDZ1',filepath_tireparameters);
        par_TIR.ALIGNING.QDZ2                     = read_parameters_sub(content,'QDZ2',filepath_tireparameters);
        par_TIR.ALIGNING.QDZ3                     = read_parameters_sub(content,'QDZ3',filepath_tireparameters);
        par_TIR.ALIGNING.QDZ4                     = read_parameters_sub(content,'QDZ4',filepath_tireparameters);
        par_TIR.ALIGNING.QDZ6                     = read_parameters_sub(content,'QDZ6',filepath_tireparameters);
        par_TIR.ALIGNING.QDZ7                     = read_parameters_sub(content,'QDZ7',filepath_tireparameters);
        par_TIR.ALIGNING.QDZ8                     = read_parameters_sub(content,'QDZ8',filepath_tireparameters);
        par_TIR.ALIGNING.QDZ9                     = read_parameters_sub(content,'QDZ9',filepath_tireparameters);
        par_TIR.ALIGNING.QEZ1                     = read_parameters_sub(content,'QEZ1',filepath_tireparameters);
        par_TIR.ALIGNING.QEZ2                     = read_parameters_sub(content,'QEZ2',filepath_tireparameters);
        par_TIR.ALIGNING.QEZ3                     = read_parameters_sub(content,'QEZ3',filepath_tireparameters);
        par_TIR.ALIGNING.QEZ4                     = read_parameters_sub(content,'QEZ4',filepath_tireparameters);
        par_TIR.ALIGNING.QEZ5                     = read_parameters_sub(content,'QEZ5',filepath_tireparameters);
        par_TIR.ALIGNING.QHZ1                     = read_parameters_sub(content,'QHZ1',filepath_tireparameters);
        par_TIR.ALIGNING.QHZ2                     = read_parameters_sub(content,'QHZ2',filepath_tireparameters);
        par_TIR.ALIGNING.QHZ3                     = read_parameters_sub(content,'QHZ3',filepath_tireparameters);
        par_TIR.ALIGNING.QHZ4                     = read_parameters_sub(content,'QHZ4',filepath_tireparameters);
        par_TIR.ALIGNING.SSZ1                     = read_parameters_sub(content,'SSZ1',filepath_tireparameters);
        par_TIR.ALIGNING.SSZ2                     = read_parameters_sub(content,'SSZ2',filepath_tireparameters);
        par_TIR.ALIGNING.SSZ3                     = read_parameters_sub(content,'SSZ3',filepath_tireparameters);
        par_TIR.ALIGNING.SSZ4                     = read_parameters_sub(content,'SSZ4',filepath_tireparameters);
        par_TIR.ALIGNING.QTZ1                     = read_parameters_sub(content,'QTZ1',filepath_tireparameters);
        par_TIR.ALIGNING.MBELT                    = read_parameters_sub(content,'MBELT',filepath_tireparameters);
        % added for matlab tire model
        par_TIR.ALIGNING.QBZ6                     = read_parameters_sub(content,'QBZ6',filepath_tireparameters);
        par_TIR.ALIGNING.QDZ10                    = read_parameters_sub(content,'QDZ10',filepath_tireparameters);
        par_TIR.ALIGNING.QDZ11                    = read_parameters_sub(content,'QDZ11',filepath_tireparameters);
        par_TIR.ALIGNING.PPZ1                    = read_parameters_sub(content,'PPZ1',filepath_tireparameters);
        par_TIR.ALIGNING.PPZ2                    = read_parameters_sub(content,'PPZ2',filepath_tireparameters);

        % TURNSLIP completely added for Matlab tire MODEL
        % [TURNSLIP]
        par_TIR.TURNSLIP.PDXP1                     = read_parameters_sub(content,'PDXP1',filepath_tireparameters);
        par_TIR.TURNSLIP.PDXP2                     = read_parameters_sub(content,'PDXP2',filepath_tireparameters);
        par_TIR.TURNSLIP.PDXP3                     = read_parameters_sub(content,'PDXP3',filepath_tireparameters);
        par_TIR.TURNSLIP.PKYP1                     = read_parameters_sub(content,'PKYP1',filepath_tireparameters);
        par_TIR.TURNSLIP.PDYP1                     = read_parameters_sub(content,'PDYP1',filepath_tireparameters);
        par_TIR.TURNSLIP.PDYP2                     = read_parameters_sub(content,'PDYP2',filepath_tireparameters);
        par_TIR.TURNSLIP.PDYP3                     = read_parameters_sub(content,'PDYP3',filepath_tireparameters);
        par_TIR.TURNSLIP.PDYP4                     = read_parameters_sub(content,'PDYP4',filepath_tireparameters);
        par_TIR.TURNSLIP.PHYP1                     = read_parameters_sub(content,'PHYP1',filepath_tireparameters);
        par_TIR.TURNSLIP.PHYP2                     = read_parameters_sub(content,'PHYP2',filepath_tireparameters);
        par_TIR.TURNSLIP.PHYP3                     = read_parameters_sub(content,'PHYP3',filepath_tireparameters);
        par_TIR.TURNSLIP.PHYP4                     = read_parameters_sub(content,'PHYP4',filepath_tireparameters);
        par_TIR.TURNSLIP.PECP1                     = read_parameters_sub(content,'PECP1',filepath_tireparameters);
        par_TIR.TURNSLIP.PECP2                     = read_parameters_sub(content,'PECP2',filepath_tireparameters);
        par_TIR.TURNSLIP.QDTP1                     = read_parameters_sub(content,'QDTP1',filepath_tireparameters);
        par_TIR.TURNSLIP.QCRP1                     = read_parameters_sub(content,'QCRP1',filepath_tireparameters);
        par_TIR.TURNSLIP.QCRP2                     = read_parameters_sub(content,'QCRP2',filepath_tireparameters);
        par_TIR.TURNSLIP.QBRP1                     = read_parameters_sub(content,'QBRP1',filepath_tireparameters);
        par_TIR.TURNSLIP.QDRP1                     = read_parameters_sub(content,'QDRP1',filepath_tireparameters);
        par_TIR.TURNSLIP.QDRP2                     = read_parameters_sub(content,'QDRP2',filepath_tireparameters);

        % CONTACTPATCH completely added for Matlab tire MODEL
        % [CONTACTPATCH]
        par_TIR.CONTACTPATCH.Q_RA1                   = read_parameters_sub(content,'Q_RA1',filepath_tireparameters);
        par_TIR.CONTACTPATCH.Q_RA2                   = read_parameters_sub(content,'Q_RA2',filepath_tireparameters);
        par_TIR.CONTACTPATCH.Q_RB1                   = read_parameters_sub(content,'Q_RB1',filepath_tireparameters);
        par_TIR.CONTACTPATCH.Q_RB2                   = read_parameters_sub(content,'Q_RB2',filepath_tireparameters);

        % STRUCTURAL completely added for Matlab tire MODEL
        % [STRUCTURAL]
        par_TIR.STRUCTURAL.LONGITUDINAL_STIFFNESS     = read_parameters_sub(content,'LONGITUDINAL_STIFFNESS',filepath_tireparameters);
        par_TIR.STRUCTURAL.LATERAL_STIFFNESS          = read_parameters_sub(content,'LATERAL_STIFFNESS',filepath_tireparameters);
        par_TIR.STRUCTURAL.PCFX1                      = read_parameters_sub(content,'PCFX1',filepath_tireparameters);
        par_TIR.STRUCTURAL.PCFX2                      = read_parameters_sub(content,'PCFX2',filepath_tireparameters);
        par_TIR.STRUCTURAL.PCFX3                      = read_parameters_sub(content,'PCFX3',filepath_tireparameters);
        par_TIR.STRUCTURAL.PCFY1                      = read_parameters_sub(content,'PCFY1',filepath_tireparameters);
        par_TIR.STRUCTURAL.PCFY2                      = read_parameters_sub(content,'PCFY2',filepath_tireparameters);
        par_TIR.STRUCTURAL.PCFY3                      = read_parameters_sub(content,'PCFY3',filepath_tireparameters);

        % GENERAL completely added for Matlab tire MODEL
        % [GENERAL]
        par_TIR.CONTACTPATCH.k1_TireFB_PT1              = read_parameters_sub(content,'k1_TireFB_PT1',filepath_tireparameters);
        par_TIR.CONTACTPATCH.k1_WheelsFB_PT1            = read_parameters_sub(content,'k1_WheelsFB_PT1',filepath_tireparameters);
        par_TIR.CONTACTPATCH.k2_TireFB_PT1              = read_parameters_sub(content,'k2_TireFB_PT1',filepath_tireparameters);
        par_TIR.CONTACTPATCH.p_Tires_Pa                 = read_parameters_sub(content,'p_Tires_Pa',filepath_tireparameters);

    end

end


function [mtexFig,newFigure] = newMtexFigure(varargin)
% set up a new plotting figure
%
% Syntax
%
%   newMtexFigure('figSize','large')
%   newMtexFigure('layout',[2,3])
%
% Options
%  figSize - huge, large, normal, small, tiny
%  layout  - [numberRows, numberColumns]
%

mtexFig = gcm;

% check hold state
newFigure = isempty(mtexFig) || check_option(varargin,'newFigure') || ...
  (strcmp(getHoldState,'off') && ~check_option(varargin,{'hold','parent','add2all'}) ...
  && ~isempty(get(mtexFig.currentAxes,'Children')));

% check tag
if ~newFigure && check_option(varargin,'ensureTag') && ...
    ~any(strcmpi(get(gcf,'tag'),get_option(varargin,'ensureTag')))
  newFigure = true;
  warning('MTEX:newFigure','Plot type not compatible to previous plot! I''going to create a new figure.');
end

% check appdata
ad = get_option(varargin,'ensureAppdata');
if ~newFigure
  try
    for i = 1:length(ad)
      if isappdata(gcf,ad{i}{1}) && ~isempty(ad{i}{2})
        ad_stored = getappdata(gcf,ad{i}{1});
        if isa(ad{i}{2},'symmetry')
          ad{i}{2} = ad{i}{2}.Laue;
          ad_stored = ad_stored.Laue;
        end
        if ~all(ad_stored == ad{i}{2})
          newFigure = true;
          if ishold
            warning('MTEX:newFigure','Plot properties not compatible to previous plot! I''going to create a new figure.');
          end
          break
        end
      elseif ~isappdata(gcf,ad{i}{1})
        newFigure = true;
        if ishold
          warning('MTEX:newFigure','Plot properties not compatible to previous plot! I''going to create a new figure.');
        end
        break
      end
    end
  catch %#ok<CTCH>
    newFigure = true;
  end
end

% set up a new figure
if newFigure

  if check_option(varargin,'parent')

    fig = get_option(varargin,'parent');
    mtexFig.gca = fig;
    while ~isempty(fig) && ~strcmp('figure', get(fig,'type'))
      fig = get(fig,'parent');
    end
    mtexFig.parent = fig;
    newFigure = false;

  else

    mtexFig = mtexFigure(varargin{:});

    % set tag
    if check_option(varargin,'ensureTag','char')
      set(gcf,'tag',get_option(varargin,'ensureTag'));
    end

    % set appdata
    if check_option(varargin,'ensureAppdata')
      for i = 1:length(ad)
        setappdata(gcf,ad{i}{1},ad{i}{2})
      end
    end
  end
else % use an existing figure

  % get existing mtexFigure
  mtexFig = getappdata(gcf,'mtexFig');

  holdState = getHoldState;
  % distribute hold state over all axes
  for i=1:numel(mtexFig.children)
    hold(mtexFig.children(i),holdState);
  end

  % set current axis
  if check_option(varargin,'parent')
    p =  get_option(varargin,'parent');
    if isgraphics(p,'axes')
      mtexFig.currentAxes = p;
    else
      mtexFig.currentAxes = get(p,'parent');
    end
  elseif check_option(varargin,'add2all')
    mtexFig.currentId = 1;
  end
end

if nargout == 0, clear mtexFig; end

end


function plot_recall_all_datasets()
  % Plot the average recall of PASCAL, ImageNet, and COCO for all methods.
  %
  % This function requires the proposals to already be saved to disk. It will
  % compute a matching between ground truth and proposals (if the result is not
  % yet found on disk) and then plot recall curves. The plots are saved to
  % figures/.

  methods = get_method_configs();
  methods([14 16 19:25]) = [];

  pascal = {methods.best_voc07_candidates_file};
  imagenet = {methods.best_imagenet_candidates_file};
  coco = {methods.best_coco14_candidates_file};

  valid_methods = check_for_data(cat(2, pascal(:), imagenet(:), coco(:)));
  if ~any(valid_methods)
    fprintf('no methods have the recall matchings computed, run the plot scripts for each of the datasets, to get the required data\n');
    return
  end
  methods = methods(valid_methods);
  pascal = {methods.best_voc07_candidates_file};
  imagenet = {methods.best_imagenet_candidates_file};
  coco = {methods.best_coco14_candidates_file};

%   plot_legend(methods);
%   printpdf('figures/imagenet_recall_legend.pdf');

  fprintf('\n\n');
  for i = 1:numel(methods)
    fprintf('Valid data for plots: %s\n', methods(i).name);
  end

  dataset_labels = {'PASCAL 2007', 'ImageNet 2013', 'COCO 2014'};
  AR_plots(methods, cat(2, pascal(:), imagenet(:), coco(:)), dataset_labels);
end

function AR_plots(methods, iou_files, dataset_labels)
  num_candidates = 1000;

  n = size(iou_files, 1);
  num_datasets = size(iou_files, 2);

  for i = 1:n
    ARs = zeros(1, num_datasets);
    for dataset_i = 1:num_datasets, iou_file = iou_files{i,dataset_i};
      try
        data = load(iou_file);

        num_experiments = numel(data.best_candidates);
        exp_idx = find([data.best_candidates.candidates_threshold] == num_candidates);
        assert(numel(exp_idx) == 1);
        experiment = data.best_candidates(exp_idx);
        [~, ~, ARs(dataset_i)] = compute_average_recall(experiment.best_candidates.iou);
      catch
        ARs(dataset_i) = nan;
      end
    end

    line_style = '-';
    if methods(i).is_baseline
      line_style = '--';
    end
    if ~isempty(methods(i).line_style)
      line_style = methods(i).line_style;
    end
    plot(1:num_datasets, ARs, '.', 'MarkerSize', 20, 'Color', methods(i).color, 'LineWidth', 1.5, 'LineStyle', line_style);
    hold on;
  end
  xlim([0.5, num_datasets + 0.5]);
  ylim([0.1, 0.6]);
  ylabel('average recall');
  hold off; grid on;
  set(gca,'XTick',(1:num_datasets),'XTickLabel',dataset_labels);
  set(gca,'XTickLabelRotation',25);
  set(gca, 'box','off');
  set(gca,'YTick', 0.1:0.1:0.6);

  hei = 10;
  wid = 8;
  set(gcf, 'Units','centimeters', 'Position',[0 0 wid hei]);
  set(gcf, 'PaperPositionMode','auto');
  printpdf('figures/average_recall_all_datasets.pdf');
end

function valid = check_for_data(candidate_files)
  valid = true(size(candidate_files));
  for i = 1:size(candidate_files,1)
    for j = 1:size(candidate_files,2)
      try
        ld = load(candidate_files{i,j});
      catch
        fprintf('file missing: %s\n', candidate_files{i,j});
        valid(i,j) = false;
      end
    end
  end
  valid = all(valid,2);
end


function [cfg] = ft_singleplotER(cfg, varargin)

% FT_SINGLEPLOTER plots the event-related fields or potentials of a single
% channel or the average over multiple channels. Multiple datasets can be
% overlayed.
%
% Use as
%   ft_singleplotER(cfg, data)
% or
%   ft_singleplotER(cfg, data1, data2, ..., datan)
%
% The data can be an erp/erf produced by FT_TIMELOCKANALYSIS, a power
% spectrum produced by FT_FREQANALYSIS or connectivity spectrum produced by
% FT_CONNECTIVITYANALYSIS.
%
% The configuration can have the following parameters:
%   cfg.parameter     = field to be plotted on y-axis, for example 'avg', 'powspctrm' or 'cohspctrm' (default is automatic)
%   cfg.maskparameter = field in the first dataset to be used for masking of data; this is not supported when
%                       computing the mean over multiple channels, or when giving multiple input datasets (default = [])
%   cfg.maskstyle     = style used for masking of data, 'box', 'thickness' or 'saturation' (default = 'box')
%   cfg.maskfacealpha = mask transparency value between 0 and 1
%   cfg.xlim          = 'maxmin' or [xmin xmax] (default = 'maxmin')
%   cfg.ylim          = 'maxmin', 'maxabs', 'zeromax', 'minzero', or [ymin ymax] (default = 'maxmin')
%   cfg.channel       = Nx1 cell-array with selection of channels (default = 'all'), see FT_CHANNELSELECTION for details
%   cfg.title         = string, title of plot
%   cfg.showlegend    = 'yes' or 'no', show the legend with the colors (default = 'no')
%   cfg.refchannel    = name of reference channel for visualising connectivity, can be 'gui'
%   cfg.baseline      = 'yes', 'no' or [time1 time2] (default = 'no'), see ft_timelockbaseline
%   cfg.baselinetype  = 'absolute' or 'relative' (default = 'absolute')
%   cfg.trials        = 'all' or a selection given as a 1xn vector (default = 'all')
%   cfg.fontsize      = font size of title (default = 8)
%   cfg.hotkeys       = enables hotkeys (leftarrow/rightarrow/uparrow/downarrow/m) for dynamic zoom and translation (ctrl+) of the axes
%   cfg.interactive   = interactive plot 'yes' or 'no' (default = 'yes')
%                       in a interactive plot you can select areas and produce a new
%                       interactive plot when a selected area is clicked. multiple areas
%                       can be selected by holding down the shift key.
%   cfg.figure        = 'yes' or 'no', whether to open a new figure. You can also specify a figure handle from FIGURE, GCF or SUBPLOT. (default = 'yes')
%   cfg.position      = location and size of the figure, specified as [left bottom width height] (default is automatic)
%   cfg.renderer      = string, 'opengl', 'zbuffer', 'painters', see RENDERERINFO (default is automatic, try 'painters' when it crashes)
%   cfg.linestyle     = linestyle/marker type, see options of the PLOT function (default = '-')
%                       can be a single style for all datasets, or a cell-array containing one style for each dataset
%   cfg.linewidth     = linewidth in points (default = 0.5)
%   cfg.linecolor     = color(s) used for plotting the dataset(s). The default is defined in LINEATTRIBUTES_COMMON, see
%                       the help of this function for more information
%   cfg.directionality = '', 'inflow' or 'outflow' specifies for
%                       connectivity measures whether the inflow into a
%                       node, or the outflow from a node is plotted. The
%                       (default) behavior of this option depends on the dimor
%                       of the input data (see below).
%   cfg.select        = 'intersect' or 'union' (default = 'intersect')
%                       with multiple input arguments determines the
%                       pre-selection of the data that is considered for
%                       plotting.
%   cfg.showlocations = 'no' (default), or 'yes'. plot a small spatial layout of all sensors, highlighting the specified subset
%   cfg.layouttopo    = filename, or struct (see FT_PREPARE_LAYOUT) used for showing the locations with cfg.showlocations = 'yes'
%
% The following options for the scaling of the EEG, EOG, ECG, EMG, MEG and NIRS channels
% is optional and can be used to bring the absolute numbers of the different
% channel types in the same range (e.g. fT and uV). The channel types are determined
% from the input data using FT_CHANNELSELECTION.
%   cfg.eegscale       = number, scaling to apply to the EEG channels prior to display
%   cfg.eogscale       = number, scaling to apply to the EOG channels prior to display
%   cfg.ecgscale       = number, scaling to apply to the ECG channels prior to display
%   cfg.emgscale       = number, scaling to apply to the EMG channels prior to display
%   cfg.megscale       = number, scaling to apply to the MEG channels prior to display
%   cfg.gradscale      = number, scaling to apply to the MEG gradiometer channels prior to display (in addition to the cfg.megscale factor)
%   cfg.magscale       = number, scaling to apply to the MEG magnetometer channels prior to display (in addition to the cfg.megscale factor)
%   cfg.nirsscale      = number, scaling to apply to the NIRS channels prior to display
%   cfg.mychanscale    = number, scaling to apply to the channels specified in cfg.mychan
%   cfg.mychan         = Nx1 cell-array with selection of channels
%   cfg.chanscale      = Nx1 vector with scaling factors, one per channel specified in cfg.channel
%
% For the plotting of directional connectivity data the cfg.directionality
% option determines what is plotted. The default value and the supported
% functionality depend on the dimord of the input data. If the input data
% is of dimord 'chan_chan_XXX', the value of directionality determines
% whether, given the reference channel(s), the columns (inflow), or rows
% (outflow) are selected for plotting. In this situation the default is
% 'inflow'. Note that for undirected measures, inflow and outflow should
% give the same output. If the input data is of dimord 'chancmb_XXX', the
% value of directionality determines whether the rows in data.labelcmb are
% selected. With 'inflow' the rows are selected if the refchannel(s) occur in
% the right column, with 'outflow' the rows are selected if the
% refchannel(s) occur in the left column of the labelcmb-field. Default in
% this case is '', which means that all rows are selected in which the
% refchannel(s) occur. This is to robustly support linearly indexed
% undirected connectivity metrics. In the situation where undirected
% connectivity measures are linearly indexed, specifying 'inflow' or
% 'outflow' can result in unexpected behavior.
%
% to facilitate data-handling and distributed computing you can use
%   cfg.inputfile   =  ...
% if you specify this option the input data will be read from a *.mat
% file on disk. this mat files should contain only a single variable named 'data',
% corresponding to the input structure.
%
% See also FT_SINGLEPLOTTFR, FT_MULTIPLOTER, FT_MULTIPLOTTFR, FT_TOPOPLOTER, FT_TOPOPLOTTFR

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

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% DEVELOPERS NOTE: This code is organized in a similar fashion for multiplot/singleplot/topoplot
% and for ER/TFR and should remain consistent over those 6 functions.
% Section 1: general cfg handling that is independent from the data
% Section 2: data handling, this also includes converting bivariate (chan_chan and chancmb) into univariate data
% Section 3: select the data to be plotted and determine min/max range
% Section 4: do the actual plotting
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Section 1: general cfg handling that is independent from the data

% these are used by the ft_preamble/ft_postamble function and scripts
ft_revision = '$Id$';
ft_nargin   = nargin;
ft_nargout  = nargout;

% do the general setup of the function
ft_defaults
ft_preamble init
ft_preamble debug
ft_preamble loadvar varargin
ft_preamble provenance varargin

% the ft_abort variable is set to true or false in ft_preamble_init
if ft_abort
  return
end

Ndata = numel(varargin);
for i=1:Ndata
  % check if the input data is valid for this function
  varargin{i} = ft_checkdata(varargin{i}, 'datatype', {'timelock', 'freq'});
end

% check if the input cfg is valid for this function
cfg = ft_checkconfig(cfg, 'forbidden',  {'channels', 'trial'}); % prevent accidental typos, see issue 1729
cfg = ft_checkconfig(cfg, 'unused',     {'cohtargetchannel'});
cfg = ft_checkconfig(cfg, 'renamedval', {'zlim', 'absmax', 'maxabs'});
cfg = ft_checkconfig(cfg, 'renamedval', {'directionality', 'feedforward', 'outflow'});
cfg = ft_checkconfig(cfg, 'renamedval', {'directionality', 'feedback',    'inflow'});
cfg = ft_checkconfig(cfg, 'renamed',    {'matrixside',     'directionality'});
cfg = ft_checkconfig(cfg, 'renamed',    {'channelindex',   'channel'});
cfg = ft_checkconfig(cfg, 'renamed',    {'channelname',    'channel'});
cfg = ft_checkconfig(cfg, 'renamed',    {'cohrefchannel',  'refchannel'});
cfg = ft_checkconfig(cfg, 'renamed',	  {'zparam',         'parameter'});
cfg = ft_checkconfig(cfg, 'renamed',    {'graphcolor',     'linecolor'});
cfg = ft_checkconfig(cfg, 'deprecated', {'xparam'});
cfg = ft_checkconfig(cfg, 'renamed',    {'newfigure',      'figure'});

% set the defaults
cfg.baseline        = ft_getopt(cfg, 'baseline',      'no');
cfg.trials          = ft_getopt(cfg, 'trials',        'all', 1);
cfg.xlim            = ft_getopt(cfg, 'xlim',          'maxmin');
cfg.ylim            = ft_getopt(cfg, 'ylim',          'maxmin');
cfg.zlim            = ft_getopt(cfg, 'zlim',          'maxmin');
cfg.comment         = ft_getopt(cfg, 'comment',        strcat([date '\n']));
cfg.axes            = ft_getopt(cfg, ' axes',         'yes');
cfg.fontsize        = ft_getopt(cfg, 'fontsize',       8);
cfg.interpreter     = ft_getopt(cfg, 'interpreter',   'none');  % none, tex or latex
cfg.hotkeys         = ft_getopt(cfg, 'hotkeys',       'yes');
cfg.interactive     = ft_getopt(cfg, 'interactive',   'yes');
cfg.maskparameter   = ft_getopt(cfg, 'maskparameter',  []);
cfg.colorgroups     = ft_getopt(cfg, 'colorgroups',   'condition'); % this is the only supported option
cfg.linecolor       = ft_getopt(cfg, 'linecolor',     []);
cfg.linestyle       = ft_getopt(cfg, 'linestyle',     '-');
cfg.linewidth       = ft_getopt(cfg, 'linewidth',      0.5);
cfg.maskstyle       = ft_getopt(cfg, 'maskstyle',     'box');
cfg.maskfacealpha   = ft_getopt(cfg, 'maskfacealpha', 1);
cfg.channel         = ft_getopt(cfg, 'channel',       'all');
cfg.title           = ft_getopt(cfg, 'title',          []);
cfg.directionality  = ft_getopt(cfg, 'directionality', []);
cfg.figurename      = ft_getopt(cfg, 'figurename',     []);
cfg.preproc         = ft_getopt(cfg, 'preproc',        []);
cfg.frequency       = ft_getopt(cfg, 'frequency',     'all'); % needed for frequency selection with TFR data
cfg.latency         = ft_getopt(cfg, 'latency',       'all'); % needed for latency selection with TFR data, FIXME, probably not used
cfg.showlegend      = ft_getopt(cfg, 'showlegend',    'no');
cfg.renderer        = ft_getopt(cfg, 'renderer',       []); % let MATLAB decide on the default
cfg.select          = ft_getopt(cfg, 'select',         'intersect'); % for ft_selectdata
cfg.showlocations   = ft_getopt(cfg, 'showlocations',  'no');
cfg.layouttopo      = ft_getopt(cfg, 'layouttopo');

% this is needed for the figure title and correct labeling of linecolor later on
if isfield(cfg, 'dataname') && ~isempty(cfg.dataname)
  dataname = cfg.dataname;
elseif isfield(cfg, 'inputfile') && ~isempty(cfg.inputfile)
  dataname = cfg.inputfile;
elseif nargin>1
  dataname = arrayfun(@inputname, 2:nargin, 'UniformOutput', false);
else
  dataname = {};
end

%% Section 2: data handling, this also includes converting bivariate (chan_chan and chancmb) into univariate data

for i=1:Ndata
  dtype{i}    = ft_datatype(varargin{i});
  hastime(i)  = isfield(varargin{i}, 'time');
  hasfreq(i)  = isfield(varargin{i}, 'freq');
end

% check if the input has consistent datatypes
if ~all(strcmp(dtype, dtype{1})) || ~all(hastime==hastime(1)) || ~all(hasfreq==hasfreq(1))
  ft_error('different datatypes are not allowed as input');
else
  dtype   = dtype{1};
  hastime = hastime(1);
  hasfreq = hasfreq(1);
end

% Set x/y/parameter according to datatype and dimord
switch dtype
  case 'timelock'
    xparam = 'time';
    if isfield(varargin{1}, 'trial')
      cfg.parameter = ft_getopt(cfg, 'parameter', 'trial');
    elseif isfield(varargin{1}, 'individual')
      cfg.parameter = ft_getopt(cfg, 'parameter', 'individual');
    elseif isfield(varargin{1}, 'avg')
      cfg.parameter = ft_getopt(cfg, 'parameter', 'avg');
    end
  case 'freq'
    if hastime && hasfreq
      xparam = 'time';   % average over selected frequencies
    else
      xparam = 'freq';
    end
    cfg.parameter = ft_getopt(cfg, 'parameter', 'powspctrm');
  case 'comp'
    % not supported
  otherwise
    % not supported
end

% check whether rpt/subj is present and remove if necessary
dimord = getdimord(varargin{1}, cfg.parameter);
dimtok = tokenize(dimord, '_');
hasrpt = any(ismember(dimtok, {'rpt' 'subj'}));

if ~hasrpt
  assert(isequal(cfg.trials, 'all') || isequal(cfg.trials, 1), 'incorrect specification of cfg.trials for data without repetitions');
else
  assert(~isempty(cfg.trials), 'empty specification of cfg.trials for data with repetitions');
end

% parse cfg.channel
if isfield(cfg, 'channel') && isfield(varargin{1}, 'label')
  cfg.channel = ft_channelselection(cfg.channel, varargin{1}.label);
elseif isfield(cfg, 'channel') && isfield(varargin{1}, 'labelcmb')
  cfg.channel = ft_channelselection(cfg.channel, unique(varargin{1}.labelcmb(:)));
end

% apply baseline correction
if ~strcmp(cfg.baseline, 'no')
  tmpcfg = keepfields(cfg, {'baseline', 'baselinetype', 'baselinewindow', 'demean', 'parameter', 'channel'});
  for i=1:Ndata
    % keep mask-parameter if it is set
    if ~isempty(cfg.maskparameter)
      tempmask = varargin{i}.(cfg.maskparameter);
    end
    if strcmp(dtype, 'timelock') && strcmp(xparam, 'time')
      varargin{i} = ft_timelockbaseline(tmpcfg, varargin{i});
    elseif strcmp(dtype, 'freq') && strcmp(xparam, 'time')
      varargin{i} = ft_freqbaseline(tmpcfg, varargin{i});
    elseif strcmp(dtype, 'freq') && strcmp(xparam, 'freq')
      ft_error('baseline correction is not supported for spectra without a time dimension');
    else
      ft_warning('baseline correction not applied, please set xparam');
    end
    % put mask-parameter back if it is set
    if ~isempty(cfg.maskparameter)
      varargin{i}.(cfg.maskparameter) = tempmask;
    end
  end
end

% channels should NOT be selected and averaged here, since a topoplot might follow in interactive mode
tmpcfg = keepfields(cfg, {'trials', 'select', 'showcallinfo', 'trackcallinfo', 'trackusage', 'trackdatainfo', 'trackmeminfo', 'tracktimeinfo', 'checksize'});
if hasrpt
  tmpcfg.avgoverrpt = 'yes';
else
  tmpcfg.avgoverrpt = 'no';
end
if hastime && hasfreq
  tmpcfg.avgoverfreq = 'yes';       % average over selected frequencies
  tmpcfg.frequency = cfg.frequency; % not to be confused with cfg.xlim or cfg.ylim
  tmpcfg.keepfreqdim = 'no';
else
  tmpcfg.avgoverfreq = 'no';
end
tmpvar = varargin{1};
[varargin{:}] = ft_selectdata(tmpcfg, varargin{:});
% restore the provenance information and put back cfg.channel
tmpchannel  = cfg.channel;
[cfg, varargin{:}] = rollback_provenance(cfg, varargin{:});
cfg.channel = tmpchannel;

if isfield(tmpvar, cfg.maskparameter) && ~isfield(varargin{1}, cfg.maskparameter)
  % the mask parameter is not present after ft_selectdata, because it is
  % not included in all input arguments. Make the same selection and copy
  % it over
  tmpvar = ft_selectdata(tmpcfg, tmpvar);
  varargin{1}.(cfg.maskparameter) = tmpvar.(cfg.maskparameter);
end

clear tmpvar tmpcfg dimord dimtok hastime hasfreq hasrpt

% ensure that the preproc specific options are located in the cfg.preproc
% substructure, but also ensure that the field 'refchannel' remains at the
% highest level in the structure. This is a little hack by JM because the field
% refchannel can relate to connectivity or to an EEg reference.

if isfield(cfg, 'refchannel'), refchannelincfg = cfg.refchannel; cfg = rmfield(cfg, 'refchannel'); end
cfg = ft_checkconfig(cfg, 'createsubcfg',  {'preproc'});
if exist('refchannelincfg', 'var'), cfg.refchannel  = refchannelincfg; end

if ~isempty(cfg.preproc)
  % preprocess the data, i.e. apply filtering, baselinecorrection, etc.
  fprintf('applying preprocessing options\n');
  if ~isfield(cfg.preproc, 'feedback')
    cfg.preproc.feedback = cfg.interactive;
  end
  for i=1:Ndata
    varargin{i} = ft_preprocessing(cfg.preproc, varargin{i});
  end
end

% Handle the bivariate case
dimord = getdimord(varargin{1}, cfg.parameter);
if startsWith(dimord, 'chan_chan_') || startsWith(dimord, 'chancmb_')
  % convert the bivariate data to univariate and call this plotting function again
  cfg.originalfunction = 'ft_singleplotER';
  cfg.trials = 'all'; % trial selection has been taken care off
  bivariate_common(cfg, varargin{:});
  return
end

% Apply channel-type specific scaling
fn = fieldnames(cfg);
fn = setdiff(fn, {'skipscale', 'showscale', 'gridscale'}); % these are for the layout and plotting, not for CHANSCALE_COMMON
fn = fn(endsWith(fn, 'scale') | startsWith(fn, 'mychan') | strcmp(fn, 'channel') | strcmp(fn, 'parameter'));
tmpcfg = keepfields(cfg, fn);
if ~isempty(tmpcfg)
  for i=1:Ndata
    varargin{i} = chanscale_common(tmpcfg, varargin{i});
  end
  % remove the scaling fields from the configuration, to prevent them from being called again in interactive mode
  % but keep the parameter and channel field
  cfg = removefields(cfg, setdiff(fn, {'parameter', 'channel'}));
else
  % do nothing
end

%% Section 3: select the data to be plotted and determine min/max range

if istrue(cfg.showlocations)
  % Read or create the layout that will be used for plotting, if specified
  tmpcfg = keepfields(cfg, {'rows', 'columns', 'commentpos', 'scalepos', 'projection', 'viewpoint', 'rotate', 'width', 'height', 'elec', 'grad', 'opto', 'layouttopo', 'showcallinfo', 'trackcallinfo', 'trackusage', 'trackdatainfo', 'trackmeminfo', 'tracktimeinfo', 'checksize'});
  tmpcfg.skipcomnt = 'yes';
  tmpcfg.skipscale = 'yes';
  tmpcfg.pointcolor = cfg.linecolor; % switch of name for ft_prepare_layout
  if ~isempty(cfg.layouttopo)
    tmpcfg.layout = cfg.layouttopo;
  elseif isfield(cfg, 'layout') && ~isempty(cfg.layout)
    tmpcfg.layout = cfg.layout;
  else
    ft_warning('no explicit layout specified, attempting to create one from the data');
  end
  cfg.layouttopo = ft_prepare_layout(tmpcfg, varargin{1});
end

% Take the desided subselection of channels, this is the same in all datasets
[selchan] = match_str(varargin{1}.label, cfg.channel);

% Get physical min/max range of x, i.e. time or frequency
if strcmp(cfg.xlim, 'maxmin')
  % Find maxmin throughout all varargins:
  xmin = [];
  xmax = [];
  for i=1:Ndata
    xmin = min([xmin varargin{i}.(xparam)]);
    xmax = max([xmax varargin{i}.(xparam)]);
  end
else
  xmin = cfg.xlim(1);
  xmax = cfg.xlim(2);
end

% Get the index of the nearest bin, this is the same in all datasets
xminindx = nearest(varargin{1}.(xparam), xmin);
xmaxindx = nearest(varargin{1}.(xparam), xmax);
xmin = varargin{1}.(xparam)(xminindx);
xmax = varargin{1}.(xparam)(xmaxindx);
selx = xminindx:xmaxindx;
xval = varargin{1}.(xparam)(selx);

% get physical y-axis range, i.e. parameter to be plotted
if ~isnumeric(cfg.ylim)
  % find maxmin throughout all varargins
  ymin = +inf;
  ymax = -inf;
  for i=1:Ndata
    % select the channels in the data that match with the layout and that are selected for plotting
    dat = nanmean(varargin{i}.(cfg.parameter)(selchan, selx), 1); % mean over channels

    ymin = min(ymin, min(dat(:)));
    ymax = max(ymax, max(dat(:)));
  end
  switch cfg.ylim
    case 'maxmin'
      % keep them as they are
    case 'maxabs'
      ymax = max(abs(ymax), abs(ymin));
      ymin = -ymax;
    case 'zeromax'
      ymin = 0;
    case 'minzero'
      ymax = 0;
    otherwise
      ft_error('invalid specification of cfg.ylim');
  end
else
  ymin = cfg.ylim(1);
  ymax = cfg.ylim(2);
end

% gather the data from all input data structures
datamatrix = zeros(Ndata, length(selx));
for i=1:Ndata
  datamatrix(i,:) = mean(varargin{i}.(cfg.parameter)(selchan, selx), 1); % mean over channels
end

% gather the mask from the first input data structure
if ~isempty(cfg.maskparameter)
  maskmatrix = mean(varargin{1}.(cfg.maskparameter)(selchan, selx), 1); % mean over channels
else
  % create an Nx0 matrix
  maskmatrix = zeros(length(selchan), 0);
end

%% Section 4: do the actual plotting

% determine the coloring of channels/conditions
[linecolor, linestyle, linewidth] = lineattributes_common(cfg, varargin{:});
linecolor = mean(linecolor(selchan, :, :), 1);
linestyle = linestyle(selchan(1), :);
linewidth = mean(linewidth(selchan, :), 1);

% open a new figure, or add it to the existing one
open_figure(keepfields(cfg, {'figure', 'position', 'visible', 'renderer', 'figurename', 'title'}));

yval = datamatrix;
mask = maskmatrix;

if strcmp(cfg.maskstyle, 'difference')
  % combine the conditions in a single plot, highlight the difference
  ft_plot_vector(xval, yval, 'color', permute(linecolor, [3 2 1]), 'style', linestyle(1,:), 'linewidth', linewidth(1,:), 'highlight', mask, 'highlightstyle', cfg.maskstyle, 'hlim', [xmin xmax], 'vlim', [ymin ymax], 'facealpha', cfg.maskfacealpha);
else
  % loop over the conditions, plot them on top of each other
  for i=1:Ndata
    ft_plot_vector(xval, yval(i,:), 'color', linecolor(1,:,i), 'style', linestyle{1,i}, 'linewidth', linewidth(1,i), 'highlight', mask, 'highlightstyle', cfg.maskstyle, 'hlim', [xmin xmax], 'vlim', [ymin ymax], 'facealpha', cfg.maskfacealpha);
  end
end

if ischar(linecolor)
  set(gca, 'ColorOrder', char2rgb(linecolor))
elseif isnumeric(linecolor)
  set(gca, 'ColorOrder', shiftdim(linecolor(1,:,:),1)');
end

% show the legend with the colors of the conditions
if istrue(cfg.showlegend) && Ndata>1
  if strcmp(cfg.maskstyle, 'difference')
    colorLabels = {'difference'};
  else
    colorLabels = {};
  end
  for i=1:Ndata
    if ischar(linecolor)
      colorLabels{end+1} = [dataname{i} '='         linecolor(i)     ];
    elseif isnumeric(linecolor)
      colorLabels{end+1} = [dataname{i} '=' num2str(linecolor(1, :, i)) ];
    end
  end
  legend(colorLabels)
end

% set xlim and ylim
if xmin~=xmax
  xlim([xmin xmax]);
end
if ymin~=ymax
  ylim([ymin ymax]);
end

% adjust mask box extents to ymin/ymax
if ~isempty(cfg.maskparameter)
  ptchs = findobj(gcf, 'type', 'patch');
  for i = 1:length(ptchs)
    YData = get(ptchs(i), 'YData');
    YData(YData == min(YData)) = ymin;
    YData(YData == max(YData)) = ymax;
    set(ptchs(i), 'YData',YData);
  end
end

% Set callback to adjust axes
if strcmp('yes', cfg.hotkeys)
  %  attach data and cfg to figure and attach a key listener to the figure
  set(gcf, 'KeyPressFcn', {@key_sub, xmin, xmax, ymin, ymax})
end

% Create axis title containing channel name(s) and channel number(s):
if ~isempty(cfg.title)
  t = cfg.title;
else
  if length(cfg.channel) == 1
    t = [char(cfg.channel) ' / ' num2str(selchan) ];
  else
    t = sprintf('mean(%0s)', join_str(', ', cfg.channel));
  end
end
title(t, 'fontsize', cfg.fontsize, 'interpreter', cfg.interpreter);

% set the figure window title, add channel labels if number is small
if isempty(get(gcf, 'Name'))
  if length(selchan) < 5
    chans = join_str(', ', cfg.channel);
  else
    chans = '<multiple channels>';
  end
  if ~isempty(cfg.figurename)
    set(gcf, 'name', cfg.figurename);
    set(gcf, 'NumberTitle', 'off');
  elseif ~isempty(dataname)
    set(gcf, 'Name', sprintf('%d: %s: %s (%s)', double(gcf), mfilename, join_str(', ', dataname), chans));
    set(gcf, 'NumberTitle', 'off');
  else
    set(gcf, 'Name', sprintf('%d: %s (%s)', double(gcf), mfilename, chans));
    set(gcf, 'NumberTitle', 'off');
  end
end

if istrue(cfg.showlocations)
  hpos = xmin+(xmax-xmin)*0.1;
  vpos = ymin+(ymax-ymin)*0.9;
  h    = 0.2*(ymax-ymin);
  w    = 0.2*(xmax-xmin);
  pointcolor  = zeros(numel(cfg.layouttopo.label),3);
  pointsize   = ones(numel(cfg.layouttopo.label),2);
  pointsize(selchan) = 4;
  pointsymbol = 'o';
  ft_plot_layout(cfg.layouttopo, 'box', 'no', 'label', 'off', 'pointsize', pointsize, 'pointcolor', pointcolor, 'pointsymbol', pointsymbol, 'hpos', hpos, 'vpos', vpos, 'width', w, 'height', h);
end

% make the figure interactive
if strcmp(cfg.interactive, 'yes')
  % add the cfg/data/channel information to the figure under identifier linked to this axis
  ident                  = ['axh' num2str(round(sum(clock.*1e6)))]; % unique identifier for this axis
  set(gca, 'tag', ident);
  info                   = guidata(gcf);
  info.(ident).cfg       = cfg;
  info.(ident).varargin  = varargin;
  info.(ident).dataname  = dataname;
  if exist('linecolor', 'var')
    info.(ident).linecolor   = linecolor;
  end
  guidata(gcf, info);
  set(gcf, 'windowbuttonupfcn',     {@ft_select_range, 'multiple', false, 'yrange', false, 'callback', {@select_topoplotER}, 'event', 'windowbuttonupfcn'});
  set(gcf, 'windowbuttondownfcn',   {@ft_select_range, 'multiple', false, 'yrange', false, 'callback', {@select_topoplotER}, 'event', 'windowbuttondownfcn'});
  set(gcf, 'windowbuttonmotionfcn', {@ft_select_range, 'multiple', false, 'yrange', false, 'callback', {@select_topoplotER}, 'event', 'windowbuttonmotionfcn'});
end

% do the general cleanup and bookkeeping at the end of the function
ft_postamble debug
ft_postamble previous varargin
ft_postamble provenance
ft_postamble savefig

% add a menu to the figure, but only if the current figure does not have subplots
menu_fieldtrip(gcf, cfg, false);

if ~ft_nargout
  % don't return anything
  clear cfg
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTION which is called after selecting a time range
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function select_topoplotER(range, varargin)

% fetch cfg/data based on axis indentifier given as tag
ident    = get(gca, 'tag');
info     = guidata(gcf);
cfg      = info.(ident).cfg;
varargin = info.(ident).varargin;
if ~isempty(range)
  cfg = removefields(cfg, 'inputfile');   % the reading has already been done and varargin contains the data
  cfg = removefields(cfg, 'showlabels');  % this is not allowed in topoplotER
  cfg.baseline = 'no';                    % make sure the next function does not apply a baseline correction again
  cfg.dataname = info.(ident).dataname;   % put data name in here, this cannot be resolved by other means
  cfg.channel = 'all';                    % make sure the topo displays all channels, not just the ones in this singleplot
  cfg.comment = 'auto';
  cfg.trials = 'all';                     % trial selection has already been taken care of
  cfg.xlim = range(1:2);
  % if user specified a ylim, copy it over to the zlim of topoplot
  if isfield(cfg, 'ylim')
    cfg.zlim = cfg.ylim;
    cfg = rmfield(cfg, 'ylim');
  end
  fprintf('selected cfg.xlim = [%f %f]\n', cfg.xlim(1), cfg.xlim(2));
  % ensure that the new figure appears at the same position
  cfg.figure = 'yes';
  cfg.position = get(gcf, 'Position');
  ft_topoplotER(cfg, varargin{:});
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTION which handles hot keys in the current plot
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function key_sub(handle, eventdata, varargin)
xlimits = xlim;
ylimits = ylim;
incr_x = abs(xlimits(2) - xlimits(1)) /10;
incr_y = abs(ylimits(2) - ylimits(1)) /10;

if length(eventdata.Modifier) == 1 && strcmp(eventdata.Modifier{:}, 'control')
  % TRANSLATE by 10%
  switch eventdata.Key
    case 'leftarrow'
      xlim([xlimits(1)+incr_x xlimits(2)+incr_x])
    case 'rightarrow'
      xlim([xlimits(1)-incr_x xlimits(2)-incr_x])
    case 'uparrow'
      ylim([ylimits(1)-incr_y ylimits(2)-incr_y])
    case 'downarrow'
      ylim([ylimits(1)+incr_y ylimits(2)+incr_y])
  end % switch
else
  % ZOOM by 10%
  switch eventdata.Key
    case 'leftarrow'
      xlim([xlimits(1)-incr_x xlimits(2)+incr_x])
    case 'rightarrow'
      xlim([xlimits(1)+incr_x xlimits(2)-incr_x])
    case 'uparrow'
      ylim([ylimits(1)-incr_y ylimits(2)+incr_y])
    case 'downarrow'
      ylim([ylimits(1)+incr_y ylimits(2)-incr_y])
    case 'm'
      xlim([varargin{1} varargin{2}])
      ylim([varargin{3} varargin{4}])
  end % switch
end % if


%%*****************************************************************
%% sqlpmisc:
%% unscale and produce infeasibility certificates if appropriate
%%*****************************************************************
%% SDPT3: version 4.0
%% Copyright (c) 1997 by
%% Kim-Chuan Toh, Michael J. Todd, Reha H. Tutuncu
%% Last Modified: 16 Sep 2004
%%*****************************************************************

   function [X,y,Z,termcode,resid,reldist,msg] = sqlpmisc(blk,At,C,b,X,y,Z,permZ,param);

   termcode    = param.termcode;
   iter        = param.iter;
   obj         = param.obj;
   relgap      = param.relgap;
   prim_infeas = param.prim_infeas;
   dual_infeas = param.dual_infeas;
   homRd       = param.homRd;
   homrp       = param.homrp;
   AX          = param.AX;
   ZpATynorm   = param.ZpATynorm;
   m0          = param.m0;
   indeprows   = param.indeprows;
   normX0      = param.normX0;
   normZ0      = param.normZ0;
   inftol      = param.inftol;
   maxit       = param.maxit;
   scale_data  = param.scale_data;
   printlevel  = param.printlevel;
%%
   resid = []; reldist = []; msg = [];
   if (scale_data)
      normA = param.normA; normC = param.normC; normb = param.normb;
   else
      normA = 1; normC = 1; normb = 1;
   end
   Anorm = ops(At,'norm'); xnorm = ops(X,'norm'); ynorm = norm(y);
   infeas = max(prim_infeas,dual_infeas);
%%
   if (iter >= maxit)
      termcode = -6;
      msg = 'sqlp stop: maximum number of iterations reached';
      if (printlevel); fprintf('\n  %s',msg); end
   end
   if (termcode <= 0)
      %%
      %% To detect near-infeasibility when the algorithm provides
      %% a "better" certificate of infeasibility than of optimality.
      %%
      err = max(infeas,relgap);
      iflag = 0;
      if (obj(2) > 0)
         if (homRd < 0.1*sqrt(err*inftol))
            iflag = 1;
            msg = sprintf('prim_inf,dual_inf,relgap = %3.2e, %3.2e, %3.2e',...
		  prim_infeas,dual_infeas,relgap);
            if (printlevel); fprintf('\n  %s',msg); end
            termcode = 1;
         end
      end
      if (obj(1) < 0)
         if (homrp < 0.1*sqrt(err*inftol))
            iflag = 1;
            msg = sprintf('prim_inf,dual_inf,relgap = %3.2e, %3.2e, %3.2e',...
                  prim_infeas,dual_infeas,relgap);
            if (printlevel); fprintf('\n  %s',msg); end
            termcode = 2;
         end
      end
      if (iflag == 0)
         if (scale_data == 1)
            X = ops(ops(X,'./',normA),'*',normb);
            y = y*normC;
            Z = ops(ops(Z,'.*',normA),'*',normC);
         end
      end
   end
   if (termcode == 1) & (iter > 3)
      msg = 'sqlp stop: primal problem is suspected of being infeasible';
      if (printlevel); fprintf('\n  %s',msg); end
      if (scale_data == 1)
         X = ops(X,'./',normA); b = b*normb;
      end
      rby = 1/(b'*y); y = rby*y; Z = ops(Z,'*',rby);
      resid = ZpATynorm * rby;
      reldist = ZpATynorm/(Anorm*ynorm);
   end
   if (termcode == 2) & (iter > 3)
      msg = 'sqlp stop: dual problem is suspected of being infeasible';
      if (printlevel); fprintf('\n  %s',msg); end
      if (scale_data == 1)
         C = ops(C,'.*',normC);
         Z = ops(Z,'.*',normA);
      end
      tCX = blktrace(blk,C,X);
      X = ops(X,'*',1/(-tCX));
      resid = norm(AX)/(-tCX);
      reldist = norm(AX)/(Anorm*xnorm);
   end
   if (termcode == 3)
      maxblowup = max(ops(X,'norm')/normX0,ops(Z,'norm')/normZ0);
      msg = sprintf('sqlp stop: primal or dual is diverging, %3.1e',maxblowup);
      if (printlevel); fprintf('\n  %s',msg); end
   end
   [X,Z] = unperm(blk,permZ,X,Z);
   if ~isempty(indeprows)
      ytmp = zeros(m0,1);
      ytmp(indeprows) = y;
      y = ytmp;
   end
%%*****************************************************************************
%% unperm: undo the permutations applied in validate.
%%
%% [X,Z] = unperm(blk,permZ,X,Z);
%%
%% undoes the permutation introduced in validate.
%%*****************************************************************************

  function [X,Z] = unperm(blk,permZ,X,Z);
%%
  for p = 1:size(blk,1)
     if (strcmp(blk{p,1},'s') & ~isempty(permZ{p}))
        per = permZ{p};
        X{p} = X{p}(per,per);
        Z{p} = Z{p}(per,per);
     end
  end
%%*****************************************************************************


function SO3F = ctranspose(SO3F)
% overloads ctranspose
%
% Syntax
%   SO3F'
%

SO3F = conj(SO3F.');

end


function vw = wangAtlasToROIs(vw, wangAtlasNifti)
%
% Converts Wang Atlas from freesurfer MGZ volume to vistasoft ROIs
%
% Example
%   fsID = 'ernie';
%

hideGrayROIs = viewGet(vw, 'hide gray ROIs');
vw = viewSet(vw, 'hide Gray ROIs', true);

Wang_ROI_Names = {...
    'V1v' 'V1d' 'V2v' 'V2d' 'V3v' 'V3d' 'hV4' 'VO1' 'VO2' 'PHC1' 'PHC2' ...
    'TO2' 'TO1' 'LO2' 'LO1' 'V3B' 'V3A' 'IPS0' 'IPS1' 'IPS2' 'IPS3' 'IPS4' ...
    'IPS5' 'SPL1' 'FEF'};

wangComments = 'ROI made based on maximum probabilty map from Wang et al, 2014 ''Probabilistic Maps of Visual Topography in Human Cortex''';

% count the current number of ROIs
nROIs = length(viewGet(vw, 'ROIs'));

% create new ROIs from atlas
vw = nifti2ROI(vw, wangAtlasNifti);

% how many new ROIs did we get?
numNewROIs = length(viewGet(vw, 'ROIs')) - nROIs;
assert(numNewROIs>0)

for jj = 1:numNewROIs
    this_roi       = viewGet(vw, 'ROI name', nROIs + jj);
    this_roi_num   = str2double(this_roi(regexp(this_roi, '[0-9]')));
    this_roi_name  = sprintf('WangAtlas_%s', Wang_ROI_Names{this_roi_num});
    vw             = viewSet(vw, 'ROI Name', this_roi_name, nROIs + jj);
    comments       = viewGet(vw, 'ROI comments', nROIs + jj);
    comments       = sprintf('%s\n%s', comments, wangComments);
    vw             = viewSet(vw, 'ROI comments', comments, nROIs + jj);
end

vw = viewSet(vw, 'hide Gray ROIs', hideGrayROIs);

return
%
%
% colors = jet(25);
%
% colors = colors(randperm(25),:)
%
% for ii = 1:length(vw.ROIs); vw.ROIs(ii).color = colors(ii,:); end


function sfc_pres_temp_rd ( )

%*****************************************************************************80
%
%% SFC_PRES_TEMP_RD reads pressure and temperature arrays from a NETCDF file.
%
%  Discussion:
%
%    We are reading 2D data, 6 x 12 lat-lon grids for pressure and temperature.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 December 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Russ Rew, Glenn Davis, Steve Emmerson, Harvey Davies, Ed Hartne,
%    The NETCDF User's Guide,
%    Unidata Program Center, March 2009.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'SFC_PRES_TEMP_RD:\n' );
  fprintf ( 1, '  MATLAB version.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Read 2D arrays of pressure and temperature\n' );
  fprintf ( 1, '  from a NETCDF file.\n' );
%
%  Open the file.
%
  nc_filename = 'sfc_pres_temp.nc';
  ncid = netcdf.open ( nc_filename, 'NOWRITE' );
%
%  There are a number of inquiry functions in NETCDF which can be
%  used to learn about an unknown NETCDF file.  INQ tells how many
%  NETCDF variables, dimensions, and global attributes are in the
%  file; also the dimension id of the unlimited dimension, if there
%  is one.
%
  [ ndims_in, nvars_in, ngatts_in, unlimdimid_in ] = netcdf.inq ( ncid );
%
%  In this case, we know that there are:
%    2 NETCDF dimensions,
%    4 NETCDF variables,
%    0 global attributes,
%    the unlimited dimension id is -1 (because there is no unlimited dimension).
%
  if ( ndims_in ~= 2 | ...
       nvars_in ~= 4 | ...
       ngatts_in ~= 0 | ...
       unlimdimid_in ~= -1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'SFC_PRES_TEMP_RD - Fatal error!\n' );
    fprintf ( 1, '  File has wrong properties.\n' );
    return
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The file properties are correct.\n' );
%
%  Get the varids of the latitude and longitude coordinate variables.
%
  lat_name = 'latitude';
  lat_varid = netcdf.inqVarid ( ncid, lat_name );

  lon_name = 'longitude';
  lon_varid = netcdf.inqVarid ( ncid, lon_name );
%
%  Read the latitude and longitude data.
%
  lats = netcdf.getVar ( ncid, lat_varid );
  lons = netcdf.getVar ( ncid, lon_varid );
%
%  Check to make sure we got what we expected.
%
  lat_num = 6;
  lat_start = 25.0;

  for lat = 1 : lat_num
    if (lats(lat) ~= lat_start + ( lat - 1 ) * 5.0 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'SFC_PRES_TEMP_RD - Fatal error!\n' );
      fprintf ( 1, '  LAT data is wrong.\n' );
    end
  end
  fprintf ( 1, '  The LAT data is correct.\n' );

  lon_num = 12;
  lon_start = -125.0;

  for lon = 1 : lon_num
    if (lons(lon) ~= lon_start + ( lon - 1 ) * 5.0 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'SFC_PRES_TEMP_RD - Fatal error!\n' );
      fprintf ( 1, '  LON data is wrong.\n' );
    end
  end
  fprintf ( 1, '  The LON data is correct.\n' );
%
%  Get the varids of the pressure and temperature variables.
%
  press_name = 'pressure';
  press_varid = netcdf.inqVarid ( ncid, press_name );
  temp_name = 'temperature';
  temp_varid = netcdf.inqVarid ( ncid, temp_name );
%
%  Read the pressure and temperature data.
%
  press = netcdf.getVar ( ncid, press_varid );
  temp = netcdf.getVar ( ncid, temp_varid );
%
%  Check the data. It should be the same as the data we wrote.
%
  sample_pressure = 900.0;
  sample_temp = 9.0;

  for lon = 1 : lon_num
    for lat = 1 : lat_num

      if ( press(lon,lat) ~= sample_pressure + ( lon - 1 ) * lat_num + ( lat - 1 ) )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'SFC_PRES_TEMP_RD - Fatal error!\n' );
        fprintf ( 1, '  PRESS data is wrong.\n' );
      end

      if ( temp(lon,lat) ~= sample_temp + 0.25 * ( ( lon - 1 ) * lat_num + ( lat - 1 ) ) )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'SFC_PRES_TEMP_RD - Fatal error!\n' );
        fprintf ( 1, '  TEMP data is wrong.\n' );
      end

    end
  end

  fprintf ( 1, '  The PRESS data is correct.\n' );
  fprintf ( 1, '  The TEMP data is correct.\n' );
%
%  Each of the NETCDF variables has a "units" attribute.
%  Let's read them and check them.
%
  units = 'units';

  lat_units = netcdf.getAtt ( ncid, lat_varid, units );
  if ( lat_units ~= 'degrees north' )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'SFC_PRES_TEMP_RD - Fatal error!\n' );
    fprintf ( 1, '  LAT units is wrong.\n' );
  end

  lon_units = netcdf.getAtt ( ncid, lon_varid, units );
  if ( lon_units ~= 'degrees east' )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'SFC_PRES_TEMP_RD - Fatal error!\n' );
    fprintf ( 1, '  LON units is wrong.\n' );
  end

  press_units = netcdf.getAtt ( ncid, press_varid, units );
  if ( press_units ~= 'hPa' )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'SFC_PRES_TEMP_RD - Fatal error!\n' );
    fprintf ( 1, '  PRESS units is wrong.\n' );
  end

  temp_units = netcdf.getAtt ( ncid, temp_varid, units );
  if ( temp_units ~= 'celsius' )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'SFC_PRES_TEMP_RD - Fatal error!\n' );
    fprintf ( 1, '  TEMP units is wrong.\n' );
  end

  fprintf ( 1, '  The units data is correct.\n' );
%
%  Close the file.
%
  netcdf.close ( ncid );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The data was read from the file "%s".\n', nc_filename );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'SFC_PRES_TEMP_RD:\n' );
  fprintf ( 1, '  Normal end of execution.\n' );

  return
end


% prtOptionsRvPlot contains available options for plotting RVs within the PRT
%
% Properties
%   nSamplesPerDim - 1x3 int array - number of samples to use for plotting
%       classifier confidence as a function of dimensionality [1D 2D 3D]
%       Default=[100 40 20]
%   colorMapFunction - a MATLAB colormap function
%
% Methods
%   Obj = prtOptionsRvPlot('paramName',paramVal,...) - Contructor
%

classdef prtOptionsRvPlot
    % Internal function
    % xxx Need Help xxx
    properties
        nSamplesPerDim = [100 40 20]; % Number of samples to use for plotting
        colorMapFunction = @(n)hot(n); % Two class colormap function handle
        nColorMapSamples = 256;
    end

    methods
        function obj = prtOptionsRvPlot(varargin)
            obj = prtUtilAssignStringValuePairs(obj,varargin{:});
        end
    end

%     methods
%         function obj = set.nSamplesPerDim(obj,val)
%             assert(length(val)==3,'largestMatrixSize must be a positive integer');
%
%             if val < 1e3
%                 warning('prt:prtOptionsComputation','Although valid, this value for largestMatrixSize is small. Consider using a larger value.')
%             end
%         end
%     end
end


function preds = predict_box(box, modelPath, saveConfmaps)
%PREDICT_BOX Evaluates model predictions on a stack of frames. Wrapper for predict_box.py.
% Usage:
%   preds = predict_box(box, modelPath)
%   preds = predict_box(box, modelPath, saveConfmaps)
%
% Args:
%   box: 4-D array or path to HDF5 file with '/box' dataset
%   modelPath: path to model weights
%   saveConfmaps: if true, returns full confidence maps in addition to
%                 peaks (default: false). Very slow and memory intensive!
%
% Returns:
%   preds: struct containing results from model prediction
%        .positions_pred: 3-D array of (parts x [X Y] x frames) indicating
%                         peak positions for each confidence map in image coordinates
%        .conf_pred: 2-D array of (parts x frames) with the confidence map
%                    value at the peak pixel for detecting bad predictions
%        .confmaps: 4-D array of confidence maps returned if saveConfmaps
%                   is set true

if nargin < 3 || isempty(saveConfmaps); saveConfmaps = false; end

% Process args
delete_box = false;
is_singleton = false;
if ischar(box)
    boxPath = box;
else
    boxPath = [tempname '.h5'];

    if numel(size(box)) < 4
        box = repmat(box,[1 1 1 2]);
        is_singleton = true;
    end

    h5save(boxPath, box)
    delete_box = true;
end

% Generate temporary output filename
outPath = [tempname '.h5'];

% Build command line args
cmd = {
    'python'
    ['"' ff(funpath(true), 'predict_box.py') '"']
    ['"' boxPath '"']
    ['"' modelPath '"']
    ['"' outPath '"']
    };
if saveConfmaps
    cmd{end+1} = '--save-confmaps';
end
disp(strjoin(cmd))

% Predict
try
    exit_code = system(strjoin(cmd));
catch ME
    if delete_box && exists(boxPath); delete(boxPath); end
    rethrow(ME)
end
if delete_box && exists(boxPath); delete(boxPath); end

% Read data back in
try
    preds = h5readgroup(outPath);
catch ME
    if exists(outPath); delete(outPath); end
    rethrow(ME)
end
if exists(outPath); delete(outPath); end

% Adjust for 0-based indexing
preds.positions_pred = single(preds.positions_pred) + 1;

% Rescale confidence maps to correct range prior to quantization
if saveConfmaps && isfield(preds.Attributes, 'confmaps')
    c_min = preds.Attributes.confmaps.range_min;
    c_max = preds.Attributes.confmaps.range_max;
    preds.confmaps = rescale(single(preds.confmaps) / 255, c_min, c_max);
end

% Adjust for singleton input
if is_singleton
    preds.positions_pred = preds.positions_pred(:,:,1);
    preds.conf_pred = preds.conf_pred(:,1);
    if isfield(preds,'confmaps')
        preds.confmaps = preds.confmaps(:,:,:,1);
    end
end

end


function iccvWriteSupplementalResults(fn)

gtdir1 = './iccvGroundTruth/gtsave/';
ourdir1 = './data4/smallsegs/3/';
ncutdir1 = './data4/ncutsegs/';
geomdir1 = './data4/geomsegs/';

gtdir2 = './results/supp/gt/';
ourdir2 = './results/supp/result/';
ncutdir2 = './results/supp/ncut/';
geomdir2 = './results/supp/geom/';

imdir = './iccvGroundTruth/images/';

for f = 1:numel(fn)

    disp(num2str(f))

    bn = strtok(fn{f}, '.');

    im = im2double(imread([imdir bn '.jpg']));

    %% gt
    if 0
    load([gtdir1 bn '_gt.mat']);
    outname = [gtdir2 bn '_gt.jpg'];

    contact = {}; %cell(bndinfo.nseg, 1);

    bndinfo2 = updateBoundaryInfo2(bndinfo, bndinfo.labels);

    bndinfo2.names = bndinfo.names;
    bndinfo2.type = bndinfo.type;
    bndinfo2 = orderfields(bndinfo2);

    bndinfo2 = processGtBoundaryLabels(bndinfo2);

    lab = bndinfo2.edges.boundaryType;
    lab = (lab(1:end/2)>0) + 2*(lab(end/2+1:end)>0);

    printOcclusionResultWithContact(im, bndinfo2, lab, outname, contact, 1);
    end

    %% results
    resdirs = {ourdir1, geomdir1, ncutdir1};
    outdirs = {ourdir2, geomdir2, ncutdir2};

    for k = 1 %:numel(resdirs)

        load([resdirs{k} bn '_seg.mat']);
        %try
            if k==1
                writeDepthImages(resdirs{k}, fn(f), outdirs{k});
                load([outdirs{k} bn '_contact.mat']);
            end
%         catch
%             lasterr
%             contact = {};
%         end
if 0
        try
            lab = bndinfo.edges.boundaryType;
            lab = lab(1:end/2) + 2*lab(end/2+1:end);
        catch
            lab = [];
        end

        outname = [outdirs{k} bn '_res.jpg'];
        printOcclusionResultWithContact(im, bndinfo, lab, outname, contact, 1);
end
    end
end


% track a target
function tracker = MOT_track(frame_idx, frame_image, frame_size, bboxes, tracker, opt, seq_name)

if tracker.state == opt.STATE_TRACKED || tracker.state == opt.STATE_ACTIVATED
    tracker.num_occluded = 0;
    tracker.num_tracked = tracker.num_tracked + 1;
    tracker = track_frame(tracker, frame_idx, frame_image, bboxes, [], seq_name, opt);

    % check if target exits from the camera view
    [~, ov] = calc_overlap(tracker.bboxes, numel(tracker.bboxes.fr), frame_size, 1);
    if ov < opt.exit_thre
        if opt.is_print
            fprintf('The target exits from the camera view.\n');
        end
        tracker.state = opt.STATE_STOP;
    end
end


%PRINT2ARRAY  Exports a figure to an image array
%
% Examples:
%   A = print2array
%   A = print2array(figure_handle)
%   A = print2array(figure_handle, resolution)
%   A = print2array(figure_handle, resolution, renderer)
%   [A bcol] = print2array(...)
%
% This function outputs a bitmap image of the given figure, at the desired
% resolution.
%
% If renderer is '-painters' then ghostcript needs to be installed. This
% can be downloaded from: http://www.ghostscript.com
%
% IN:
%   figure_handle - The handle of the figure to be exported. Default: gcf.
%   resolution - Resolution of the output, as a factor of screen
%                resolution. Default: 1.
%   renderer - string containing the renderer paramater to be passed to
%              print. Default: '-opengl'.
%
% OUT:
%   A - MxNx3 uint8 image of the figure.
%   bcol - 1x3 uint8 vector of the background color

% Copyright (C) Oliver Woodford 2008-2011

% 5/9/2011 Set EraseModes to normal when using opengl or zbuffer renderers.
% Thanks to Pawel Kocieniewski for reporting the issue.

% 21/9/2011 Bug fix: unit8 -> uint8!
% Thanks to Tobias Lamour for reporting the issue.

% 14/11/2011 Bug fix: stop using hardcopy(), as it interfered with figure
% size and erasemode settings. Makes it a bit slower, but more reliable.
% Thanks to Phil Trinh and Meelis Lootus for reporting the issues.

% 9/12/2011 Pass font path to ghostscript.

% 27/1/2012 Bug fix affecting painters rendering tall figures. Thanks to
% Ken Campbell for reporting it.

function [A bcol] = print2array(fig, res, renderer)
% Generate default input arguments, if needed
if nargin < 2
    res = 1;
    if nargin < 1
        fig = gcf;
    end
end
% Warn if output is large
old_mode = get(fig, 'Units');
set(fig, 'Units', 'pixels');
px = get(fig, 'Position');
set(fig, 'Units', old_mode);
npx = prod(px(3:4)*res)/1e6;
if npx > 30
    % 30M pixels or larger!
    warning('MATLAB:LargeImage', 'print2array generating a %.1fM pixel image. This could be slow and might also cause memory problems.', npx);
end
% Retrieve the background colour
bcol = get(fig, 'Color');
% Set the resolution parameter
res_str = ['-r' num2str(ceil(get(0, 'ScreenPixelsPerInch')*res))];
% Generate temporary file name
tmp_nam = [tempname '.tif'];
if nargin > 2 && strcmp(renderer, '-painters')
    % Print to eps file
    tmp_eps = [tempname '.eps'];
    print2eps(tmp_eps, fig, renderer, '-loose');
    try
        % Initialize the command to export to tiff using ghostscript
        cmd_str = ['-dEPSCrop -q -dNOPAUSE -dBATCH ' res_str ' -sDEVICE=tiff24nc'];
        % Set the font path
        fp = font_path();
        if ~isempty(fp)
            cmd_str = [cmd_str ' -sFONTPATH="' fp '"'];
        end
        % Add the filenames
        cmd_str = [cmd_str ' -sOutputFile="' tmp_nam '" "' tmp_eps '"'];
        % Execute the ghostscript command
        ghostscript(cmd_str);
    catch
        % Delete the intermediate file
        delete(tmp_eps);
        rethrow(lasterror);
    end
    % Delete the intermediate file
    delete(tmp_eps);
    % Read in the generated bitmap
    A = imread(tmp_nam);
    % Delete the temporary bitmap file
    delete(tmp_nam);
    % Set border pixels to the correct colour
    if isequal(bcol, 'none')
        bcol = [];
    elseif isequal(bcol, [1 1 1])
        bcol = uint8([255 255 255]);
    else
        for l = 1:size(A, 2)
            if ~all(reshape(A(:,l,:) == 255, [], 1))
                break;
            end
        end
        for r = size(A, 2):-1:l
            if ~all(reshape(A(:,r,:) == 255, [], 1))
                break;
            end
        end
        for t = 1:size(A, 1)
            if ~all(reshape(A(t,:,:) == 255, [], 1))
                break;
            end
        end
        for b = size(A, 1):-1:t
            if ~all(reshape(A(b,:,:) == 255, [], 1))
                break;
            end
        end
        bcol = median([reshape(A(:,[l r],:), [], size(A, 3)); reshape(A([t b],:,:), [], size(A, 3))], 1);
        for c = 1:size(A, 3)
            A(:,[1:l-1, r+1:end],c) = bcol(c);
            A([1:t-1, b+1:end],:,c) = bcol(c);
        end
    end
else
    if nargin < 3
        renderer = '-opengl';
    end
    err = false;
    % Set paper size
    old_mode = get(fig, 'PaperPositionMode');
    set(fig, 'PaperPositionMode', 'auto');
    try
        % Print to tiff file
        print(fig, renderer, res_str, '-dtiff', tmp_nam);
        % Read in the printed file
        A = imread(tmp_nam);
        % Delete the temporary file
        delete(tmp_nam);
    catch ex
        err = true;
    end
    % Reset paper size
    set(fig, 'PaperPositionMode', old_mode);
    % Throw any error that occurred
    if err
        rethrow(ex);
    end
    % Set the background color
    if isequal(bcol, 'none')
        bcol = [];
    else
        bcol = bcol * 255;
        if isequal(bcol, round(bcol))
            bcol = uint8(bcol);
        else
            bcol = squeeze(A(1,1,:));
        end
    end
end
% Check the output size is correct
if isequal(res, round(res))
    px = [px([4 3])*res 3];
    if ~isequal(size(A), px)
        % Correct the output size
        A = A(1:min(end,px(1)),1:min(end,px(2)),:);
    end
end
return

% Function to return (and create, where necessary) the font path
function fp = font_path()
fp = user_string('gs_font_path');
if ~isempty(fp)
    return
end
% Create the path
% Start with the default path
fp = getenv('GS_FONTPATH');
% Add on the typical directories for a given OS
if ispc
    if ~isempty(fp)
        fp = [fp ';'];
    end
    fp = [fp getenv('WINDIR') filesep 'Fonts'];
else
    if ~isempty(fp)
        fp = [fp ':'];
    end
    fp = [fp '/usr/share/fonts:/usr/local/share/fonts:/usr/share/fonts/X11:/usr/local/share/fonts/X11:/usr/share/fonts/truetype:/usr/local/share/fonts/truetype'];
end
user_string('gs_font_path', fp);
return


%SAVEPGM	Write a PGM format file
%
%	SAVEPGM(filename, im)
%
%	Saves the specified image array in a binary (P5) format PGM image file.
%
% SEE ALSO:	loadpgm
%

% Copyright (C) 1993-2011, by Peter I. Corke
%
% This file is part of The Machine Vision Toolbox for Matlab (MVTB).
%
% MVTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% MVTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with MVTB.  If not, see <http://www.gnu.org/licenses/>.

function savepgm(fname, im)

	fid = fopen(fname, 'w');
	if isempty(fid),
		error('cant open file for write');
	end
	[r,c] = size(im');
	fprintf(fid, 'P5\n');
	fprintf(fid, '%d %d\n', r, c);
	fprintf(fid, '255\n');
	fwrite(fid, im', 'uchar');
	fclose(fid)


function pathway=markPathwayWithExpression(pathway,model,experiment,experimentOrder)
% markPathwayWithExpression
%   Adds gene expression data to a pathway object
%
%   pathway           map structure as generated by constructPathwayFromCelldesigner
%   model             a model structure
%   experiment        experiment structure as generated by getExpressionStructure
%   experimentOrder   cell array with two experiment names as defined in
%                     'experiment'
%
%   pathway           updated pathway object
%
%   Usage: pathway=markPathwayWithExpression(pathway,model,experiment,experimentOrder)

if numel(experimentOrder)~=2
    EM='This can only be done for two cases at the moment (experimentOrder must be two elements)';
    dispEM(EM);
end

%Check that experiment fit with experimentOrder
[present, expIds]=ismember(experimentOrder,experiment.experiments);

if ~all(present)
    EM='Not all experiments could be found in the experiment structure';
    dispEM(EM);
end

experiment.data=experiment.data(:,expIds);
experiment.experiments=experiment.experiments(:,expIds);

%Go through each species in pathway and if it's a reaction, get it's genes
%and log2-fold change in expression from model and experiment
for i=1:numel(pathway.listOfSpecies)
    if strcmp('PROTEIN', pathway.listOfSpecies(i).type)
        if isfield(pathway.listOfSpecies(i),'note')
            if ~isempty(pathway.listOfSpecies(i).note)
                %Get the reaction if present in model
                [present, index]=ismember(pathway.listOfSpecies(i).note,model.rxns);

                %If present, then get the genes
                if any(present)
                    [~, genes]=find(model.rxnGeneMat(index,:));

                    %If it was associated with genes match them to the ORFs
                    if any(genes)
                        [present, experimentIndexes]=ismember(model.genes(genes),experiment.orfs);

                        %Add annotation to pathway structure
                        if any(present)
                            pathway.listOfSpecies(i).orfs=experiment.orfs(experimentIndexes(present));
                            pathway.listOfSpecies(i).expA=experiment.data(experimentIndexes(present),1);
                            pathway.listOfSpecies(i).expB=experiment.data(experimentIndexes(present),2);
                        end
                    end
                end
            end
        end
    end
end
end