%test_VAcPlant(t, ID) is an example, which shows how to use the VAModel in MATLAB
%In this example, Luyben's multi-loop control structure is implemented and tested
%Eight process disturbances are available and transients are generated at the end of simulation
%On a PIII-1GHz PC, the VA plant model runs approaximately 80 times faster than the real time
%To use this example:
%       t sets the simulation time (in munite)
%       ID is an integer selected between 0 and 8
%           0: no disturbance
%           1: setpoint of the reactor outlet temperature decreases 8 degC (from 159 to 151)
%           2: setpoint of the reactor outlet temperature increases 6 degC (from 159 to 165)
%           3: setpoint of the H2O composition in the column bottom increases 9% (from 9% to 18%)
%           4: the vaporizer liqiud inlet flowrate increases 0.44 kmol/min (from 2.2 to 2.64)
%           5: HAc fresh feed stream lost for 5 minutes
%           6: O2 fresh feed stream lost for 5 minutes
%           7: C2H6 composition changes from 0.001 to 0.003 in the C2H4 fresh feed stream
%           8: column feed lost for 5 minutes
%       Note: in this example, all the disturbances occur at 10 minute after the simulation starts
%-----------------------------------------------------------------------------
%Copyright: Rong Chen and Kedar David, June 2002
%-----------------------------------------------------------------------------
function test_VAcPlant(minute,selected_ID)

%-----------------------------------------------------------------------------
close all
format short g
%-----------------------------------------------------------------------------

%-----------------------------------------------------------------------------
%The recommended simulation sampling time is 1/3 second, which corresponds to a frequency of 180 samples in one minute
model_sampling_frequency=180;
%The recommended historical data sampling time is 1 minute, which corresponds to a frequency of 1 sample in one minute
storage_sampling_frequency=1;
%The recommended display sampling time is 1 minute, which corresponds to a frequency of 1 sample in one minute
display_sampling_frequency=1;
%-----------------------------------------------------------------------------

%-----------------------------------------------------------------------------
% Inintialze process states and MV's
% 246 state variables
states=zeros(246,1);
% 26 manipulated variables
MVs=zeros(26,1);
% set the current process time to 0 (in minute)
time=0;
% set initialization flag 1
is_initial=1;
% set disturbance_ID 0
disturbance_ID=0;
% get the base operation
[dstatedt,states,MVs,y_ss]=VAModel(states,MVs,time,is_initial,disturbance_ID);
%-----------------------------------------------------------------------------

%-----------------------------------------------------------------------------
% Implement Luyben and Tyreus's control structure for the VA plant
% Note that: in this example,
%   1. for each transmitter, a 3 second time lag is used
%   2. for two analyzer transmitters (on the gas recycle and column bottom), a 10 minute deadtime is used
%   3. for other transmitters, no deadtime is used
%   4. for three controllers using analyzers on the gas recycle and column bottom, a 10 minute sampling time is used
%   5. for other controllers, a 1 second sampling time is used
%   6. for each transmitter, a 1 second sampling time is used
%-----------------------------------------------------------------------------
transmitter_lag=0.05; %in minute
transmitter_deadtime=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 0 10 0 0 0 0 0 0]; %in minute
transmitter_sampling_frequency=[60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60];
controller_sampling_frequency=[60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 0.1 0.1 60 0.1 60 60 60 60 60 60];
%-----------------------------------------------------------------------------
%transmitter and controller initialization
%SP: setpoint (not scaled)
%K: controller gain which is dimentionless
%Ti: reset time (in minute)
%act: 1 if positive process gain, -1 if negative process gain
%mode: 1 for automatic, 2 for manual
%Ponly: 1 for proportional only control, 0 for PI control
%hc: controller sampling time (in minute), should be 1/"controller_sampling_frequency"
%ht: transmitter sampling time (in minute), should be 1/"transmitter_sampling_frequency"
%uLO: low limit of MV
%uHI: high limit of MV
%ded: should be "transmitter_deadtime" defined above
%tau: should be "transmitter_lag" defined above
%yLO: low limit of measurement
%yHI: high limit of measurement
%Nded: measurement deadtime storage, which should be 1+transmitter_deadtime*transmitter_sampling_frequency
%Ntau: measurement time constant storage, which should be 1 all the time
%-----------------------------------------------------------------------------
%MV1: F_O2 - O2 composition
SP_O2=0.075;
K_O2=5;
Ti_O2=10;
act_O2=1;
mode_O2=1;
Ponly_O2=0;
ht_O2=1/transmitter_sampling_frequency(1);
hc_O2=1/controller_sampling_frequency(1);
uLO_O2=0;
uHI_O2=2.268;
ded_O2=transmitter_deadtime(1);
tau_O2=transmitter_lag;
yLO_O2=0;
yHI_O2=0.2;
Nded_O2=1+transmitter_deadtime(1)*transmitter_sampling_frequency(1);
Ntau_O2=1;
xxx_O2(1)= (y_ss(37) -yLO_O2) / (yHI_O2 -yLO_O2);
for i=2:Nded_O2
    xxx_O2(i)=xxx_O2(1);
end
for i=1:Ntau_O2
    yyy_O2(i)= xxx_O2(Nded_O2);
end
xi_O2= (MVs(1) - uLO_O2) /(uHI_O2 -uLO_O2)-K_O2*act_O2*((SP_O2-yLO_O2)/(yHI_O2-yLO_O2)-yyy_O2(Ntau_O2));
%-----------------------------------------------------------------------------
%controller initialization
%MV2: F_C2H4 - Recycle Pressure
SP_C2H4=128;
K_C2H4=0.3;
Ti_C2H4=20;
act_C2H4=1;
mode_C2H4=1;
Ponly_C2H4=0;
ht_C2H4=1/transmitter_sampling_frequency(2);
hc_C2H4=1/controller_sampling_frequency(2);
uLO_C2H4=0;
uHI_C2H4=7.56;
ded_C2H4=transmitter_deadtime(2);
tau_C2H4=transmitter_lag;
yLO_C2H4=0;
yHI_C2H4=200;
Nded_C2H4=1+transmitter_deadtime(2)*transmitter_sampling_frequency(2);
Ntau_C2H4=1;
xxx_C2H4(1)= (y_ss(12) -yLO_C2H4) / (yHI_C2H4 -yLO_C2H4);
for i=2:Nded_C2H4
    xxx_C2H4(i)= xxx_C2H4(1);
end
for i=1:Ntau_C2H4
    yyy_C2H4(i)= xxx_C2H4(Nded_C2H4);
end
xi_C2H4= (MVs(2) - uLO_C2H4) /(uHI_C2H4 -uLO_C2H4)-K_C2H4*act_C2H4*((SP_C2H4-yLO_C2H4)/(yHI_C2H4-yLO_C2H4)-yyy_C2H4(Ntau_C2H4));
%-----------------------------------------------------------------------------
%controller initialization
%MV3: HAc feed stream - HAc tank level
SP_HAc=0.5;
K_HAc=2;
Ti_HAc=100;
act_HAc=1;
mode_HAc=1;
Ponly_HAc=1;
ht_HAc=1/transmitter_sampling_frequency(3);
hc_HAc=1/controller_sampling_frequency(3);
uLO_HAc=0;
uHI_HAc=4.536;
ded_HAc=transmitter_deadtime(3);
tau_HAc=transmitter_lag;
yLO_HAc=0;
yHI_HAc=1;
Nded_HAc=1+transmitter_deadtime(3)*transmitter_sampling_frequency(3);
Ntau_HAc=1;
xxx_HAc(1)= (y_ss(23) -yLO_HAc) / (yHI_HAc -yLO_HAc);
for i=2:Nded_HAc
    xxx_HAc(i)= xxx_HAc(1);
end
for i=1:Ntau_HAc
    yyy_HAc(i)= xxx_HAc(Nded_HAc);
end
xi_HAc= (MVs(3) - uLO_HAc) /(uHI_HAc -uLO_HAc)-K_HAc*act_HAc*((SP_HAc-yLO_HAc)/(yHI_HAc-yLO_HAc)-yyy_HAc(Ntau_HAc));
%-----------------------------------------------------------------------------
%controller initialization
%MV4: Qv - Level
SP_LevelVap=0.7;
K_LevelVap=0.1;
Ti_LevelVap=30;
act_LevelVap=-1;
mode_LevelVap=1;
Ponly_LevelVap=0;
ht_LevelVap=1/transmitter_sampling_frequency(4);
hc_LevelVap=1/controller_sampling_frequency(4);
uLO_LevelVap=0;
uHI_LevelVap=1433400;
ded_LevelVap=transmitter_deadtime(4);
tau_LevelVap=transmitter_lag;
yLO_LevelVap=0;
yHI_LevelVap=1;
Nded_LevelVap=1+transmitter_deadtime(4)*transmitter_sampling_frequency(4);
Ntau_LevelVap=1;
xxx_LevelVap(1)= (y_ss(2) -yLO_LevelVap) / (yHI_LevelVap -yLO_LevelVap);
for i=2:Nded_LevelVap
    xxx_LevelVap(i)= xxx_LevelVap(1);
end
for i=1:Ntau_LevelVap
    yyy_LevelVap(i)= xxx_LevelVap(Nded_LevelVap);
end
xi_LevelVap= (MVs(4) - uLO_LevelVap) /(uHI_LevelVap -uLO_LevelVap)-K_LevelVap*act_LevelVap*((SP_LevelVap-yLO_LevelVap)/(yHI_LevelVap-yLO_LevelVap)-yyy_LevelVap(Ntau_LevelVap));
%-----------------------------------------------------------------------------
%controller initialization
%MV5: F_Vaporizer - Vaporizer Pressure
SP_PresVap=128;
K_PresVap=5;
Ti_PresVap=10;
act_PresVap=-1;
mode_PresVap=1;
Ponly_PresVap=0;
ht_PresVap=1/transmitter_sampling_frequency(5);
hc_PresVap=1/controller_sampling_frequency(5);
uLO_PresVap=0;
uHI_PresVap=50;
ded_PresVap=transmitter_deadtime(5);
tau_PresVap=transmitter_lag;
yLO_PresVap=0;
yHI_PresVap=200;
Nded_PresVap=1+transmitter_deadtime(5)*transmitter_sampling_frequency(5);
Ntau_PresVap=1;
xxx_PresVap(1)= (y_ss(1) -yLO_PresVap) / (yHI_PresVap -yLO_PresVap);
for i=2:Nded_PresVap
    xxx_PresVap(i)= xxx_PresVap(1);
end
for i=1:Ntau_PresVap
    yyy_PresVap(i)= xxx_PresVap(Nded_PresVap);
end
xi_PresVap= (MVs(5) - uLO_PresVap) /(uHI_PresVap -uLO_PresVap)-K_PresVap*act_PresVap*((SP_PresVap-yLO_PresVap)/(yHI_PresVap-yLO_PresVap)-yyy_PresVap(Ntau_PresVap));
%-----------------------------------------------------------------------------
%controller initialization
%MV6: Q_heater - Vaporizer Outlet Temperature
SP_ReactorInletTemp=150;
K_ReactorInletTemp=1;
Ti_ReactorInletTemp=5;
act_ReactorInletTemp=1;
mode_ReactorInletTemp=1;
Ponly_ReactorInletTemp=0;
ht_ReactorInletTemp=1/transmitter_sampling_frequency(6);
hc_ReactorInletTemp=1/controller_sampling_frequency(6);
uLO_ReactorInletTemp=0;
uHI_ReactorInletTemp=15000;
ded_ReactorInletTemp=transmitter_deadtime(6);
tau_ReactorInletTemp=transmitter_lag;
yLO_ReactorInletTemp=120;
yHI_ReactorInletTemp=170;
Nded_ReactorInletTemp=1+transmitter_deadtime(6)*transmitter_sampling_frequency(6);
Ntau_ReactorInletTemp=1;
xxx_ReactorInletTemp(1)= (y_ss(4) -yLO_ReactorInletTemp) / (yHI_ReactorInletTemp -yLO_ReactorInletTemp);
for i=2:Nded_ReactorInletTemp
    xxx_ReactorInletTemp(i)= xxx_ReactorInletTemp(1);
end
for i=1:Ntau_ReactorInletTemp
    yyy_ReactorInletTemp(i)= xxx_ReactorInletTemp(Nded_ReactorInletTemp);
end
xi_ReactorInletTemp= (MVs(6) - uLO_ReactorInletTemp) /(uHI_ReactorInletTemp -uLO_ReactorInletTemp)-K_ReactorInletTemp*act_ReactorInletTemp*((SP_ReactorInletTemp-yLO_ReactorInletTemp)/(yHI_ReactorInletTemp-yLO_ReactorInletTemp)-yyy_ReactorInletTemp(Ntau_ReactorInletTemp));
%-----------------------------------------------------------------------------
%controller initialization
%MV7: T_Shell - T_RCTOUT
SP_TRCT=159.17;
K_TRCT=3;
Ti_TRCT=10;
act_TRCT=1;
mode_TRCT=1;
Ponly_TRCT=0;
ht_TRCT=1/transmitter_sampling_frequency(7);
hc_TRCT=1/controller_sampling_frequency(7);
uLO_TRCT=110;
uHI_TRCT=150;
ded_TRCT=transmitter_deadtime(7);
tau_TRCT=transmitter_lag;
yLO_TRCT=0;
yHI_TRCT=200;
Nded_TRCT=1+transmitter_deadtime(7)*transmitter_sampling_frequency(7);
Ntau_TRCT=1;
xxx_TRCT(1)= (y_ss(5)-yLO_TRCT) / (yHI_TRCT -yLO_TRCT);
for i=2:Nded_TRCT
    xxx_TRCT(i)= xxx_TRCT(1);
end
for i=1:Ntau_TRCT
    yyy_TRCT(i)= xxx_TRCT(Nded_TRCT);
end
xi_TRCT= (MVs(7) - uLO_TRCT) /(uHI_TRCT -uLO_TRCT)-K_TRCT*act_TRCT*((SP_TRCT-yLO_TRCT)/(yHI_TRCT-yLO_TRCT)-yyy_TRCT(Ntau_TRCT));
%-----------------------------------------------------------------------------
%controller initialization
%MV8: Separator Liquid Exit - Separator Level
SP_LevelSep=0.5;
K_LevelSep=5;
Ti_LevelSep=100;
act_LevelSep=-1;
mode_LevelSep=1;
Ponly_LevelSep=1;
ht_LevelSep=1/transmitter_sampling_frequency(8);
hc_LevelSep=1/controller_sampling_frequency(8);
uLO_LevelSep=0;
uHI_LevelSep=4.536;
ded_LevelSep=transmitter_deadtime(8);
tau_LevelSep=transmitter_lag;
yLO_LevelSep=0;
yHI_LevelSep=1;
Nded_LevelSep=1+transmitter_deadtime(8)*transmitter_sampling_frequency(8);
Ntau_LevelSep=1;
xxx_LevelSep(1)= (y_ss(9)-yLO_LevelSep) / (yHI_LevelSep -yLO_LevelSep);
for i=2:Nded_LevelSep
    xxx_LevelSep(i)= xxx_LevelSep(1);
end
for i=1:Ntau_LevelSep
    yyy_LevelSep(i)= xxx_LevelSep(Nded_LevelSep);
end
xi_LevelSep= (MVs(8) - uLO_LevelSep) /(uHI_LevelSep -uLO_LevelSep)-K_LevelSep*act_LevelSep*((SP_LevelSep-yLO_LevelSep)/(yHI_LevelSep-yLO_LevelSep)-yyy_LevelSep(Ntau_LevelSep));
%-----------------------------------------------------------------------------
%controller initialization
%MV9: T_Shell_Separator - Separator Liquid Temperature
SP_TempSep=40;
K_TempSep=5;
Ti_TempSep=20;
act_TempSep=-1;
mode_TempSep=1;
Ponly_TempSep=0;
ht_TempSep=1/transmitter_sampling_frequency(9);
hc_TempSep=1/controller_sampling_frequency(9);
uLO_TempSep=0;
uHI_TempSep=80;
ded_TempSep=transmitter_deadtime(9);
tau_TempSep=transmitter_lag;
yLO_TempSep=0;
yHI_TempSep=80;
Nded_TempSep=1+transmitter_deadtime(9)*transmitter_sampling_frequency(9);
Ntau_TempSep=1;
xxx_TempSep(1)= (y_ss(10)-yLO_TempSep) / (yHI_TempSep -yLO_TempSep);
for i=2:Nded_TempSep
    xxx_TempSep(i)= xxx_TempSep(1);
end
for i=1:Ntau_TempSep
    yyy_TempSep(i)= xxx_TempSep(Nded_TempSep);
end
xi_TempSep= (MVs(9) - uLO_TempSep) /(uHI_TempSep -uLO_TempSep)-K_TempSep*act_TempSep*((SP_TempSep-yLO_TempSep)/(yHI_TempSep-yLO_TempSep)-yyy_TempSep(Ntau_TempSep));
%-----------------------------------------------------------------------------
%controller initialization
%MV10: Separator Vapor Exit is fixed at 16.1026 kmol/min
%-----------------------------------------------------------------------------
%controller initialization
%MV11: Q_Compressor_Cooler - Compressor Outlet Temperature (80degC)
SP_CompOutletTemp=80;
K_CompOutletTemp=1;
Ti_CompOutletTemp=5;
act_CompOutletTemp=-1;
mode_CompOutletTemp=1;
Ponly_CompOutletTemp=0;
ht_CompOutletTemp=1/transmitter_sampling_frequency(11);
hc_CompOutletTemp=1/controller_sampling_frequency(11);
uLO_CompOutletTemp=0;
uHI_CompOutletTemp=50000;
ded_CompOutletTemp=transmitter_deadtime(11);
tau_CompOutletTemp=transmitter_lag;
yLO_CompOutletTemp=70;
yHI_CompOutletTemp=90;
Nded_CompOutletTemp=1+transmitter_deadtime(11)*transmitter_sampling_frequency(11);
Ntau_CompOutletTemp=1;
xxx_CompOutletTemp(1)= (y_ss(11) -yLO_CompOutletTemp) / (yHI_CompOutletTemp -yLO_CompOutletTemp);
for i=2:Nded_CompOutletTemp
    xxx_CompOutletTemp(i)= xxx_CompOutletTemp(1);
end
for i=1:Ntau_CompOutletTemp
    yyy_CompOutletTemp(i)= xxx_CompOutletTemp(Nded_CompOutletTemp);
end
xi_CompOutletTemp= (MVs(11) - uLO_CompOutletTemp) /(uHI_CompOutletTemp -uLO_CompOutletTemp)-K_CompOutletTemp*act_CompOutletTemp*((SP_CompOutletTemp-yLO_CompOutletTemp)/(yHI_CompOutletTemp-yLO_CompOutletTemp)-yyy_CompOutletTemp(Ntau_CompOutletTemp));
%-----------------------------------------------------------------------------
%controller initialization
%MV12: Absorber Liquid Exit - Absorber Level
SP_LevelAbs=0.5;
K_LevelAbs=5;
Ti_LevelAbs=100;
act_LevelAbs=-1;
mode_LevelAbs=1;
Ponly_LevelAbs=1;
ht_LevelAbs=1/transmitter_sampling_frequency(12);
hc_LevelAbs=1/controller_sampling_frequency(12);
uLO_LevelAbs=0;
uHI_LevelAbs=4.536;
ded_LevelAbs=transmitter_deadtime(12);
tau_LevelAbs=transmitter_lag;
yLO_LevelAbs=0;
yHI_LevelAbs=1;
Nded_LevelAbs=1+transmitter_deadtime(12)*transmitter_sampling_frequency(12);
Ntau_LevelAbs=1;
xxx_LevelAbs(1)= (y_ss(13)-yLO_LevelAbs) / (yHI_LevelAbs -yLO_LevelAbs);
for i=2:Nded_LevelAbs
    xxx_LevelAbs(i)= xxx_LevelAbs(1);
end
for i=1:Ntau_LevelAbs
    yyy_LevelAbs(i)= xxx_LevelAbs(Nded_LevelAbs);
end
xi_LevelAbs= (MVs(12) - uLO_LevelAbs) /(uHI_LevelAbs -uLO_LevelAbs)-K_LevelAbs*act_LevelAbs*((SP_LevelAbs-yLO_LevelAbs)/(yHI_LevelAbs-yLO_LevelAbs)-yyy_LevelAbs(Ntau_LevelAbs));
%-----------------------------------------------------------------------------
%controller initialization
%MV13: Circulation Flowrate is fixed to 15.1198 kmol/min
%-----------------------------------------------------------------------------
%controller initialization
%MV14: Q_Cooler_Circulation - Circulation Temperature
SP_CircOutletTemp=25;
K_CircOutletTemp=1;
Ti_CircOutletTemp=5;
act_CircOutletTemp=-1;
mode_CircOutletTemp=1;
Ponly_CircOutletTemp=0;
ht_CircOutletTemp=1/transmitter_sampling_frequency(14);
hc_CircOutletTemp=1/controller_sampling_frequency(14);
uLO_CircOutletTemp=0;
uHI_CircOutletTemp=30000;
ded_CircOutletTemp=transmitter_deadtime(14);
tau_CircOutletTemp=transmitter_lag;
yLO_CircOutletTemp=10;
yHI_CircOutletTemp=40;
Nded_CircOutletTemp=1+transmitter_deadtime(14)*transmitter_sampling_frequency(14);
Ntau_CircOutletTemp=1;
xxx_CircOutletTemp(1)= (y_ss(14) -yLO_CircOutletTemp) / (yHI_CircOutletTemp -yLO_CircOutletTemp);
for i=2:Nded_CircOutletTemp
    xxx_CircOutletTemp(i)= xxx_CircOutletTemp(1);
end
for i=1:Ntau_CircOutletTemp
    yyy_CircOutletTemp(i)= xxx_CircOutletTemp(Nded_CircOutletTemp);
end
xi_CircOutletTemp= (MVs(14) - uLO_CircOutletTemp) /(uHI_CircOutletTemp -uLO_CircOutletTemp)-K_CircOutletTemp*act_CircOutletTemp*((SP_CircOutletTemp-yLO_CircOutletTemp)/(yHI_CircOutletTemp-yLO_CircOutletTemp)-yyy_CircOutletTemp(Ntau_CircOutletTemp));
%-----------------------------------------------------------------------------
%controller initialization
%MV15: Scrub Flowrate is fixed to 0.756 kmol/min
%-----------------------------------------------------------------------------
%controller initialization
%MV16: Q_Cooler_Scrub - Scrub Temperature
SP_ScrubOutletTemp=25;
K_ScrubOutletTemp=1;
Ti_ScrubOutletTemp=5;
act_ScrubOutletTemp=-1;
mode_ScrubOutletTemp=1;
Ponly_ScrubOutletTemp=0;
ht_ScrubOutletTemp=1/transmitter_sampling_frequency(16);
hc_ScrubOutletTemp=1/controller_sampling_frequency(16);
uLO_ScrubOutletTemp=0;
uHI_ScrubOutletTemp=5000;
ded_ScrubOutletTemp=transmitter_deadtime(16);
tau_ScrubOutletTemp=transmitter_lag;
yLO_ScrubOutletTemp=10;
yHI_ScrubOutletTemp=40;
Nded_ScrubOutletTemp=1+transmitter_deadtime(16)*transmitter_sampling_frequency(16);
Ntau_ScrubOutletTemp=1;
xxx_ScrubOutletTemp(1)= (y_ss(15) -yLO_ScrubOutletTemp) / (yHI_ScrubOutletTemp -yLO_ScrubOutletTemp);
for i=2:Nded_ScrubOutletTemp
    xxx_ScrubOutletTemp(i)= xxx_ScrubOutletTemp(1);
end
for i=1:Ntau_ScrubOutletTemp
    yyy_ScrubOutletTemp(i)= xxx_ScrubOutletTemp(Nded_ScrubOutletTemp);
end
xi_ScrubOutletTemp= (MVs(16) - uLO_ScrubOutletTemp) /(uHI_ScrubOutletTemp -uLO_ScrubOutletTemp)-K_ScrubOutletTemp*act_ScrubOutletTemp*((SP_ScrubOutletTemp-yLO_ScrubOutletTemp)/(yHI_ScrubOutletTemp-yLO_ScrubOutletTemp)-yyy_ScrubOutletTemp(Ntau_ScrubOutletTemp));
%-----------------------------------------------------------------------------
%controller initialization
%MV17: CO2 - CO2 composition
SP_CO2=0.0076393;
K_CO2=1;
Ti_CO2=100;
act_CO2=-1;
mode_CO2=1;
Ponly_CO2=1;
ht_CO2=1/transmitter_sampling_frequency(17);
hc_CO2=1/controller_sampling_frequency(17);
uLO_CO2=0;
uHI_CO2=22.68;
ded_CO2=transmitter_deadtime(17);
tau_CO2=transmitter_lag;
yLO_CO2=0;
yHI_CO2=0.5;
Nded_CO2=1+transmitter_deadtime(17)*transmitter_sampling_frequency(17);
Ntau_CO2=1;
xxx_CO2(1)= (y_ss(31) -yLO_CO2) / (yHI_CO2 -yLO_CO2);
for i=2:Nded_CO2
    xxx_CO2(i)= xxx_CO2(1);
end
for i=1:Ntau_CO2
    yyy_CO2(i)= xxx_CO2(Nded_CO2);
end
xi_CO2= (MVs(17) - uLO_CO2) /(uHI_CO2 -uLO_CO2)-K_CO2*act_CO2*((SP_CO2-yLO_CO2)/(yHI_CO2-yLO_CO2)-yyy_CO2(Ntau_CO2));
%-----------------------------------------------------------------------------
%controller initialization
%MV18: Purge - C2H6 composition
SP_C2H6=0.25;
K_C2H6=1;
Ti_C2H6=100;
act_C2H6=-1;
mode_C2H6=1;
Ponly_C2H6=1;
ht_C2H6=1/transmitter_sampling_frequency(18);
hc_C2H6=1/controller_sampling_frequency(18);
uLO_C2H6=0;
uHI_C2H6=0.02268;
ded_C2H6=transmitter_deadtime(18);
tau_C2H6=transmitter_lag;
yLO_C2H6=0;
yHI_C2H6=1;
Nded_C2H6=1+transmitter_deadtime(18)*transmitter_sampling_frequency(18);
Ntau_C2H6=1;
xxx_C2H6(1)= (y_ss(33) -yLO_C2H6) / (yHI_C2H6 -yLO_C2H6);
for i=2:Nded_C2H6
    xxx_C2H6(i)= xxx_C2H6(1);
end
for i=1:Ntau_C2H6
    yyy_C2H6(i)= xxx_C2H6(Nded_C2H6);
end
xi_C2H6= (MVs(18) - uLO_C2H6) /(uHI_C2H6 -uLO_C2H6)-K_C2H6*act_C2H6*((SP_C2H6-yLO_C2H6)/(yHI_C2H6-yLO_C2H6)-yyy_C2H6(Ntau_C2H6));
%-----------------------------------------------------------------------------
%controller initialization
%MV19: bypass - FEHE Cold Exit Temp
SP_FEHE=134;
K_FEHE=5;
Ti_FEHE=10;
act_FEHE=1;
mode_FEHE=1;
Ponly_FEHE=0;
ht_FEHE=1/transmitter_sampling_frequency(19);
hc_FEHE=1/controller_sampling_frequency(19);
uLO_FEHE=0;
uHI_FEHE=1;
ded_FEHE=transmitter_deadtime(19);
tau_FEHE=transmitter_lag;
yLO_FEHE=0;
yHI_FEHE=200;
Nded_FEHE=1+transmitter_deadtime(19)*transmitter_sampling_frequency(19);
Ntau_FEHE=1;
xxx_FEHE(1)= (y_ss(8) -yLO_FEHE) / (yHI_FEHE -yLO_FEHE);
for i=2:Nded_FEHE
    xxx_FEHE(i)= xxx_FEHE(1);
end
for i=1:Ntau_FEHE
    yyy_FEHE(i)= xxx_FEHE(Nded_FEHE);
end
xi_FEHE= (MVs(19) - uLO_FEHE) /(uHI_FEHE -uLO_FEHE)-K_FEHE*act_FEHE*((SP_FEHE-yLO_FEHE)/(yHI_FEHE-yLO_FEHE)-yyy_FEHE(Ntau_FEHE));
%-----------------------------------------------------------------------------
%controller initialization
%MV20: LR - %H2O in bottom
SP_H2OCol=0.09344;
K_H2OCol=0.5;
Ti_H2OCol=60;
act_H2OCol=-1;
mode_H2OCol=1;
Ponly_H2OCol=0;
ht_H2OCol=1/transmitter_sampling_frequency(20);
hc_H2OCol=1/controller_sampling_frequency(20);
uLO_H2OCol=0;
uHI_H2OCol=7.56;
ded_H2OCol=transmitter_deadtime(20);
tau_H2OCol=transmitter_lag;
yLO_H2OCol=0;
yHI_H2OCol=0.2;
Nded_H2OCol=1+transmitter_deadtime(20)*transmitter_sampling_frequency(20);
Ntau_H2OCol=1;
xxx_H2OCol(1)= (y_ss(28) -yLO_H2OCol) / (yHI_H2OCol -yLO_H2OCol);
for i=2:Nded_H2OCol
    xxx_H2OCol(i)= xxx_H2OCol(1);
end
for i=1:Ntau_H2OCol
    yyy_H2OCol(i)= xxx_H2OCol(Nded_H2OCol);
end
xi_H2OCol= (MVs(20) - uLO_H2OCol) /(uHI_H2OCol -uLO_H2OCol)-K_H2OCol*act_H2OCol*((SP_H2OCol-yLO_H2OCol)/(yHI_H2OCol-yLO_H2OCol)-yyy_H2OCol(Ntau_H2OCol));
%-----------------------------------------------------------------------------
%controller initialization
%MV21: Qr - Temp
SP_TempCol=110;
K_TempCol=20;
Ti_TempCol=30;
act_TempCol=1;
mode_TempCol=1;
Ponly_TempCol=0;
ht_TempCol=1/transmitter_sampling_frequency(21);
hc_TempCol=1/controller_sampling_frequency(21);
uLO_TempCol=0;
uHI_TempCol=100000;
ded_TempCol=transmitter_deadtime(21);
tau_TempCol=transmitter_lag;
yLO_TempCol=0;
yHI_TempCol=120;
Nded_TempCol=1+transmitter_deadtime(21)*transmitter_sampling_frequency(21);
Ntau_TempCol=1;
xxx_TempCol(1)= (y_ss(22) -yLO_TempCol) / (yHI_TempCol -yLO_TempCol);
for i=2:Nded_TempCol
    xxx_TempCol(i)= xxx_TempCol(1);
end
for i=1:Ntau_TempCol
    yyy_TempCol(i)= xxx_TempCol(Nded_TempCol);
end
xi_TempCol= (MVs(21) - uLO_TempCol) /(uHI_TempCol -uLO_TempCol)-K_TempCol*act_TempCol*((SP_TempCol-yLO_TempCol)/(yHI_TempCol-yLO_TempCol)-yyy_TempCol(Ntau_TempCol));
%-----------------------------------------------------------------------------
%controller initialization
%MV22: Q_Condenser - Decanter Temperature (45.845 degC) is perfetly controlled in the code
SP_DecanterTemp=45.845;
K_DecanterTemp=1;
Ti_DecanterTemp=5;
act_DecanterTemp=-1;
mode_DecanterTemp=1;
Ponly_DecanterTemp=0;
ht_DecanterTemp=1/transmitter_sampling_frequency(22);
hc_DecanterTemp=1/controller_sampling_frequency(22);
uLO_DecanterTemp=0;
uHI_DecanterTemp=150000;
ded_DecanterTemp=transmitter_deadtime(22);
tau_DecanterTemp=transmitter_lag;
yLO_DecanterTemp=40;
yHI_DecanterTemp=50;
Nded_DecanterTemp=1+transmitter_deadtime(22)*transmitter_sampling_frequency(25);
Ntau_DecanterTemp=1;
xxx_DecanterTemp(1)= (y_ss(20) -yLO_DecanterTemp) / (yHI_DecanterTemp -yLO_DecanterTemp);
for i=2:Nded_DecanterTemp
    xxx_DecanterTemp(i)= xxx_DecanterTemp(1);
end
for i=1:Ntau_DecanterTemp
    yyy_DecanterTemp(i)= xxx_DecanterTemp(Nded_DecanterTemp);
end
xi_DecanterTemp= (MVs(22) - uLO_DecanterTemp) /(uHI_DecanterTemp -uLO_DecanterTemp)-K_DecanterTemp*act_DecanterTemp*((SP_DecanterTemp-yLO_DecanterTemp)/(yHI_DecanterTemp-yLO_DecanterTemp)-yyy_DecanterTemp(Ntau_DecanterTemp));
%-----------------------------------------------------------------------------
%controller initialization
%MV22: Organic Level is controlled by Organic Product Flow at 0.5
SP_Organic=0.5;
K_Organic=1;
Ti_Organic=100;
act_Organic=-1;
mode_Organic=1;
Ponly_Organic=1;
ht_Organic=1/transmitter_sampling_frequency(23);
hc_Organic=1/controller_sampling_frequency(23);
uLO_Organic=0;
uHI_Organic=2.4;
ded_Organic=transmitter_deadtime(23);
tau_Organic=transmitter_lag;
yLO_Organic=0;
yHI_Organic=1;
Nded_Organic=1+transmitter_deadtime(23)*transmitter_sampling_frequency(23);
Ntau_Organic=1;
xxx_Organic(1)= (y_ss(18)-yLO_Organic) / (yHI_Organic -yLO_Organic);
for i=2:Nded_Organic
    xxx_Organic(i)= xxx_Organic(1);
end
for i=1:Ntau_Organic
    yyy_Organic(i)= xxx_Organic(Nded_Organic);
end
xi_Organic= (MVs(23) - uLO_Organic) /(uHI_Organic -uLO_Organic)-K_Organic*act_Organic*((SP_Organic-yLO_Organic)/(yHI_Organic-yLO_Organic)-yyy_Organic(Ntau_Organic));
%-----------------------------------------------------------------------------
%controller initialization
%MV23: Aqueous Level is controlled by Aqueous Product Flow at 0.5
SP_Aqueous=0.5;
K_Aqueous=1;
Ti_Aqueous=100;
act_Aqueous=-1;
mode_Aqueous=1;
Ponly_Aqueous=1;
ht_Aqueous=1/transmitter_sampling_frequency(24);
hc_Aqueous=1/controller_sampling_frequency(24);
uLO_Aqueous=0;
uHI_Aqueous=2.4;
ded_Aqueous=transmitter_deadtime(24);
tau_Aqueous=transmitter_lag;
yLO_Aqueous=0;
yHI_Aqueous=1;
Nded_Aqueous=1+transmitter_deadtime(24)*transmitter_sampling_frequency(24);
Ntau_Aqueous=1;
xxx_Aqueous(1)= (y_ss(19)-yLO_Aqueous) / (yHI_Aqueous -yLO_Aqueous);
for i=2:Nded_Aqueous
    xxx_Aqueous(i)= xxx_Aqueous(1);
end
for i=1:Ntau_Aqueous
    yyy_Aqueous(i)= xxx_Aqueous(Nded_Aqueous);
end
xi_Aqueous= (MVs(24) - uLO_Aqueous) /(uHI_Aqueous -uLO_Aqueous)-K_Aqueous*act_Aqueous*((SP_Aqueous-yLO_Aqueous)/(yHI_Aqueous-yLO_Aqueous)-yyy_Aqueous(Ntau_Aqueous));
%-----------------------------------------------------------------------------
%MV24: Column Bottom Exit is used to control the Column Bottom Level
SP_ColButtom=0.5;
K_ColButtom=1;
Ti_ColButtom=100;
act_ColButtom=-1;
mode_ColButtom=1;
Ponly_ColButtom=1;
ht_ColButtom=1/transmitter_sampling_frequency(25);
hc_ColButtom=1/controller_sampling_frequency(25);
uLO_ColButtom=0;
uHI_ColButtom=4.536;
ded_ColButtom=transmitter_deadtime(25);
tau_ColButtom=transmitter_lag;
yLO_ColButtom=0;
yHI_ColButtom=1;
Nded_ColButtom=1+transmitter_deadtime(25)*transmitter_sampling_frequency(25);
Ntau_ColButtom=1;
xxx_ColButtom(1)= (y_ss(21)-yLO_ColButtom) / (yHI_ColButtom -yLO_ColButtom);
for i=2:Nded_ColButtom
    xxx_ColButtom(i)= xxx_ColButtom(1);
end
for i=1:Ntau_ColButtom
    yyy_ColButtom(i)= xxx_ColButtom(Nded_ColButtom);
end
xi_ColButtom= (MVs(25) - uLO_ColButtom) /(uHI_ColButtom -uLO_ColButtom)-K_ColButtom*act_ColButtom*((SP_ColButtom-yLO_ColButtom)/(yHI_ColButtom-yLO_ColButtom)-yyy_ColButtom(Ntau_ColButtom));
%-----------------------------------------------------------------------------
%controller initialization
%MV26: Vaporizer Liquid Inlet is fixed at 2.1924 kmol/min
%-----------------------------------------------------------------------------

%-----------------------------------------------------------------------------
%initialize historical data vectors
x_history=[];
y_history=[];
u_history=[];
dx_history=[];
%initialize simulation parameters
tic
timer=0;
is_initial=0;
disturbance_ID=0;
%start simulation
for k=0:(model_sampling_frequency*minute)
    time=k/model_sampling_frequency; %in minute
    %initialize disturbances
    if (k/model_sampling_frequency)>=10
        switch selected_ID
        case 0
            ;
        case 1
            SP_TRCT=151;
        case 2
            SP_TRCT=165;
        case 3
            SP_H2OCol=0.18;
        case 4
            MVs(26)=2.64;
        case 5
            if (k/model_sampling_frequency)<15
                MVs(3)=0;
            end
        case 6
            if (k/model_sampling_frequency)<15
                MVs(1)=0;
            end
        case 7
             disturbance_ID=1;
        case 8
            if (k/model_sampling_frequency)<15
                disturbance_ID=2;
            else
                disturbance_ID=0;
            end
        end
    end
    %calculate state derivatives and measurements
    [dstatedt,states,MVs,y_ss]=VAModel(states,MVs,time,is_initial,disturbance_ID);
    %in this example, we assume the setpoint of the vaporizer pressure control is given by the current gas recycle pressure
    SP_PresVap=y_ss(12);
    %command window display refreshing rate
    if rem(k,display_sampling_frequency*model_sampling_frequency)==0
        [error, indx]=max(abs(dstatedt./states));
%        info=['minute: ' num2str(time) '    max_dxdt_error: ' num2str(error) '    location: ' num2str(indx)];
 %       disp(info);
    end
    %save information
    if rem(k,storage_sampling_frequency*model_sampling_frequency)==0
        x_history=[x_history;states'];
        y_history=[y_history;[y_ss(37);y_ss(12);y_ss(23);y_ss(2);y_ss(1);y_ss(4);y_ss(5);y_ss(9);y_ss(10);MVs(10);y_ss(11);y_ss(13);MVs(13);y_ss(14);MVs(15);y_ss(15);y_ss(31);y_ss(33);y_ss(8);y_ss(28);y_ss(22);y_ss(20);y_ss(18);y_ss(19);y_ss(21);MVs(26);y_ss(27)]'];
        u_history=[u_history;MVs'];
        dx_history=[dx_history;dstatedt'];
    end
    %update states
    states=states+(1/model_sampling_frequency)*dstatedt;
    %controller action
    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(1))==0 & k~=0
        [xxx_O2, yyy_O2]=Transmit(y_ss(37), xxx_O2, yyy_O2, ded_O2, tau_O2, Nded_O2, Ntau_O2, ht_O2, yLO_O2, yHI_O2);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(1))==0 & k~=0
        [MVs(1),xi_O2,flag_O2]=controller(SP_O2, yyy_O2(Ntau_O2), MVs(1), xi_O2, mode_O2, K_O2, Ti_O2, hc_O2,...
            yLO_O2, yHI_O2, uLO_O2, uHI_O2, act_O2, Ponly_O2, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(2))==0 & k~=0
        [xxx_C2H4, yyy_C2H4]=Transmit(y_ss(12), xxx_C2H4, yyy_C2H4, ded_C2H4, tau_C2H4, Nded_C2H4, Ntau_C2H4, ht_C2H4, yLO_C2H4, yHI_C2H4);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(2))==0 & k~=0
        [MVs(2),xi_C2H4,flag_C2H4]=controller(SP_C2H4, yyy_C2H4(Ntau_C2H4), MVs(2), xi_C2H4, mode_C2H4, K_C2H4, Ti_C2H4, hc_C2H4,...
            yLO_C2H4, yHI_C2H4, uLO_C2H4, uHI_C2H4, act_C2H4, Ponly_C2H4, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(3))==0 & k~=0
        [xxx_HAc, yyy_HAc]=Transmit(y_ss(23), xxx_HAc, yyy_HAc, ded_HAc, tau_HAc, Nded_HAc, Ntau_HAc, ht_HAc, yLO_HAc, yHI_HAc);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(3))==0 & k~=0
        [MVs(3),xi_HAc,flag_HAc]=controller(SP_HAc, yyy_HAc(Ntau_HAc), MVs(3), xi_HAc, mode_HAc, K_HAc, Ti_HAc, hc_HAc,...
            yLO_HAc, yHI_HAc, uLO_HAc, uHI_HAc, act_HAc, Ponly_HAc, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(4))==0 & k~=0
        [xxx_LevelVap, yyy_LevelVap]=Transmit(y_ss(2), xxx_LevelVap, yyy_LevelVap, ded_LevelVap, tau_LevelVap, Nded_LevelVap, Ntau_LevelVap, ht_LevelVap, yLO_LevelVap, yHI_LevelVap);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(4))==0 & k~=0
        [MVs(4),xi_LevelVap,flag_LevelVap]=controller(SP_LevelVap, yyy_LevelVap(Ntau_LevelVap), MVs(4), xi_LevelVap, mode_LevelVap, K_LevelVap, Ti_LevelVap, hc_LevelVap,...
            yLO_LevelVap, yHI_LevelVap, uLO_LevelVap, uHI_LevelVap, act_LevelVap, Ponly_LevelVap, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(5))==0 & k~=0
        [xxx_PresVap, yyy_PresVap]=Transmit(y_ss(1), xxx_PresVap, yyy_PresVap, ded_PresVap, tau_PresVap, Nded_PresVap, Ntau_PresVap, ht_PresVap, yLO_PresVap, yHI_PresVap);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(5))==0 & k~=0
        [MVs(5),xi_PresVap,flag_PresVap]=controller(SP_PresVap, yyy_PresVap(Ntau_PresVap), MVs(5), xi_PresVap, mode_PresVap, K_PresVap, Ti_PresVap, hc_PresVap,...
            yLO_PresVap, yHI_PresVap, uLO_PresVap, uHI_PresVap, act_PresVap, Ponly_PresVap, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(6))==0 & k~=0
        [xxx_ReactorInletTemp, yyy_ReactorInletTemp]=Transmit(y_ss(4), xxx_ReactorInletTemp, yyy_ReactorInletTemp, ded_ReactorInletTemp, tau_ReactorInletTemp, Nded_ReactorInletTemp, Ntau_ReactorInletTemp, ht_ReactorInletTemp, yLO_ReactorInletTemp, yHI_ReactorInletTemp);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(6))==0 & k~=0
        [MVs(6),xi_ReactorInletTemp,flag_ReactorInletTemp]=controller(SP_ReactorInletTemp, yyy_ReactorInletTemp(Ntau_ReactorInletTemp), MVs(6), xi_ReactorInletTemp, mode_ReactorInletTemp, K_ReactorInletTemp, Ti_ReactorInletTemp, hc_ReactorInletTemp,...
            yLO_ReactorInletTemp, yHI_ReactorInletTemp, uLO_ReactorInletTemp, uHI_ReactorInletTemp, act_ReactorInletTemp, Ponly_ReactorInletTemp, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(7))==0 & k~=0
        [xxx_TRCT, yyy_TRCT]=Transmit(y_ss(5), xxx_TRCT, yyy_TRCT, ded_TRCT, tau_TRCT, Nded_TRCT, Ntau_TRCT, ht_TRCT, yLO_TRCT, yHI_TRCT);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(7))==0 & k~=0
        [MVs(7),xi_TRCT,flag_TRCT]=controller(SP_TRCT, yyy_TRCT(Ntau_TRCT), MVs(7), xi_TRCT, mode_TRCT, K_TRCT, Ti_TRCT, hc_TRCT,...
            yLO_TRCT, yHI_TRCT, uLO_TRCT, uHI_TRCT, act_TRCT, Ponly_TRCT, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(8))==0 & k~=0
        [xxx_LevelSep, yyy_LevelSep]=Transmit(y_ss(9), xxx_LevelSep, yyy_LevelSep, ded_LevelSep, tau_LevelSep, Nded_LevelSep, Ntau_LevelSep, ht_LevelSep, yLO_LevelSep, yHI_LevelSep);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(8))==0 & k~=0
        [MVs(8),xi_LevelSep,flag_LevelSep]=controller(SP_LevelSep, yyy_LevelSep(Ntau_LevelSep), MVs(8), xi_LevelSep, mode_LevelSep, K_LevelSep, Ti_LevelSep, hc_LevelSep,...
            yLO_LevelSep, yHI_LevelSep, uLO_LevelSep, uHI_LevelSep, act_LevelSep, Ponly_LevelSep, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(9))==0 & k~=0
        [xxx_TempSep, yyy_TempSep]=Transmit(y_ss(10), xxx_TempSep, yyy_TempSep, ded_TempSep, tau_TempSep, Nded_TempSep, Ntau_TempSep, ht_TempSep, yLO_TempSep, yHI_TempSep);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(9))==0 & k~=0
        [MVs(9),xi_TempSep,flag_TempSep]=controller(SP_TempSep, yyy_TempSep(Ntau_TempSep), MVs(9), xi_TempSep, mode_TempSep, K_TempSep, Ti_TempSep, hc_TempSep,...
            yLO_TempSep, yHI_TempSep, uLO_TempSep, uHI_TempSep, act_TempSep, Ponly_TempSep, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(11))==0 & k~=0
        [xxx_CompOutletTemp, yyy_CompOutletTemp]=Transmit(y_ss(11), xxx_CompOutletTemp, yyy_CompOutletTemp, ded_CompOutletTemp, tau_CompOutletTemp, Nded_CompOutletTemp, Ntau_CompOutletTemp, ht_CompOutletTemp, yLO_CompOutletTemp, yHI_CompOutletTemp);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(11))==0 & k~=0
        [MVs(11),xi_CompOutletTemp,flag_CompOutletTemp]=controller(SP_CompOutletTemp, yyy_CompOutletTemp(Ntau_CompOutletTemp), MVs(11), xi_CompOutletTemp, mode_CompOutletTemp, K_CompOutletTemp, Ti_CompOutletTemp, hc_CompOutletTemp,...
            yLO_CompOutletTemp, yHI_CompOutletTemp, uLO_CompOutletTemp, uHI_CompOutletTemp, act_CompOutletTemp, Ponly_CompOutletTemp, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(12))==0 & k~=0
        [xxx_LevelAbs, yyy_LevelAbs]=Transmit(y_ss(13), xxx_LevelAbs, yyy_LevelAbs, ded_LevelAbs, tau_LevelAbs, Nded_LevelAbs, Ntau_LevelAbs, ht_LevelAbs, yLO_LevelAbs, yHI_LevelAbs);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(12))==0 & k~=0
        [MVs(12),xi_LevelAbs,flag_LevelAbs]=controller(SP_LevelAbs, yyy_LevelAbs(Ntau_LevelAbs), MVs(12), xi_LevelAbs, mode_LevelAbs, K_LevelAbs, Ti_LevelAbs, hc_LevelAbs,...
            yLO_LevelAbs, yHI_LevelAbs, uLO_LevelAbs, uHI_LevelAbs, act_LevelAbs, Ponly_LevelAbs, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(14))==0 & k~=0
        [xxx_CircOutletTemp, yyy_CircOutletTemp]=Transmit(y_ss(14), xxx_CircOutletTemp, yyy_CircOutletTemp, ded_CircOutletTemp, tau_CircOutletTemp, Nded_CircOutletTemp, Ntau_CircOutletTemp, ht_CircOutletTemp, yLO_CircOutletTemp, yHI_CircOutletTemp);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(14))==0 & k~=0
        [MVs(14),xi_CircOutletTemp,flag_CircOutletTemp]=controller(SP_CircOutletTemp, yyy_CircOutletTemp(Ntau_CircOutletTemp), MVs(14), xi_CircOutletTemp, mode_CircOutletTemp, K_CircOutletTemp, Ti_CircOutletTemp, hc_CircOutletTemp,...
            yLO_CircOutletTemp, yHI_CircOutletTemp, uLO_CircOutletTemp, uHI_CircOutletTemp, act_CircOutletTemp, Ponly_CircOutletTemp, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(16))==0 & k~=0
        [xxx_ScrubOutletTemp, yyy_ScrubOutletTemp]=Transmit(y_ss(15), xxx_ScrubOutletTemp, yyy_ScrubOutletTemp, ded_ScrubOutletTemp, tau_ScrubOutletTemp, Nded_ScrubOutletTemp, Ntau_ScrubOutletTemp, ht_ScrubOutletTemp, yLO_ScrubOutletTemp, yHI_ScrubOutletTemp);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(16))==0 & k~=0
        [MVs(16),xi_ScrubOutletTemp,flag_ScrubOutletTemp]=controller(SP_ScrubOutletTemp, yyy_ScrubOutletTemp(Ntau_ScrubOutletTemp), MVs(16), xi_ScrubOutletTemp, mode_ScrubOutletTemp, K_ScrubOutletTemp, Ti_ScrubOutletTemp, hc_ScrubOutletTemp,...
            yLO_ScrubOutletTemp, yHI_ScrubOutletTemp, uLO_ScrubOutletTemp, uHI_ScrubOutletTemp, act_ScrubOutletTemp, Ponly_ScrubOutletTemp, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(17))==0 & k~=0
        [xxx_CO2, yyy_CO2]=Transmit(y_ss(31), xxx_CO2, yyy_CO2, ded_CO2, tau_CO2, Nded_CO2, Ntau_CO2, ht_CO2, yLO_CO2, yHI_CO2);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(17))==0 & k~=0
        [MVs(17),xi_CO2,flag_CO2]=controller(SP_CO2, yyy_CO2(Ntau_CO2), MVs(17), xi_CO2, mode_CO2, K_CO2, Ti_CO2, hc_CO2,...
            yLO_CO2, yHI_CO2, uLO_CO2, uHI_CO2, act_CO2, Ponly_CO2, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(18))==0 & k~=0
        [xxx_C2H6, yyy_C2H6]=Transmit(y_ss(33), xxx_C2H6, yyy_C2H6, ded_C2H6, tau_C2H6, Nded_C2H6, Ntau_C2H6, ht_C2H6, yLO_C2H6, yHI_C2H6);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(18))==0 & k~=0
        [MVs(18),xi_C2H6,flag_C2H6]=controller(SP_C2H6, yyy_C2H6(Ntau_C2H6), MVs(18), xi_C2H6, mode_C2H6, K_C2H6, Ti_C2H6, hc_C2H6,...
            yLO_C2H6, yHI_C2H6, uLO_C2H6, uHI_C2H6, act_C2H6, Ponly_C2H6, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(19))==0 & k~=0
        [xxx_FEHE, yyy_FEHE]=Transmit(y_ss(8), xxx_FEHE, yyy_FEHE, ded_FEHE, tau_FEHE, Nded_FEHE, Ntau_FEHE, ht_FEHE, yLO_FEHE, yHI_FEHE);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(19))==0 & k~=0
        [MVs(19),xi_FEHE,flag_FEHE]=controller(SP_FEHE, yyy_FEHE(Ntau_FEHE), MVs(19), xi_FEHE, mode_FEHE, K_FEHE, Ti_FEHE, hc_FEHE,...
            yLO_FEHE, yHI_FEHE, uLO_FEHE, uHI_FEHE, act_FEHE, Ponly_FEHE, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(20))==0 & k~=0
        [xxx_H2OCol, yyy_H2OCol]=Transmit(y_ss(28), xxx_H2OCol, yyy_H2OCol, ded_H2OCol, tau_H2OCol, Nded_H2OCol, Ntau_H2OCol, ht_H2OCol, yLO_H2OCol, yHI_H2OCol);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(20))==0 & k~=0
        [MVs(20),xi_H2OCol,flag_H2OCol]=controller(SP_H2OCol, yyy_H2OCol(Ntau_H2OCol), MVs(20), xi_H2OCol, mode_H2OCol, K_H2OCol, Ti_H2OCol, hc_H2OCol,...
            yLO_H2OCol, yHI_H2OCol, uLO_H2OCol, uHI_H2OCol, act_H2OCol, Ponly_H2OCol, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(21))==0 & k~=0
        [xxx_TempCol, yyy_TempCol]=Transmit(y_ss(22), xxx_TempCol, yyy_TempCol, ded_TempCol, tau_TempCol, Nded_TempCol, Ntau_TempCol, ht_TempCol, yLO_TempCol, yHI_TempCol);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(21))==0 & k~=0
        [MVs(21),xi_TempCol,flag_TempCol]=controller(SP_TempCol, yyy_TempCol(Ntau_TempCol), MVs(21), xi_TempCol, mode_TempCol, K_TempCol, Ti_TempCol, hc_TempCol,...
            yLO_TempCol, yHI_TempCol, uLO_TempCol, uHI_TempCol, act_TempCol, Ponly_TempCol, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(22))==0 & k~=0
        [xxx_DecanterTemp, yyy_DecanterTemp]=Transmit(y_ss(20), xxx_DecanterTemp, yyy_DecanterTemp, ded_DecanterTemp, tau_DecanterTemp, Nded_DecanterTemp, Ntau_DecanterTemp, ht_DecanterTemp, yLO_DecanterTemp, yHI_DecanterTemp);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(22))==0 & k~=0
        [MVs(22),xi_DecanterTemp,flag_DecanterTemp]=controller(SP_DecanterTemp, yyy_DecanterTemp(Ntau_DecanterTemp), MVs(22), xi_DecanterTemp, mode_DecanterTemp, K_DecanterTemp, Ti_DecanterTemp, hc_DecanterTemp,...
            yLO_DecanterTemp, yHI_DecanterTemp, uLO_DecanterTemp, uHI_DecanterTemp, act_DecanterTemp, Ponly_DecanterTemp, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(23))==0 & k~=0
        [xxx_Organic, yyy_Organic]=Transmit(y_ss(18), xxx_Organic, yyy_Organic, ded_Organic, tau_Organic, Nded_Organic, Ntau_Organic, ht_Organic, yLO_Organic, yHI_Organic);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(23))==0 & k~=0
        [MVs(23),xi_Organic,flag_Organic]=controller(SP_Organic, yyy_Organic(Ntau_Organic), MVs(23), xi_Organic, mode_Organic, K_Organic, Ti_Organic, hc_Organic,...
            yLO_Organic, yHI_Organic, uLO_Organic, uHI_Organic, act_Organic, Ponly_Organic, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(24))==0 & k~=0
        [xxx_Aqueous, yyy_Aqueous]=Transmit(y_ss(19), xxx_Aqueous, yyy_Aqueous, ded_Aqueous, tau_Aqueous, Nded_Aqueous, Ntau_Aqueous, ht_Aqueous, yLO_Aqueous, yHI_Aqueous);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(24))==0 & k~=0
        [MVs(24),xi_Aqueous,flag_Aqueous]=controller(SP_Aqueous, yyy_Aqueous(Ntau_Aqueous), MVs(24), xi_Aqueous, mode_Aqueous, K_Aqueous, Ti_Aqueous, hc_Aqueous,...
            yLO_Aqueous, yHI_Aqueous, uLO_Aqueous, uHI_Aqueous, act_Aqueous, Ponly_Aqueous, 0, 0, 0, 0);
    end

    if rem(k,model_sampling_frequency/transmitter_sampling_frequency(25))==0 & k~=0
        [xxx_ColButtom, yyy_ColButtom]=Transmit(y_ss(21), xxx_ColButtom, yyy_ColButtom, ded_ColButtom, tau_ColButtom, Nded_ColButtom, Ntau_ColButtom, ht_ColButtom, yLO_ColButtom, yHI_ColButtom);
    end
    if rem(k,model_sampling_frequency/controller_sampling_frequency(25))==0 & k~=0
        [MVs(25),xi_ColButtom,flag_ColButtom]=controller(SP_ColButtom, yyy_ColButtom(Ntau_ColButtom), MVs(25), xi_ColButtom, mode_ColButtom, K_ColButtom, Ti_ColButtom, hc_ColButtom,...
            yLO_ColButtom, yHI_ColButtom, uLO_ColButtom, uHI_ColButtom, act_ColButtom, Ponly_ColButtom, 0, 0, 0, 0);
    end

end
toc
%plot graphics
my_label=['   %O2  ';'  Pres  ';'  HAc-L ';'  Vap-L ';'  Vap-P ';'  Pre-T ';'  RCT-T ';'  Sep-L ';'  Sep-T ';'  Sep-V ';'  Com-T ';'  Abs-L ';'  Cir-F ';'  Cir-T ';'  Scr-F ';'  Scr-T ';'  %CO2  ';'  %C2H6 ';' FEHE-T ';'  %H2O  ';'  Col-T ';'  Org-L ';'  Aqu-L ';'  Col-L ';' Vap-In ';' Dect-T ';'%VAc E-3'];
MV_label=[' F-O2 ';'F-C2H4';' F-HAc';' Q-Vap';' F-Vap';'Q-Heat';'ShellT';'F-SepL';' T-Sep';'F-SepV';'Q-Comp';'F-AbsL';'F-Circ';'Q-Circ';'F-Scru';'Q-Scru';' F-CO2';' Purge';'bypass';'Reflux';'Q-Rebo';'F-Orga';'F-Aque';' F-Bot';'Q_Cond';'F-Tank'];
setpoint=[SP_O2;SP_C2H4;SP_HAc;SP_LevelVap;SP_PresVap;150;SP_TRCT;SP_LevelSep;SP_TempSep;16.1026;80;SP_LevelAbs;15.1198;25;0.756;25;SP_CO2;SP_C2H6;SP_FEHE;SP_H2OCol;SP_TempCol;0.5;0.5;SP_ColButtom;45.845;2.1924];
warning off
if selected_ID==1
    McAvoy_Plot_1(y_history,u_history,setpoint,my_label,MV_label,storage_sampling_frequency);
elseif selected_ID==2
    McAvoy_Plot_2(y_history,u_history,setpoint,my_label,MV_label,storage_sampling_frequency);
elseif selected_ID==3
    McAvoy_Plot_3(y_history,u_history,setpoint,my_label,MV_label,storage_sampling_frequency);
elseif selected_ID==4
    McAvoy_Plot_4(y_history,u_history,setpoint,my_label,MV_label,storage_sampling_frequency);
else
    Transient_Plot(y_history,u_history,setpoint,my_label,MV_label,storage_sampling_frequency);
end
return


function [collect] = ft_channelcombination(channelcmb, datachannel, includeauto, dirflag)

% FT_CHANNELCOMBINATION creates a cell-array with combinations of EEG/MEG
% channels for subsequent cross-spectral-density and coherence analysis
%
% You should specify channel combinations as a two-column cell-array,
%   cfg.channelcmb = {  'EMG' 'MLF31'
%                       'EMG' 'MLF32'
%                       'EMG' 'MLF33' };
% to compare EMG with these three sensors, or
%   cfg.channelcmb = { 'MEG' 'MEG' };
% to make all MEG combinations, or
%   cfg.channelcmb = { 'EMG' 'MEG' };
% to make all combinations between the EMG and all MEG channels.
%
% For each column, you can specify a mixture of real channel labels
% and of special strings that will be replaced by the corresponding
% channel labels. Channels that are not present in the raw datafile
% are automatically removed from the channel list.
%
% When directional connectivity measures will subsequently be computed, the
% interpretation of each channel-combination is that the direction of the
% interaction is from the first column to the second column.
%
% Note that the default behavior is to exclude symmetric pairs and
% auto-combinations.
%
% See also FT_CHANNELSELECTION

% Undocumented options:
%   includeauto = 0 (or 1), include auto-combinations
%   dirflag     = 0 (or 1, or 2) specifies the treatment of the order in
%                   the columns of the output. If dirflag = 0, the order is
%                   preserved, if dirflag = 1, the order is reversed,
%                   second input column is put first. If dirflag = 2, both
%                   directions are added to the list of combinations.

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

if nargin<3 || isempty(includeauto), includeauto = 0; end
if nargin<4 || isempty(dirflag),     dirflag     = 0; end

% ensure that datachannel is a column vector
datachannel = datachannel(:);

if ischar(channelcmb) && strcmp(channelcmb, 'all')
  % make all possible combinations of all channels
  channelcmb = {'all' 'all'};
end

% it should have a selection of two channels or channelgroups in each row
if size(channelcmb,1)==2 && size(channelcmb,2)~=2
  ft_warning('transposing channelcombination matrix');
  channelcmb = channelcmb';
end

% allow for channelcmb to be a 1x2 cell-array containing cells
if numel(channelcmb)==2 && iscell(channelcmb{1}) && iscell(channelcmb{2})
  channelcmb{1} = ft_channelselection(channelcmb{1}, datachannel);
  channelcmb{2} = ft_channelselection(channelcmb{2}, datachannel);
  n1  = numel(channelcmb{1});
  n2  = numel(channelcmb{2});
  tmp = cell(n1*n2+n1+n2,2);
  for k = 1:n1
    tmp((k-1)*n2+(1:n2), 1) = channelcmb{1}(k);
    tmp((k-1)*n2+(1:n2), 2) = channelcmb{2};
    tmp(n2*k+(1:n1),     1) = channelcmb{1};
    tmp(n2*k+(1:n1),     2) = channelcmb{1};
    tmp(n2*k+n1+(1:n2),  1) = channelcmb{2};
    tmp(n2*k+n1+(1:n2),  2) = channelcmb{2};
  end
  collect = tmp;
  return;
end

if isempty(setdiff(channelcmb(:), datachannel))
  % there is not much to do, since there are no channelgroups with special names
  % each element of the input therefore already contains a proper channel name

  switch dirflag
    case 0
      % nothing to do
    case 1
      % switch the order
      channelcmb = channelcmb(:,[2 1]);
    case 2
      channelcmb = [channelcmb; channelcmb(:,[2 1])];
    otherwise
      ft_error('unknown value for input argument ''dirflag''');
  end
  collect = channelcmb;

  if includeauto
    autochannel = unique(channelcmb(:));
    for ch=1:numel(autochannel)
      collect = cat(1, collect, [autochannel(ch) autochannel(ch)]);
    end
  end

else
  % a combination is made for each row of the input selection after
  % translating the channel group (such as 'all') to the proper channel names
  % and within each set, double occurences and autocombinations are removed

  selmat = false(numel(datachannel));
  for sel=1:size(channelcmb,1)
    % translate both columns and subsequently make all combinations
    channelcmb1 = ft_channelselection(channelcmb(sel,1), datachannel);
    channelcmb2 = ft_channelselection(channelcmb(sel,2), datachannel);

    % translate both columns and subsequently make all combinations
    list1 = match_str(datachannel, channelcmb1);
    list2 = match_str(datachannel, channelcmb2);

    selmat(list1,list2) = true;

    if ~includeauto,
      % exclude the auto-combinations
      selmat = selmat & ~eye(size(selmat));
    else
      % ensure that the appropriate diagonal entries are filled
      autovec = false(numel(datachannel),1);
      autovec([list1(:);list2(:)]) = true;
      selmat = selmat | diag(autovec);
    end

    if dirflag==2,
      % also fill the other 'direction'
      selmat(list2,list1) = true;
    end
  end

  if dirflag<2
    % remove double occurrences
    selmat   = selmat & ~tril(selmat, -1)';
  end
  [i1, i2] = find(selmat);

  switch dirflag
    case 0
      % original behavior,
      % row-to-column, i.e. outflow according to FT's convention
      indx = [i1 i2];
    case 1
      % column-to-row, i.e. inflow according to FT's convention
      indx = [i2 i1];
    case 2
      % both
      indx = [i1 i2];

    otherwise
      ft_error('unknown value for input argument ''dirflag''');
  end

  collect = [datachannel(indx(:,1)) datachannel(indx(:,2))];
end


function OutputToCSV(whatData,writeTimeSeriesData,writeMasterFeatures)
% OutputToCSV     Outputs data to csv for external analysis
%
%---INPUTS:
% whatData, which hctsa .mat file to use (default: HCTSA.mat)
% writeTimeSeriesData, (logical)[false] whether to also output time-series data to file
% writeMasterFeatures, (logical)[false] whether to also output master operation info

% ------------------------------------------------------------------------------
% Copyright (C) 2020, Ben D. Fulcher <ben.d.fulcher@gmail.com>,
% <http://www.benfulcher.com>
%
% If you use this code for your research, please cite the following two papers:
%
% (1) B.D. Fulcher and N.S. Jones, "hctsa: A Computational Framework for Automated
% Time-Series Phenotyping Using Massive Feature Extraction, Cell Systems 5: 527 (2017).
% DOI: 10.1016/j.cels.2017.10.001
%
% (2) B.D. Fulcher, M.A. Little, N.S. Jones, "Highly comparative time-series
% analysis: the empirical structure of time series and their methods",
% J. Roy. Soc. Interface 10(83) 20130048 (2013).
% DOI: 10.1098/rsif.2013.0048
%
% This work is licensed under the Creative Commons
% Attribution-NonCommercial-ShareAlike 4.0 International License. To view a copy of
% this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/ or send
% a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View,
% California, 94041, USA.
% ------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
% Check inputs and set defaults
%-------------------------------------------------------------------------------
if nargin < 1 || isempty(whatData)
    whatData = 'raw';
end
if nargin < 2 || isempty(writeTimeSeriesData)
    writeTimeSeriesData = false;
end
if nargin < 3
    writeMasterFeatures = false;
end
theDelimiter = ',';
%-------------------------------------------------------------------------------

% Load in the hctsa data:
[TS_DataMat,TimeSeries,Operations,whatData] = TS_LoadData(whatData);

% Get the master operations
if writeMasterFeatures
    MasterOperations = TS_GetFromData(whatData,'MasterOperations');
end

% Get the quality info:
TS_Quality = TS_GetFromData(whatData,'TS_Quality');

% Put NaNs in TS_DataMat where good quality is lacking (ignoring the code):
TS_DataMat(TS_Quality~=0) = NaN;

%-------------------------------------------------------------------------------
% Output data matrix to file:
%-------------------------------------------------------------------------------
fileName = 'hctsa_datamatrix.csv';
dlmwrite(fileName,TS_DataMat,'delimiter',theDelimiter);
fprintf(1,'Wrote feature matrix to %s.\n',fileName);

%-------------------------------------------------------------------------------
% Output time-series data to file:
%-------------------------------------------------------------------------------
if writeTimeSeriesData
    numTimeSeries = height(TimeSeries);
    fprintf(1,'Writing time-series data for %u time series...\n',numTimeSeries);
    fileName = 'hctsa_timeseries-data.csv';
    fid = fopen(fileName,'w');
    for i = 1:numTimeSeries
        x = TimeSeries.Data{i};
        L = length(x);
        for t = 1:L-1
            fprintf(fid,'%.6g,',x(t)); % up to last value with commas
        end
        fprintf(fid,'%.6g\n',x(L)); % final value with new line
    end
    fclose(fid);
    fprintf(1,'Wrote comma-delimited time-series data (6-decimal precision) to %s.\n',fileName);
end

%-------------------------------------------------------------------------------
% Output time-series info to .csv file:
%-------------------------------------------------------------------------------
fileName = 'hctsa_timeseries-info.csv';
if strcmp(theDelimiter,',')
    doQuoteStrings = true;
    % warning(['The comma-delimited Keywords variable may cause trouble for ',...
        % 'the comma-delimited %s file: quoting strings should help'],fileName);
else
    doQuoteStrings = false;
end

% We don't want the data to be written out in this info file:
v = version;
if str2double(v(1:3)) < 9.4
    % 2017 or older MATLAB version
    TimeSeries(:,'Data') = [];
else
    TimeSeries = removevars(TimeSeries,{'Data'});
end
writetable(TimeSeries,fileName,'FileType','text','WriteVariableNames',true,...
                'Delimiter',theDelimiter,'QuoteStrings',doQuoteStrings)
fprintf(1,'Wrote the TimeSeries table to %s.\n',fileName);

%-------------------------------------------------------------------------------
% Output feature info to file:
%-------------------------------------------------------------------------------
fileName = 'hctsa_features.csv';
writetable(Operations,fileName,'FileType','text','WriteVariableNames',true,...
                            'Delimiter',theDelimiter)
fprintf(1,'Wrote the Operations table to %s.\n',fileName);

%-------------------------------------------------------------------------------
% Output master features info to file:
%-------------------------------------------------------------------------------
if writeMasterFeatures
    fileName = 'hctsa_masterfeatures.csv';
    writetable(MasterOperations,fileName,'FileType','text','WriteVariableNames',true,...
                                'Delimiter',theDelimiter)
    fprintf(1,'Wrote the MasterOperations table to %s.\n',fileName);
end

%-------------------------------------------------------------------------------
% Output time-series group info to file:
% (it's accessible from the time-series table)
%-------------------------------------------------------------------------------
% if ismember('Group',TimeSeries.Properties.VariableNames)
%     fileName = 'hctsa_grouplabel-info.csv';
%     fid = fopen(fileName,'w');
%     % Header:
%     fprintf(fid,'%s%s%s\n','Name',theDelimiter,'Group');
%     for i = 1:height(TimeSeries)
%         fprintf(fid,'%s%s%u\n',TimeSeries.Name{i},theDelimiter,TimeSeries.Group(i));
%     end
%     fclose(fid);
%     fprintf(1,'Wrote time-series info to %s.\n',fileName);
% end

end


  function strum_test
%|function strum_test
%| test strum object
%| Copyright 2006-1-19, Jeff Fessler, University of Michigan

dat.a = 'x';
dat.b = 'y';

imp10 = @(st) st.b;
imp11 = @(st, arg) [st.a arg];
imp12 = @(st, arg1, arg2) sum(arg1) + sum(arg2);

list = { ...
	'fun10', @strum_test_fun10, '()'; ...
	'fun11', @strum_test_fun11, '(arg)'; ...
	'fun12', @strum_test_fun12, '(arg1, arg2)'; ...
	'imp11', imp11, '(arg)'; ...
	'imp12', imp12, '(arg1, arg2)'; ...
};

% no longer attempting anything but exactly 1 output so comment out these:
%	'fun00', @strum_test_fun00, '()'; ...
%	'fun22', @strum_test_fun22, '(arg1, arg2)'; ...

for ii=1:2
	if ii==1
		st = strum(dat, list); % with comment
	else
		tmp = col(list(:,1:2)');
		st = strum(dat, tmp); % without comment
	end
	st.a;
	st.b;
	jf_equal(st.fun10(), dat.a)
	jf_equal(st.fun11('d'), [dat.a 'd'])
	jf_equal(st.fun12('d', 'e'), [dat.a 'd' 'e'])
	jf_equal(st.imp11('d'), imp11(dat, 'd'))
	jf_equal(st.imp12(1:2, 3:4), imp12(dat, 1:2, 3:4))

	% augment base strum with more data and methods
	new.c = {10, 20};
	new.d = 'z';
	if ii==1
		s2 = strum(new, {'imp10', imp10, 'imp10()'}, 'base', st);
	else
		s2 = strum(new, {'imp10', imp10}, 'base', st);
	end
	jf_equal(s2.d, 'z')
	jf_equal(s2.imp10(), st.b)

	% cell arguments
	new.c{1};
	s2.c{1};
	jf_equal(s2.c{1}, new.c{1})
	jf_equal(s2.c{2}, new.c{2})

%	s2.c{1:2} % fails due to matlab limitation
%	s2.c{:} % ""
	tmp = s2.c; jf_equal(new.c, tmp) % this is the workaround
end

if 0 % old attempt to see if two outputs would work (it does not)
	st = strum(dat, {'fun22', @strum_test_fun22});
	jf_equal(st.fun22('c', 'd'), 'xc')
%	[a b] = st.fun22('c', 'd'); % "Too many output arguments" says matlab

	try
		[a b] = st.fun22(3, 4)
		printm 'multiple outputs worked!'
	catch
		warn 'darn, matlab cannot handle multiple outputs, as matt said'
	end
end

function strum_test_fun00(ob) % 0 out, 0 in
printm 'ok'

function a = strum_test_fun10(ob) % 1 out, 0 in
a = ob.a;

function out = strum_test_fun11(ob, arg) % 1 out, 1 in
out = [ob.a arg];

function out = strum_test_fun12(ob, arg1, arg2) % 1 out, 2 in
out = [ob.a arg1 arg2];

function [a, b] = strum_test_fun22(ob, arg1, arg2) % 2 out, 2 in
a = [ob.a arg1];
b = [ob.b arg2];


function [uCA,ndx,pos] = uniqueRowsCA(iCA,TREAT_NAN_EQUAL,FIRST_LAST)
%uniqueRowsCA  unique Rows for a Cell Array
%   U_CA = uniqueRowsCA(I_CA) returns Unique rows of the Input Cell Array, I_CA
%
%   [U_CA,I,J] = uniqueRowsCA(...) also returns index vectors I and J such
%   that U_CA = iCA(I,:) and iCA = B(J,:).
%
%   uniqueRowsCA(I_CA,TREAT_NAN_EQUAL), treats NaN comparisions as equal if
%   TREAT_NAN_EQUAL is true, the default is to treat NaN as equal
%
%   uniqueRowsCA(I_CA,[],'first'), returns the first instance
%   of the match of the index where I_CA matches U_CA, the default
%   is 'last'
%
%   NOTE: This function only handles strings and scalars, and N-D matrices
%   that are the same size for every row within the same column
%
%   See also: isequal, isequalwithequalnans

    %INPUT HANDLING
    %===========================================================
    if nargin == 1, TREAT_NAN_EQUAL = true; FIRST_LAST = 'last';
    elseif nargin == 2,
        if isempty(TREAT_NAN_EQUAL)
            TREAT_NAN_EQUAL = true;
        end
    elseif nargin ~= 3
        error('Incorrect number of input arguments to %s',mfilename)
    end

    %SOME BASIC INITIALIZATION
    %=====================================================
    [M,N] = size(iCA);
    COL_ORDER = 1:N; %Could make this an input argument,
    %affects order of unique output => see sortrows

    %HANDLING THE SIMPLE CASE
    %======================================================
    if M == 1, uCA = iCA; ndx = 1; pos = 1; return, end

    %ERROR CHECKING - CHECK CONSISTENCY FOR EACH COLUMN
    %===========================================================
    for iCol = 1:N
        %NOT YET DONE
    end

    %THE SORT_CELL_BACK_TO_FRONT FUNCTION & SORTROWS
    %=================================================================
    %Note, cell2mat is very slow, rewrote sortrows

    ndx = (1:M)';
    for k = N:-1:1
        colUse = abs(COL_ORDER(k));
        %NOTE: right here we make an assumption about the types being consistent in a given column
        if isnumeric(iCA{1, colUse})
            sz = cellfun('prodofsize',iCA(:,colUse)); %sz = cellfun(@numel,iCA(:,k));
            if isempty(find(sz > 1,1))
                tmp = fastC2M(iCA(ndx,colUse));
                ind = sortrowsc(tmp, sign(COL_ORDER(k))*1);
            else %We are dealing with matrices

                %SOME ERROR CHECKING ON THE MATRICES
                %=========================================
                szS = cellfun(@size,iCA(:,colUse),'UniformOutput',false);

                %1) DIMENSION SAME CHECK
                %----------------------------------------------
                nDims = cellfun('ndims',szS);
                if length(unique(nDims)) ~= 1
                    error('%s not setup to handle varying size matrices yet',mfilename)
                end

                %2) EACH DIMENSION THE SAME CHECK
                %----------------------------------------------
                szMat = fastC2M(szS); %NOTE: we had to first check that each input is
                %the same size, i.e. that the dimensions were the same otherwise fastC2M barfs
                %We are checking dimensions here instead of number of elements as perhaps someone
                %cares if the dimensions are different, even though the linearized contents might
                %not be ex. a = [1 3;2 4] vs b = [1 2 3 4], size(a) = [2 2], size(b) = [1 4], but
                %all(a(:) == b(:)) is true, note that the matrix code linearizes the inputs for
                %sorting purposes
                curCol = 1;
                notMatchSz = [];
                while curCol <= nDims(1) && isempty(notMatchSz)
                    notMatchSz = find(diff(szMat(:,curCol)) ~= 0,1);
                    curCol = curCol + 1;
                end

                if ~isempty(notMatchSz)
                    error('%s not setup to handle varying size matrices yet',mfilename)
                end
                %=============================================

                tmp = fastC2M(iCA(ndx,colUse));
                ind = sortrowsc(tmp, sign(COL_ORDER(k))*(1:size(tmp,2)));
            end

        else
            tmp = char(iCA(ndx,k)); %Nice and quick
            ind = sortrowsc(tmp, sign(COL_ORDER(k))*(1:size(tmp,2)));
        end
        ndx = ndx(ind);
    end

    %NOW RESORTING AND OBTAINING UNIQUE
    %=========================================
    %NOTE: ndx is the 2nd output of sortrows
    iCA = iCA(ndx,:);

    sameVector = false(M,N);

    if TREAT_NAN_EQUAL
        for iCol = 1:N
            sameVector(2:end,iCol) = arrayfun(@isequalwithequalnans,iCA(2:end,iCol),iCA(1:end-1,iCol));
        end
    else
        for iCol = 1:N
            sameVector(2:end,iCol) = arrayfun(@isequal,iCA(2:end,iCol),iCA(1:end-1,iCol));
        end
    end

    d = ~all(sameVector,2);
    uCA = iCA(d,:);

    %ADDITIONAL OUTPUT HANDLING
    %===========================================
    if nargout == 3
        pos = cumsum(d);
        pos(ndx) = pos;             % Re-reference POS to indexing of SORT.
    end

    % Create indices if needed.
    if nargout > 1
        if FIRST_LAST(1) == 'l'
            ndx = ndx([d(2:end); true]);  % Final element is always a member of unique list.
        else
            ndx = ndx(d); % First element is always a member of unique list.
        end
    else
        ndx = [];
        pos = [];
    end
end

function m = fastC2M(CA)
%ASSUMPTIONS -> all elements of CA have the same size
%TO REPLACE SLOW CELL2MAT FOR MATRICES

    szCA = size(CA);
    sz = numel(CA{1});

    m = zeros(szCA(1),sz(1));
    for iRow = 1:szCA(1)
        m(iRow,:) = CA{iRow}(:);
    end
end


function stop = stopOutFun(x,optimValues,state)
stop = false;
if optimValues.constrviolation < 1e-9
    stop = true;
end
end


function varargout=rotpl2ro(varargin)
%
% For calling details please see v_rotpl2ro.m
%
% This dummy routine is included for backward compatibility only
% and will be removed in a future release of voicebox. Please use
% v_rotpl2ro.m in future and/or update with v_voicebox_update.m
%
%      Copyright (C) Mike Brookes 2018
%      Version: $Id: rotpl2ro.m 10863 2018-09-21 15:39:23Z dmb $
%
if nargout
    varargout=cell(1,nargout);
    [varargout{:}]=v_rotpl2ro(varargin{:});
else
    v_rotpl2ro(varargin{:});
end


  function hs = jf_add_slider(varargin)
%|function hs = jf_add_slider([options])
%|
%| add a slider control to the current figure to enable interaction
%|
%| option
%|	'callback'	@ (value,data{:})	function to call with
%|						slider value [0,1] and data
%|	'pos'		[l b w h]	slider position
%|	'data'		{}		data to be passed to callback
%|	'value'		0 <= x <= 1	initial slider value, default 0
%|
%| Copyright 2010-1-11, Jeff Fessler, University of Michigan

if ~nargin && ~nargout, ir_usage, end
if nargin && streq(varargin{1}, 'test'), jf_add_slider_test, return, end

arg.callback = @jf_add_slider_call;
arg.pos = [0.1, 0.0, 0.8, 0.03];
arg.data = {};
arg.name = '';
arg.value = 0;
arg.min = [];
arg.max = [];
arg.style = 'slider';
arg.sliderstep = [0.01 0.10];
arg.string = 'button';
arg = vararg_pair(arg, varargin);

args = {};
if ~isempty(arg.min)
	args = {args{:}, 'min', arg.min};
end
if ~isempty(arg.max)
	args = {args{:}, 'max', arg.max};
end

if isempty(arg.callback)
	arg.callback = @jf_add_slider_call_null;
end

% construct gui components
if ir_is_octave % && exist('uicontrol') ~= 2
	warn 'no uicontrol in octave'
	% todo: draw box or something?
else
	hs = uicontrol('style', arg.style, 'string', arg.string, ...
		'units', 'normalized', 'position', arg.pos, ...
		'value', arg.value, ...
		args{:}, ...
		'sliderstep', arg.sliderstep, ...
		'callback', {@jf_add_slider_callback});
end

if ~isempty(arg.name)
	set(gcf, 'name', arg.name) % assign GUI a name for window title
end

if ~nargout
	clear hs
end

% callbacks: these automatically have access to component handles
% and initialized data because they are nested at a lower level.

% slider callback
function jf_add_slider_callback(source, eventdata)
	val = get(source, 'value');
	arg.callback(val, arg.data{:});
end % jf_add_slider_callback

end % jf_add_slider

function jf_add_slider_call(value)
pr value
end % jf_add_slider_call

function jf_add_slider_call_null(value)
end % jf_add_slider_call_null

function jf_add_slider_test
jf_add_slider_test_call(0.5);
if im
	jf_add_slider('callback', @jf_add_slider_test_call, 'data', {gca}, ...
		'value', 0.5)
%	jf_add_slider_test_call(0);
	jf_add_slider('callback', @jf_add_slider_test_call, 'data', {gca}, ...
		'pos', [0.1 0.04 0.8 0.03], ...
		'value', 0, 'style', 'togglebutton', 'string', 'push me')
end
end % jf_add_slider_test

function jf_add_slider_test_call(value, h)
if isvar('h')
	axes(h)
end
if im
	plot([0 value], [0 value], '-')
	axis([0 1 0 1])
end
end % jf_add_slider_test_call


function res = getEigenVals(a)
res = a.eigenVals;


function imdb = voc_get_database(vocDir, varargin)
opts.seed = 1 ;
opts = vl_argparse(opts, varargin) ;

assert(opts.seed == 1) ; % there is only one split

imdb.imageDir = fullfile(vocDir, 'JPEGImages') ;
imdb.maskDir = fullfile(vocDir, 'Masks'); % doesn't exist
imdb.classes.name={...
  'aeroplane'
  'bicycle'
  'bird'
  'boat'
  'bottle'
  'bus'
  'car'
  'cat'
  'chair'
  'cow'
  'diningtable'
  'dog'
  'horse'
  'motorbike'
  'person'
  'pottedplant'
  'sheep'
  'sofa'
  'train'
  'tvmonitor'};
numClass = length(imdb.classes.name);

% source images
imageFiles = dir(fullfile(imdb.imageDir, '*.jpg'));
imdb.images.name = {imageFiles.name};
numImages = length(imdb.images.name);

imdb.images.label = zeros(numClass, numImages);
imdb.images.label = zeros(1, numImages);
imdb.images.set = zeros(1, numImages);
imdb.images.id = 1:numImages;
imdb.images.vocid = cellfun(@(S) S(1:end-4), imdb.images.name, 'UniformOutput', false);
imageSets = {'train', 'val', 'test'};

% Loop over classes load labels
for c = 1:numClass,
  for s = 1:length(imageSets);
    imageSetPath = fullfile(vocDir, 'ImageSets', 'Main', sprintf('%s_%s.txt', imdb.classes.name{c}, imageSets{s}));
    [gtids,gt]=textread(imageSetPath,'%s %d');
    [membership, loc] = ismember(gtids, imdb.images.vocid);
    assert(all(membership));
    imdb.images.label(c, loc) = gt ;
  end
end

% Loop over images and record the imag sets
for s = 1:length(imageSets),
  imageSetPath = fullfile(vocDir, 'ImageSets', 'Main', sprintf('%s.txt',imageSets{s}));
  gtids = textread(imageSetPath,'%s');
  [membership, loc] = ismember(gtids, imdb.images.vocid);
  assert(all(membership));
  imdb.images.set(loc) = s;
end

% Remove images not part of train, val, test sets
valid = ismember(imdb.images.set, 1:length(imageSets));
imdb.images.name = imdb.images.name(imdb.images.id(valid));
imdb.images.id = 1:numel(imdb.images.name);
imdb.images.label = imdb.images.label(:, valid);
imdb.images.set = imdb.images.set(valid);
imdb.images.vocid = imdb.images.vocid(valid);

% Write out the segments
imdb.segments = imdb.images ;
imdb.segments.imageId = imdb.images.id ;
imdb.segments.difficult = false(1, numel(imdb.segments.id)) ;
% no masks

% make this compatible with the OS imdb
imdb.meta.classes = imdb.classes.name ;
imdb.meta.inUse = true(1,numel(imdb.meta.classes)) ;


function [msh,lights,tenseMsh] = mrmConvertEMSEMesh(fileName,mmPerVox, host, id, varargin);
%
%  [msh,lights,tenseMsh] = mrmConvertEMSEMesh(fileName,mmPerVox, host, id, varargin);
%
%
% Author: ARW (based on RFD's mrmBuildMesh)
% Purpose:
%  Take a mesh in EMSE's .wfr format and convert it into a mrLoadRet /
%  mrMesh-type mesh. Allows you to do the usual mrMesh type things like
%  relaxation...
%  Additional processing options can be set as well.  These
%  options include:
%     * 'RelaxIterations'- the next value specifies how many extra smoothing iterations.
%     * 'SavetenseMsh'- if you specify any RelaxIterations and add this option, then
% you will get two meshes- the relaxed mesh and the unrelaxed (tense) mesh.
%
% Returns:
% The mesh structure and a lights structure.
% You can also get the unrelaxed mesh out (tenseMsh).
%
% See Also
%  mrmMapVerticesToGray
%
% Examples:
%   mrmConvertEMSEMesh('x:\anatomy\norcia\EMSE\test.wfr', view.mmPerVox, 'Background', [0.3,0.4,0.5]);
%   mrmBuildMesh('x:\anatomy\norcia\EMSE\test.wfr', view.mmPerVox, 'localhost', -1);
%   mrmBuildMesh('x:\anatomy\norcia\EMSE\test.wfr', view.mmPerVox, 'localhost', -1, ...
%                     'RelaxIterations', relaxIterations, 'SavetenseMsh');
%
% Notes:
%  2003.09.17 RFD: vertex-to-volume mapping is now done in a separate
%  function (mrmMapVerticesToGray), and we don't call it. So, the calling
%  function will need to compute that mapping and add the appropriate
%  fields to the mesh struct.

% transparency is off by default because it is slow.
mrGlobals;

summaryParams = 1;
meshName = '';
QueryFlag = 1;
relaxIter = 1;
saveTense = 0;
backColor = [0.2 0 0];  % CHanged from Gray - partly just to keep track of EMSE meshes...

if ieNotDefined('fileName'), error('EMSE format file is required.'); end
if ieNotDefined('mmPerVox'), error('mmPerVox is required.'); end
if ieNotDefined('host'), host = 'localhost'; end
if ieNotDefined('id'), id = 1; end

if(nargout>2),  saveTense = 1; end

% Parse the varargin values
for(ii=1:length(varargin))
    if    (strcmpi(varargin{ii}, 'RelaxIterations')), relaxIter = varargin{ii+1};
    elseif(strcmpi(varargin{ii}, 'QueryFlag')),       QueryFlag = varargin{ii+1};
    elseif(strcmpi(varargin{ii}, 'MeshName')),        meshName = varargin{ii+1};
    elseif (strcmpi(varargin{ii},'Background')),      backColor = varargin{ii+1};
    end
end

% Set initial parameters for the mesh.
msh = meshDefault(host,id,mmPerVox,relaxIter,meshName);

if QueryFlag,  msh = meshQuery(msh,summaryParams); end

% If the window is already open, no harm is done.
msh = mrmInitHostWindow(msh)

[msh, lights] = mrmInitMesh(msh,backColor);

disp('Importing mesh data from EMSE')
%

% ***************************************************************
% We need to construct a basic msh structure from the file data.
[vertex,face,edge,mesh]=mesh_emse2matlab2(fileName);

% Vertices come back rotated in an odd way. The entire cortex is rotated 90
% degrees about the L/R axis (i.e. the sag view is rotated 90degrees
% anticlockwise).
v=vertex(1:2,:);
v=v-128;

rotMat=[0 -1;1 0];
v=v'*rotMat;
vertex(1:2,:)=v'+128;
LR=vertex(3,:);

LR=(256-LR);
vertex(3,:)=LR;

face=face([3 2 1],:);

nVerts=length(vertex);

%vertex=vertex*10000;
p.vertices=(vertex);
p.triangles=face;
p.triangles = p.triangles - 1
p.class='mesh';

% Sometimes we pass in the whole array of meshes.  Mostly, just one,
% though.
host = meshGet(msh,'host');
windowID = meshGet(msh,'windowid');

if isempty(host), host = 'localhost'; end

if isempty(windowID), error('Mesh must specify a window'); end
%[id, status, result] = mrMesh ('localhost', windowID, 'add_actor', p)
p.scale = meshGet(msh,'mmPerVox');
p = setSmooth(p,msh,1);
p = setDecimate(p,msh,1);
p.actor = meshGet(msh,'actor');

p.colors=ones(4,length(p.vertices))*255;

[a,b,c]=mrmesh('localhost',id,'set_mesh',p)

        p.scale = meshGet(msh,'mmPerVox');
        p = setSmooth(p,msh,1);
        p = setDecimate(p,msh,1);
        %p.actor = meshGet(msh,'actor');
        p.normals=mrmGet(msh,'normals');
        p.actor = meshGet(msh,'actor');

%disp('Building smoothed and decimated mesh for display...');
%mrmSet(msh,'buildMeshAndDecimateAndSmooth',voxels);
%[msh] = mrmSet(msh,'smooth')

% This is a little 'center object' routine.  We could put this into mrmSet,
% really.
vertices = mrmGet(msh,'vertices');
mrmSet(msh,'origin',-mean(vertices'));

% Save these unsmoothed data.
unSmoothedData = mrmGet(msh,'data');
msh.initVertices=vertices;
msh.grayLayers=3;
view=getSelectedVolume;
    disp('Finding vertex to gray map');
    % You have to do this before smoothing...

v2gMap = mrmMapVerticesToGray(vertices,view.nodes,[1 1 1]);

msh.vertexGrayMap=v2gMap;
msh.grayToVertexMap = mrmMapGrayToVertices(view.nodes,vertices, [1 1 1]);

% Now also try to find the other mapping: the mapping from the mesh to all
% the gray nodes: So that we can ask: for any arbitray gray node, which
% mesh point is it closest to?

% If we smooth, the mesh, it is done here.
if(relaxIter>0)

    mrmSet(msh,'smooth');

    % We get the curvature colors from the uninflated mesh
    % We should figure out the correct value to use as our threshold. The mean
    % isn't ideal, since it is moved around by the large areas with arbitrary
    % curvature (eg. corpus callosum). What we really want is the value that
    % corresponds to zero curvature.
    % maybe make the specific curvature map colors adjustable?
    % We now use the actual curvature values, so we know that zero is zeros
    % curvature.
    disp('Setting up the curvature colors');

    % Attach curvature data to the mesh.  We turn on the color later, I think.
    msh=mrmSet(msh,'curvature');
    p.colors=[repmat(msh.curvature,3,1); ones(1,length(msh.curvature))]*255;
    %[a,b,c]=mrmesh('localhost',id,'set_mesh',p)

    curvColorIntensity = 128*meshGet(msh,'curvatureModDepth'); % mesh.curvature_mod_depth;

    monochrome = uint8(round((double(msh.curvature>0)*2-1)*curvColorIntensity+127.5));

    msh = mrmSet(msh,'colors',monochrome);

    disp('Storing the smoothed mesh data computed by mrMesh...');
    data = mrmGet(msh,'data');
    msh = meshSet(msh,'data',data);
    msh = meshSet(msh,'connectionMatrix',1);

else
    % We don't smooth the data with mrMesh.  We just assign it.
    msh = meshSet(msh,'data',unSmoothedData);
    msh = meshSet(msh,'connectionMatrix',1);
end

% In either case, we return a version of the data without smoothing.  This
% mesh is used to register with the gray coordinates.  This is a little
% disorganized.  If we don't smooth, tenseMesh is identically msh.
tenseMsh = msh;
tenseMsh = meshSet(tenseMsh,'data',unSmoothedData);

return;

%---------------------------------------
function p = setSmooth(p,mesh,val)
if val
    p.do_smooth = 1;
    p.smooth_iterations = meshGet(mesh,'smoothiterations');
    p.smooth_relaxation = meshGet(mesh,'smoothrelaxation');
    p.smooth_sinc_method = meshGet(mesh,'smoothmethod');
    p.do_smooth_pre = meshGet(mesh,'smooth_pre');
else
    p.do_smooth = 0;
    p.do_smooth_pre = 0;
end

return;

%----------------------------
function p = setDecimate(p,mesh,val)

if val
    p.do_decimate = 1;
    p.decimate_reduction = meshGet(mesh,'decimatereduction');
    p.decimate_iterations = meshGet(mesh,'decimateiterations');
else
    p.do_decimate = 0;
end

return;


function xyz_io_test04 ( )

%*****************************************************************************80
%
%% XYZ_IO_TEST04 tests XYZL_READ.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 January 2009
%
%  Author:
%
%    John Burkardt
%
  xyz_filename = 'cube.xyz';
  xyzl_filename = 'cube.xyzl';

  fprintf ( 1, '\n' );
  fprintf ( 1, 'XYZ_IO_TEST04\n' );
  fprintf ( 1, '  XYZ_HEADER_READ  reads the header of an XYZ  file.\n' );
  fprintf ( 1, '  XYZ_DATA_READ    reads the data   of an XYZ  file.\n' );
  fprintf ( 1, '  XYZL_HEADER_READ reads the header of an XYZL file.\n' );
  fprintf ( 1, '  XYZL_DATA_READ   reads the data   of an XYZL file.\n' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Examine XYZ file "%s".\n', xyz_filename );

  point_num = xyz_header_read ( xyz_filename );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of points = %d\n', point_num );

  xyz = xyz_data_read ( xyz_filename, point_num );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Point data:\n' );
  fprintf ( 1, '\n' );

  for i = 1 : point_num
    fprintf ( 1, '  %4d  %10f  %10f  %10f\n', i, xyz(1:3,i) );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Examine XYZL file "%s".\n', xyzl_filename );

  [ line_num, line_data_num ] = xyzl_header_read ( xyzl_filename );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of lines      = %d\n', line_num );
  fprintf ( 1, '  Number of line items = %d\n', line_data_num );

  [ line_pointer, line_data ] = xyzl_data_read ( xyzl_filename, line_num, ...
    line_data_num );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Line pointers:\n' );
  fprintf ( 1, '\n' );

  for line = 1 : line_num
    fprintf ( 1, '  %4d  %8d  %8d\n', line, line_pointer(line), ...
      line_pointer(line+1) - 1 );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Line data:\n' );
  fprintf ( 1, '\n' );

  for line = 1 : line_num
    fprintf ( 1, '  %4d    ', line );
    for j = line_pointer(line) : line_pointer(line+1) - 1
      fprintf ( 1, '  %8d', line_data(j) );
    end
    fprintf ( 1, '\n' );
  end

  return
end


function a = in( x, y )

narginchk(2,2);
b = newcnstr( evalin( 'caller', 'cvx_problem', '[]' ), x, y, '==' );
if nargout, a = b; end

% Copyright 2005-2016 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


classdef TestComposeRT
    %TestComposeRT

    properties (Constant)
        fields = {'rvec3', 'tvec3', 'dr3dr1', 'dr3dt1', ...
            'dr3dr2', 'dr3dt2', 'dt3dr1', 'dt3dt1', 'dt3dr2', 'dt3dt2'};
    end

    methods (Static)
        function test_1
            rvec1 = zeros(3,1);
            tvec1 = zeros(3,1);
            rvec2 = zeros(3,1);
            tvec2 = zeros(3,1);
            S = cv.composeRT(rvec1, tvec1, rvec2, tvec2);
            validateattributes(S, {'struct'}, {'scalar'});
            assert(all(ismember(TestComposeRT.fields, fieldnames(S))));
            cellfun(@(f) validateattributes(S.(f), {'double'}, ...
                {'vector', 'numel',3}), TestComposeRT.fields(1:2));
            cellfun(@(f) validateattributes(S.(f), {'double'}, ...
                {'2d', 'size',[3 3]}), TestComposeRT.fields(3:end));
        end

        function test_2
            rvec1 = rand(3,1, 'single');
            tvec1 = rand(3,1, 'single');
            rvec2 = rand(3,1, 'single');
            tvec2 = rand(3,1, 'single');
            S = cv.composeRT(rvec1, tvec1, rvec2, tvec2);
            validateattributes(S, {'struct'}, {'scalar'});
            assert(all(ismember(TestComposeRT.fields, fieldnames(S))));
            cellfun(@(f) validateattributes(S.(f), {'single'}, ...
                {'vector', 'numel',3}), TestComposeRT.fields(1:2));
            cellfun(@(f) validateattributes(S.(f), {'single'}, ...
                {'2d', 'size',[3 3]}), TestComposeRT.fields(3:end));
        end

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

end


startup;
[ params ] = setup_project_ht_WUSTL;

%1. retrieval
ht_retrieval;

%2. geometric verification
ht_top100_densePE_localization;

%3. pose verification
ht_top10_densePV_localization;


function Model = verifyModelBorg(Model, varargin)
% Ensures that a model is in the correct format to be analyzed
% by any of the scripts in the `Tmodel` suite. It will add fields that are
% missing and expected for comparison. It will remove fields not in this list.
% Called by  `driveModelBorgifier`, calls `TmodelFields`, `fixNames`, `removeDuplicateNames`,
% `makeNamesUnique`, `buildRxnEquations`, `fixChemFormulas`, `orderModelFieldsBorg`, `organizeModelCool`.
%
% USAGE:
%
%    Model = verifyModelBorg(Model)
%
% INPUTS:
%    Vmodel:        Model from `readCbModel` or any of the `readModel` functions.
%
% OPTIONAL INPUTS:
%    'keepName':    Don't ask for verification of model name
%    'Verbose':     Print steps.
%
% OUTPUTS:
%    Model:         Model with additional fields and correct format.
%
% Please cite:
% `Sauls, J. T., & Buescher, J. M. (2014). Assimilating genome-scale
% metabolic reconstructions with modelBorgifier. Bioinformatics
% (Oxford, England), 30(7), 1036?8`. http://doi.org/10.1093/bioinformatics/btt747
%
% ..
%    Edit the above text to modify the response to help addMetInfo
%    Last Modified by GUIDE v2.5 06-Dec-2013 14:19:28
%    This file is published under Creative Commons BY-NC-SA.
%
%    Correspondance:
%    johntsauls@gmail.com
%
%    Developed at:
%    BRAIN Aktiengesellschaft
%    Microbial Production Technologies Unit
%    Quantitative Biology and Sequencing Platform
%    Darmstaeter Str. 34-36
%    64673 Zwingenberg, Germany
%    www.brain-biotech.de

askForModelName = true ; % Declare variables.
verbose = false ;
if ~isempty(varargin)
    if sum(strcmp('keepName', varargin))
        askForModelName = false ;
    end
    if sum(strcmp('Verbose', varargin))
        verbose = true ;
    end
end

nRxns = length(Model.rxns);
nMets = length(Model.mets);

% Current Field names in the model.
fieldNames = fieldnames(Model);

% Get desired field names.
fields = TmodelFields ;
Field.rxn = fields{1};
Field.rNum = fields{2};
Field.met = fields{3};
Field.mNum = fields{4};
Field.all = fields{5};

%% Remove fields that will not be used
% This is a hacky solution, and unused fields should be carried forward
rmFieldNames = false(size(fieldNames)) ;
for iField = 1:length(fieldNames)
    if strmatch(fieldNames{iField}, Field.all)
        continue
    else
        rmFieldNames(iField) = 1 ;
    end
end
Model = rmfield(Model, fieldNames(rmFieldNames)) ;

%% Pad fields with empty strings or zeros.
% Reaction related cell arrays.
for iField = 1:length(Field.rxn)
   fieldIndex = strcmp(Field.rxn{iField}, fieldNames);
   fieldIndex = find(fieldIndex);
   if isempty(fieldIndex) % Field does not currently exist
       if verbose
           fprintf(['Array .' Field.rxn{iField} ' not in Model. Adding.\n'])
       end
       Model.(Field.rxn{iField}) = cell(nRxns, 1);
       Model.(Field.rxn{iField})(:) = {''};
   else % Field exists, check if the length is correct
       vFieldLength = length(Model.(fieldNames{fieldIndex}));
       for icell = 1:vFieldLength
           while iscell(Model.(fieldNames{fieldIndex}){icell})
               Model.(fieldNames{fieldIndex}){icell} = [Model.(fieldNames{fieldIndex}){icell}{:}] ;
           end
       end
       if vFieldLength ~= nRxns
           vFieldLength = vFieldLength + 1 ;
           Model.(fieldNames{fieldIndex})(vFieldLength:nRxns) = {''};
       end
   end
end

% Reaction related double arrays.
for iField = 1:length(Field.rNum)
   fieldIndex = strcmp(Field.rNum{iField}, fieldNames);
   fieldIndex = find(fieldIndex);
   if isempty(fieldIndex) % Field does not currently exist
       if verbose
           fprintf(['Array .' Field.rNum{iField} ' not in Model. Adding.\n'])
       end
       Model.(Field.rNum{iField}) = zeros(nRxns, 1);
   else % Field exists, check if the length is correct
       vFieldLength = length(Model.(fieldNames{fieldIndex}));
       if vFieldLength ~= nRxns
           vFieldLength = vFieldLength + 1 ;
           Model.(fieldNames{fieldIndex})(vFieldLength:nRxns) = 0 ;
       end
   end
end

% Metabolite related cell arrays.
for iField = 1:length(Field.met)
   fieldIndex = strcmp(Field.met{iField}, fieldNames);
   fieldIndex = find(fieldIndex);
   if isempty(fieldIndex) % Field does not currently exist
       if verbose
           fprintf(['Array .' Field.met{iField} ' not in Model. Adding.\n'])
       end
       Model.(Field.met{iField}) = cell(nMets, 1);
       Model.(Field.met{iField})(:) = {''};
   else % Field exists, check if the length is correct
       vFieldLength = length(Model.(fieldNames{fieldIndex}));
       % weed out cells in cells
       for icell = 1:vFieldLength
           while iscell(Model.(fieldNames{fieldIndex}){icell})
               Model.(fieldNames{fieldIndex}){icell} = [Model.(fieldNames{fieldIndex}){icell}{:}] ;
           end
       end
       if vFieldLength ~= nMets
           vFieldLength = vFieldLength + 1 ;
           Model.(fieldNames{fieldIndex})(vFieldLength:nMets) = {''};
       end
   end
end

% Metabolite related double arrays.
for iField = 1:length(Field.mNum)
   fieldIndex = strcmp(Field.mNum{iField}, fieldNames);
   fieldIndex = find(fieldIndex);
   if isempty(fieldIndex) % Field does not currently exist
       if verbose
           fprintf(['Array .' Field.mNum{iField} ' not in Model. Adding.\n'])
       end
       Model.(Field.mNum{iField}) = zeros(nMets, 1);
   else % Field exists, check if the length is correct
       vFieldLength = length(Model.(fieldNames{fieldIndex}));
       if vFieldLength ~= nMets
           vFieldLength = vFieldLength + 1 ;
           Model.(fieldNames{fieldIndex})(vFieldLength:nMets) = 0 ;
       end
   end
end

%% Ensure reactions are forwards.
if verbose
    fprintf('Making sure reactions are all forwards\n')
end
% Find reverse reactions based on bounds.
revRxns = find(abs(Model.lb) > Model.ub);

% Do it.
for iRxn = 1:length(revRxns)
    % Reverse bounds.
    [Model.lb(revRxns(iRxn)), Model.ub(revRxns(iRxn))] = ...
        deal(-Model.ub(revRxns(iRxn)), -Model.lb(revRxns(iRxn)));

    % Change sign of stochiometrix matrix.
    metStoics = find(Model.S(:, revRxns(iRxn)));
    for iMet = 1:length(metStoics)
        if Model.S(metStoics(iMet), revRxns(iRxn)) > 0
            Model.S(metStoics(iMet), revRxns(iRxn)) = ...
                0 - Model.S(metStoics(iMet), revRxns(iRxn));
        else
            Model.S(metStoics(iMet), revRxns(iRxn)) = ...
                abs(Model.S(metStoics(iMet), revRxns(iRxn)));
        end
    end
end

%% Remove hyphens and obtuse characters from names.
if verbose
    fprintf('Fixing names of metabolites and reaction\n')
end
Model.mets = fixNames(Model.mets);
Model.metNames = fixNames(Model.metNames);
Model.metNames = removeDuplicateNames(Model.metNames);
Model.rxns = fixNames(Model.rxns);
Model.rxnNames = removeDuplicateNames(Model.rxnNames);

%% Make sure all reaction and metabolite names are unique.
if verbose
    fprintf('Checking if reaction IDs (.rxns) are unique.\n');
end
if length(Model.rxns) ~= length(unique(Model.rxns))
    fprintf('ERROR: Not all reactions are unique.\n')
    % Launch name correcting script.
    Model.rxns = makeNamesUnique(Model.rxns, Model.rxnNames);
end
if verbose
    fprintf('Checking if metabolite IDs (.mets) are unique.\n');
end
if length(Model.mets) ~= length(unique(Model.mets))
    fprintf('ERROR: Not all metabolites are unique.\n')
    Model.mets = makeNamesUnique(Model.mets, Model.metNames);
end

%% Make sure all metabolites have a compartment.
noComp = find(cellfun(@isempty, regexp(Model.mets, '\[\w\]$')));

if isempty(noComp)
    if verbose
        fprintf('All metabolites have comparment designation.\n')
    end
else
    % try to get compartment information from metNames
    nameComp = find(~cellfun(@isempty, regexp(Model.metNames, '\[\w\]$')));
    if ~isempty(nameComp)
        for inc = rowvector(nameComp)
            Model.mets{inc} = [Model.mets{inc} ...
                Model.metNames{inc}(strfind(Model.metNames{inc}, '['): ...
                strfind(Model.metNames{inc}, ']')) ];
            Model.metNames{inc} = ...
                Model.metNames{inc}(1:strfind(Model.metNames{inc}, '[')-1);
        end
    end

    noComp = find(cellfun(@isempty, regexp(Model.mets, '\[\w\]$')));

    if isempty(noComp)
        if verbose
            fprintf('All metabolites have comparment designation.\n')
        end
    else
        if verbose
            fprintf(['Some metabolites have no compartment designation. ' ...
            'Assigning as cytosolic.\n'])
        end
        for iMet = 1:length(noComp)
            Model.mets{noComp(iMet)} = [Model.mets{noComp(iMet)} '[c]'];
        end
    end
end

%% Give .rxnID or .metID names from .rxns and .mets.
Model.rxnID = Model.rxns ;
Model.metID = Model.mets ;

%% If model has SEED style reaction or metabolite IDs, add them to arrays.
% Reactions.
areSEEDids = ~cellfun(@isempty, regexp(Model.rxns, '^rxn\d{5}$'));
Model.rxnSEEDID(areSEEDids) = Model.rxns(areSEEDids);

% Metabolites.
noComp = Model.mets;
for iMet = 1:length(noComp)
    noComp{iMet} = noComp{iMet}(1:end - 3);
end
areSEEDids = ~cellfun(@isempty, regexp(noComp, '^cpd\d{5}$'));
Model.metSEEDID(areSEEDids) = noComp(areSEEDids);

%% Format chemical formulas
Model.metFormulas = fixChemFormulas(Model.metFormulas);

%% Rebuild reaction equations to ensure they use fixed names/abbreviations.
Model = buildRxnEquations(Model);

%% Ensure all vectors are column vectors.
colFields = {'rxn' 'rNum' 'met' 'mNum'};
for iName = 1:length(colFields)
    for iField = 1:length(Field.(colFields{iName}))
        Model.(Field.(colFields{iName}){iField}) = ...
            Model.(Field.(colFields{iName}){iField})(:);
    end
end

%% Make sure there is a model name and if not, ask for one.
if ~isfield(Model, 'description')
    needModelName = 1 ;
else
    if askForModelName
        fprintf(['Current model name is:' char(10) Model.description char(10)])
        answer = input('Keep name? (y/n): ', 's');
        if strcmpi(answer,'y') || strcmpi(answer, 'yes')
            fprintf('Keeping name\n')
            needModelName = 0 ;
        else
            needModelName = 1 ;
        end
    else
        needModelName = 0 ;
    end
end
try
    test.(Model.description) = true  ;
catch
    disp('Sorry, this model name is invalid. (Hint: it must start with a letter and only contain letters and numbers)')
    needModelName = 1 ;
end
while needModelName
    prompt = 'Input model name: ';
    modelName = input(prompt, 's');
    Model.description = modelName ;
    try
        test.(Model.description) = true  ;
        needModelName = 0 ;
    catch
        disp('Sorry, this model name is invalid. (Hint: it must start with a letter and only contain letters and numbers)')
    end
end

%% Reorder fields and organize model based on most common mets.
Model = orderModelFieldsBorg(Model);
Model = organizeModelCool(Model);


function [weight] = ubah_kernel(data, weight_o)
% This file is the kernel core for the market strategy.
% If multiple experts are required, implement in this file.
% Here, only one expert is designed.
%
% function [weight] = ubah_kernel(data, weight_o)
% weight: generate portfolio for day t+1
% data: market sequence until day t
% weight_o: last (t^th) portfolio
%
% Example: [weight] ...
%          = ubah_kernel(data(1:t), weight_o);

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

weight = ubah_expert(data, weight_o);

end
%%%%%%%%%%%%%%End%%%%%%%%%%%%%%%%%%%%%%


% The mapping from 61 phones set to 48 phonse set for TIMIT. The mapping
% table is as follows:
%
% cl vcl epi --> sil
% el --> l
% en --> n
% zh --> sh
% aa --> ao
% ix --> ih
% ax --> ah
%
% Author: Xiong Xiao, NTU, Singapore
% Date: 1 Jun 2016

function phone_seq_39 = TIMIT_map48to39(phone_seq_48)

mapping_table = {
    'cl'  'sil';
    'vcl' 'sil';
    'epi' 'sil';
    'el'  'l';
    'en'  'n';
    'zh'  'sh';
    'aa'  'ao';
    'ix'  'ih';
    'ax'  'ah';};

phone_seq_39 = phone_seq_48;
for i=1:size(mapping_table,1)
    found = strcmpi(phone_seq_39, mapping_table{i,1});
    if sum(found)>0
        idx = find(found==1);
        for j=1:length(idx)
            phone_seq_39{idx(j)} = mapping_table{i,2};
        end
    end
end
end