%% Maryam Seif-Eddine's FE-EPR script for analysing CV-EPR data
%% 2021-2022 - Roessler Research Group - Imperial College London
%% Please cite publication (Seif-Eddine et al. Nature Chemistry 2024) if using this script

clc
clear all
close all

%%

%%---------EPR - data---------- 
 
%%
 
%Change path
%path(path,'/Users/j/Documents/2021_Imperial/Projects/FE-EPR/STEMPO/STEMPO/EPR/July22/10_07'); 

%Change file name
[B,spec,Params] = eprload('CVEPR_STEMPO_02');

%Components
TimeEPR = B{1,2}; % is the total time of programmed EPR increments
Y = B{1,1}*1e-1; % magnetic field  
Z = spec; % data

%Clean the EPR matrix from the zeros
zerocol = find(sum(abs(Z)) == 0,1);% will find the 0s in the matrix and return the index of the fst 0  
X = reshape(1:zerocol,1,[])'; % nb of increments as X axis
Xaxis = X(1:zerocol-1); % to limit the time to the real time of acquisition and not the equivalent time of the number of increments added
EPRdata = spec(1:size(Z,1), 1:zerocol-1); % to limit the data to the real time of aquisition
TimeEPR = TimeEPR(1:zerocol+1);  % total time of measurement only

%Baseline Correction
EPRdata = basecorr(EPRdata,1,2); % 2d order polynomial

%Smooth data - if neede -
EPRdata =  datasmooth(EPRdata,20,'savgol');

%EPR part of the first figure
figure(1)
subplot(2,1,1)
z=peaks(TimeEPR,Y);
ribbon(Y,EPRdata,0.5,'Color','black');
%Format of the figure
xlabel('EPR increments');
hxLabel = get(gca,'xlabel');
set(hxLabel,'rotation',7,'VerticalAlignment','middle');
axis tight
ylabel('Magnetic field (mT)');
hyLabel = get(gca,'ylabel');
set(hyLabel,'rotation',-10,'VerticalAlignment','middle');
zlabel('Intensity (a.u.)');
set (gca, 'YDir','reverse'); 
set(gca,'FontSize',12)

shading interp;

%%

 %%---------Electrochemistry - data---------

 
%%

%Change path
%path(path,'/Users/j/Documents/2021_Imperial/Projects/FE-EPR/STEMPO/STEMPO/Electrochem/10_07_22_20mMBA'); 

%Change file name
filename = 'CVEPR_STEMPO_02 nosub O2 flow4 5mVps 0p2to1V 1sc'; 

% Read out raw data
raw = readtable(filename,'HeaderLines',1); % read the complete .txt file without the header
we_potential = raw{:,1}+0.211; % potential of working electrode in V
current = raw{:,3}; % measured current in A
TimeCV = raw{:,2};
scan_nb = raw{:,4};

totscan = max(raw{:,4}); % number of performed scans
points = length(we_potential); % length of the raw table
length_matrix = points/totscan; % length of each CV scan

%Re-classify data: each scan in a separate cell
for n = 1:totscan 
    scan{n} = [we_potential(1+(n-1)*length_matrix:n*length_matrix) current(1+(n-1)*length_matrix:n*length_matrix) TimeCV(1+(n-1)*length_matrix:n*length_matrix)];
end

%CV data in the first figure: plotting all the scans
figure(1)
subplot(2,1,2)
box on
hold on
for n = 1:totscan
   plot(scan{n}(:,1),scan{n}(:,2)*1e6,'linewidth',2.0,'Color','black')
end
%Format of the figure
axis tight
xlabel('Potential (V vs SHE)')
set(gca,'XMinorTick','on')
ylabel('Current (µA)')
set(gca,'FontSize',12)

%%
    % Preparing for combining EPR and Echem data
    
%%

%Deduce the echem waiting time from the echem time vector
TimeCV = TimeCV(:,1)-TimeCV(1,1); 

%Define the time at the end of the CV experiment (including all scans)
endCV = round(TimeCV(end));

%Find the equivalent time in the EPR time vector
reallengthEPR = interp1(TimeEPR, 1:length(TimeEPR), endCV, 'nearest');
TimeEPR = TimeEPR(1:reallengthEPR+1);

%Asking the user to enter the number of CV scan to be analysed
x = input('Enter the CV scan number: '); 

%Narrowing down the data sets to the scan number provided by the user
we_potentialx = scan{x}(:,1); 
currentx = scan{x}(:,2);
TimeCVscanx = scan{x}(:,3);
TimeCVscanx = TimeCVscanx-TimeCVscanx(1,1);

%Finding the equivalent data set in the EPR matrix
lengthonescanEPR = length(TimeEPR)/totscan;
lengthonescanEPR = round(lengthonescanEPR);

if x == 1
TimeaxisEPR = TimeEPR(1 : x*lengthonescanEPR);
aa = 1;
else
aa = (x-1)*lengthonescanEPR;
bb = x*lengthonescanEPR-2*x;
TimeaxisEPR = TimeEPR(aa : bb);
end

bb = x*lengthonescanEPR-2*x;
EPRdatax = EPRdata(:,aa:bb); % to limit the data to the wanted CV scan
%%
%--------------------------------------------------------------------------
                               % Definitions
%--------------------------------------------------------------------------

%Maximum and miniumu of the delimited data sets from above
ii = length(we_potentialx)/2;
we_potentialx2 = we_potentialx(ii:length(we_potentialx));
[Min,Imin] = min(we_potentialx);
[Min2,Imin2] = min(we_potentialx2);
Imin2 = 2*Imin2-2;
[Max,Imax] = max(we_potentialx);

%Start potential and its time
start_pot = we_potential(1,1);
start_pot = round(start_pot);
tCVi = TimeCV(1,1);

%Lowest potential and its time
lowest_pot = Min;
lowest_pot = round(lowest_pot);
tCV_lowest_pot_1 = TimeCVscanx(Imin);

%Highest potential and its time
highest_pot = Max;
tCV_highest_pot_1 = TimeCVscanx(Imax)
%%
%--------------------------------------------------------------------------
              % Condition: IF start potential = lowest potential
%--------------------------------------------------------------------------

% start potential = lowest potential means we start from and stop at the
% same potential
if start_pot == lowest_pot

% l1: 1st lowest potential
tCV_l1 = TimeCVscanx(1,1);
indx_pot_CV_l1 = find(TimeCVscanx == tCV_l1);

% h1: 1st highest potential
tCV_h1 = tCV_highest_pot_1;
indx_pot_CV_h1 = find(TimeCVscanx == tCV_h1);

% l2: 2d lowest potential
indx_scnd_lowest_pot = Imin2;
tCV_l2 = TimeCVscanx(indx_scnd_lowest_pot);

%Forward CV scan data: from the lowest to the highest potential
tCV_l1h1 = TimeCVscanx(indx_pot_CV_l1:indx_pot_CV_h1);
Pot_l1h1 = we_potentialx(indx_pot_CV_l1:indx_pot_CV_h1);
Current_l1h1 = currentx(indx_pot_CV_l1:indx_pot_CV_h1);
forward = [tCV_l1h1;Pot_l1h1;Current_l1h1];

indx_l1 = interp1(TimeaxisEPR, 1:length(TimeaxisEPR), tCV_l1, 'nearest');
tEPR_l1 = TimeaxisEPR(indx_l1);
indx_h1 = interp1(TimeaxisEPR, 1:length(TimeaxisEPR), tCV_h1, 'nearest');
tEPR_h1 = TimeaxisEPR(indx_h1);

tEPR_l1h1 = TimeaxisEPR(indx_l1:indx_h1);
EPRdatax_l1h1 = EPRdatax(indx_l1:indx_h1); 

%Forward CV scan - Corresponding EPR data
EPRdatax_l1h1 = EPRdatax(:,indx_l1:indx_h1); 
EPRdatax_l1h1_bkg = basecorr(EPRdatax_l1h1,1,2);
field= Y.';

%Smoothing EPR data - if needed -
EPRdatax_l1h1_bkg =  datasmooth(EPRdatax_l1h1_bkg,20,'savgol');

%Figure of the EPR spectra corresponding to the forward CV scan only
figure('DefaultAxesFontSize',12)
[m,n] = size(EPRdatax_l1h1_bkg);
figure(2)
cc = turbo(n);
for i=1:n
    plot(field,EPRdatax_l1h1_bkg(:,i),'Color',cc(i,:),'LineWidth',1);
    hold on
    i=i+1;
    axis tight
xlabel('Magnetic Field (mT)');
ylabel('EPR intensity (a.u.)');
end
title('Forward CV scan');
figure('DefaultAxesFontSize',18);

% Choose the region to integrate on the EPR spectra directly on figure 2
disp('Choose the lowest field position, then click & hold shift before choosing the highest field position')
disp('! final outcome dependent on chosen posisions !')
dcm_obj = datacursormode(figure(2));
set(dcm_obj,'DisplayStyle','datatip',...
'SnapToDataVertex','off','Enable','on')
pause();
Datatip = getCursorInfo(dcm_obj);
p1 = extractfield(Datatip,'Position');

pmax=(p1(1,1));
pmin=(p1(1,3));

field= Y.';
dfield = mean(diff(field));

% Find the indexes of the chosen field positions
indx_pmax = interp1(field,1:length(field),pmax,'nearest');
indx_pmin = interp1(field,1:length(field),pmin,'nearest');

% Limiting the EPR data to the chosen field positions
signal_selc = field(indx_pmin:indx_pmax); %region of selected signal
EPRdata_for_bkg1 = EPRdatax_l1h1_bkg(indx_pmin:indx_pmax,:);

[f,g]=size(EPRdata_for_bkg1);

% Integrate then double integrate the corresponding data
for i = 1:g
    
EPRdata_for_bkg_int(:,i) = cumtrapz(EPRdata_for_bkg1(:,i))*dfield; %int for integral

EPRdata_for_bkg_dint(:,i) = sum(EPRdata_for_bkg_int(:,i))*dfield; %dint for double integral

end

% Represent the integrated data in a figure
figure(3)
cc = turbo(n);
for i=1:n
    plot(signal_selc,EPRdata_for_bkg_int(:,i),'Color',cc(i,:),'LineWidth',1);
    hold on
    i=i+1;
    axis tight
xlabel('Magnetic Field (mT)');
ylabel('Integral EPR intensity (a.u.)');

end
title('Forward CV scan');
figure('DefaultAxesFontSize',18);

intensities_for = EPRdata_for_bkg_dint.'; % Double integrals of EPR on th forward scan are now intensities_for

%Finding the potential of each EPR data point (EPR spectrum)
ratio_for = length (Pot_l1h1)/g; %pot for potential. count steps that correspond to EPR on Potential axis
indx_x_for = 1:ratio_for:length(Pot_l1h1); %find indexes of the steps above on the potential axis
indx_x_for=round(indx_x_for);
x_for =(Pot_l1h1(indx_x_for));%find the corresponding potential at each index from above. x_for: potential points from forward CV that correspond to each EPR on the forward CV


%%
%Reverse CV scan data: from the highest to the 2d lowest (which is
%equivalent to the 1st lowest under the condition where star potential =
%stop potential

indx_l2  = length(TimeaxisEPR);
tEPR_l2 = TimeaxisEPR(indx_l2);

tCV_h1l2 = TimeCVscanx(indx_pot_CV_h1:indx_scnd_lowest_pot);
Pot_h1l2 = we_potentialx(indx_pot_CV_h1:indx_scnd_lowest_pot);
Current_h1l2 = currentx(indx_pot_CV_h1:indx_scnd_lowest_pot);

tEPR_h1l2 = TimeaxisEPR(indx_h1:indx_l2-1);
EPRdatax_h1l2 = EPRdatax(indx_h1:indx_l2-1);


%Reverse CV scan - Corresponding EPR data
EPRdatax_h1l2 = EPRdatax(:,indx_h1:indx_l2-2);
EPRdatax_h1l2_bkg = basecorr(EPRdatax_h1l2,1,2);

%Smoothing EPR data - if needed -
EPRdatax_h1l2_bkg =  datasmooth(EPRdatax_h1l2_bkg,20,'savgol');

%Figure of the EPR spectra corresponding to the reverse CV scan only
figure('DefaultAxesFontSize',12)
figure(4)
[m,n] = size(EPRdatax_h1l2_bkg);
cc = turbo(n);
for i=1:n
    plot(field,EPRdatax_h1l2_bkg(:,i),'Color',cc(i,:),'LineWidth',1);
    hold on
    i=i+1;
    axis tight
xlabel('Magnetic Field (mT)');
ylabel('EPR intensity (a.u.)');

end
title('Reverse CV scan');
figure('DefaultAxesFontSize',12);

% Choose the region to integrate on the EPR spectra directly on figure 4
disp('REPEAT: Choose the lowest field position, then click & hold shift before choosing the highest field position')
dcm_obj = datacursormode(figure(4));
set(dcm_obj,'DisplayStyle','datatip',...
'SnapToDataVertex','off','Enable','on')
pause();
Datatip = getCursorInfo(dcm_obj);
p1 = extractfield(Datatip,'Position');

pmax=(p1(1,1));
pmin=(p1(1,3));

field= Y.';
dfield = mean(diff(field));

% Find the indexes of the chosen field positions
indx_pmax = interp1(field,1:length(field),pmax,'nearest');
indx_pmin = interp1(field,1:length(field),pmin,'nearest');

% Limiting the EPR data to the chosen field positions
signal_selc = field(indx_pmin:indx_pmax);
EPRdata_rev_bkg1 = EPRdatax_h1l2_bkg(indx_pmin:indx_pmax,:);

[f,g]=size(EPRdata_rev_bkg1);

% Integrate then double integrate the corresponding data
for i = 1:g
    
EPRdata_rev_bkg_int(:,i) = cumtrapz(EPRdata_rev_bkg1(:,i))*dfield;

EPRdata_rev_bkg_dint(:,i) = sum(EPRdata_rev_bkg_int(:,i))*dfield;

end

% Represent the integrated data in a figure
figure(5)
cc = turbo(n);
for i=1:n
    plot(signal_selc,EPRdata_rev_bkg_int(:,i),'Color',cc(i,:),'LineWidth',1);
    hold on
    i=i+1;
    axis tight
xlabel('Magnetic Field (mT)');
ylabel('Integral EPR intensity (a.u.)');

end
title('Reverse CV scan');
figure('DefaultAxesFontSize',12);

intensities_rev = EPRdata_rev_bkg_dint.'; % Double integrals of EPR on th reverse scan are now intensities_rev

%Finding the potential of each EPR data point (EPR spectrum)
[Min3,Imin3] = min(Pot_h1l2);
length_Poth1l2 = length(Pot_h1l2);
ratio_rev =(length (Pot_h1l2)/g);
indx_x_rev = 1:ratio_rev:(length_Poth1l2)-1;
x_rev = Pot_h1l2(round(indx_x_rev));

end
%%
%-----------------------------------
        %Nernst fitting
%-----------------------------------

% forward
% Nernst equation

Ex_for = x_for;  
time_for = tEPR_l1h1(1:length(intensities_for));
Potential_for = Ex_for;

scanrate = 0.005;% scan rate V/s

% Error on the potential of the EPR data
for i = 1:length(time_for)-1
dtfor(i,1) =  (time_for(i+1,1) - time_for(i,1));

dPotential_for(i,1) = scanrate * dtfor(i,1);
end
dPotential_for(length(time_for),1) = dPotential_for(length(time_for)-1,1);

figure('DefaultAxesFontSize',12)

figure(6)
subplot (1,2,1);
scatter(Potential_for,intensities_for);
% errorbar(Potential_for,intensities_for,dPotential_for,'horizontal','LineStyle','none');


xlim([0.4 1.2]);
xlabel('Applied potential (V vs SHE)');
title ('Forward');
ylim([-0.02 0.45]);
ylabel('Double integral EPR - forward CV scan');

hold all

rng default % for reproducibility
x = Potential_for;
xlow = x(x<0.5);
xhigh = x(x>0.5);

y = intensities_for;
ylow = y(x<0.5);
yhigh = y(x>0.5);

hhigh=plot(xhigh,yhigh);

hhigh.LineWidth = 2;


start = [0.3; 0.951];
options = optimset('TolX',1e-5);
[CfornoxEox,residualfor,rrsfor] = fminsearch (@(CfornoxEox) fitfor(CfornoxEox,xhigh,yhigh,hhigh),start,options);

%%
% Reverse
% Nernst equation

% 
Ex_rev = x_rev;  
Potential_rev = Ex_rev;
time_rev = tEPR_h1l2(1:length(intensities_rev));

scanrate = 0.005;% scan rate V/s

% Error on the potential of each EPR spectrum
for i = 1:length(time_rev)-1
dtrev(i,1) =  (time_rev(i+1,1) - time_rev(i,1));

dPotential_rev(i,1) = scanrate * dtrev(i,1);
end
dPotential_rev(length(time_rev),1) = dPotential_rev(length(time_rev)-1,1);

figure('DefaultAxesFontSize',12)

figure(6)
subplot (1,2,2);
Potential_Rev = Ex_rev;

scatter(Potential_Rev,intensities_rev);
% errorbar(Potential_Rev,intensities_rev,dPotential_rev,'horizontal','LineStyle','none');

hold on

Potential_Rev = Ex_rev;

xlim([0.4 1.2]);
xlabel('Applied potential (V vs SHE)');
title ('Reverse');
ylim([-0.02 0.45]);
ylabel('Double integral EPR - reverse CV scan');

hold all

% Simplex - Derivative-free method using fminsearch
rng default % for reproducibility
x = Potential_rev;
y = intensities_rev;
xhigh = x(x>0);
yhigh = y(x>0);

hhigh=plot(xhigh,yhigh);

hhigh.LineWidth = 2;

start = [0.3; 0.951];
options = optimset('TolX',1e-4);

[CrevnoxEoxrd,residualrevrd,rrsrevrd] = fminsearch (@(CrevnoxErd) fitrevrd(CrevnoxErd,xhigh,yhigh,hhigh),start,options);

set (gca, 'XDir','reverse');

close(figure(7))
close(figure(8))
close(figure(9))

