786 lines
32 KiB
Matlab
Executable File
786 lines
32 KiB
Matlab
Executable File
%% Lopap Template
|
|
% Uses data from 20211115_1431
|
|
%
|
|
%% Info: How to use this
|
|
%
|
|
% # Make a copy of this file for each Lopap measurement. Name it
|
|
% "Lopap"_date_time.m and store it in the folder with the Lopap data. %
|
|
% Remove all the general text and comments in your file and add notes and
|
|
% observations about the experiment.
|
|
%
|
|
% # You can run this script, publish it, or evaluate it section wise. For
|
|
% new data run it section wise to carefully update the settings and to
|
|
% observe the results.
|
|
% # Once the data is loaded, you can also run individual sections only.
|
|
% # You may use the LabBook :: Chrono Notes section as lab book.
|
|
% # All sections that can be modified are marked with the word "<Adapt>:".
|
|
% # You also need to give time regions such as for the background fit, as
|
|
% well as to calculate means. There are several options how to do this
|
|
%
|
|
% * While running the experiments and observing the signal in the Lopap
|
|
% software, you can enter the date and times directly in the LabBook :
|
|
% Select data ranges section.
|
|
% * You can manually select the regions in a plot. A window will pop up to
|
|
% select the region to modify. To modify several regions, re-run this
|
|
% section of the script. This overwrites the current settings.
|
|
% * The times of the regions are stored in the "TimeRanges.mat" file. If it
|
|
% exists, this is read; the LabBook : Select data ranges section is then
|
|
% ignored.
|
|
%% Info: Output & Variables
|
|
%
|
|
% * *lopapReferenceWavelength*: This _string variable_ holds text with
|
|
% stating the reference wavelength for channel 1 and 2 used to process the
|
|
% data by the Lopap software.
|
|
% * *LopapDataCh1 & LopapDataCh2*: These _time tables_ hold the data that
|
|
% have been processed by the Lopap Software during the data acquisition. It
|
|
% contains the absorption for a number
|
|
% of selected wavelength. The absorption is the log of the intensity at the
|
|
% reference wavelength relative to the intensity at each wavelength of
|
|
% interest. The timetables hold the time in each row and the wavelength in
|
|
% the columns. The content is thus identical to that shown in the
|
|
% "measurement window" of the Lopap software.
|
|
% * *LopapSpecCh1,LopapSpecCh2*: The _time tables_ hold the full spectrum
|
|
% for each time. Time is in the rows, wavelength in the columns. The
|
|
% wavelength are read from the *.prj file, the spectra data from the *.spec
|
|
% file. The information is identical to that shown in the "spectrum window"
|
|
% of the Lopap software.
|
|
% * *LopapTimeT* This is the main results table:
|
|
%
|
|
% * time
|
|
% * raw signal channel 1
|
|
% * raw signal channel 2
|
|
% * background subtracted channel 1
|
|
% * background subtracted channel 2
|
|
% * calibrated signal channel 1 in ppt
|
|
% * calibrated signal channel 2 in ppt
|
|
% * HONO in ppt (channel 2 -channel 1)
|
|
%
|
|
%
|
|
% * *TimeRanges.mat*: Time ranges after they have been manually modified. If
|
|
% this file exists, the time range definitions in this script are ignored.
|
|
% * *LopapMatlabDataDATE_TIME.mat*: Raw data and experimental settings.
|
|
% Background subtraction and calibration are not saved in this file. When
|
|
% this file exists, data will not be read from the windows server.
|
|
% * *LopapDATE_TIME.mat*: Processed data - absorption with time (column 1
|
|
% and 2: 'Ch #1' and 'Ch #2') after background (columns 3 and 4: 'Ch #1
|
|
% Bkgrd' and 'Ch #2 Bkgrd') subtraction and calibration (columns 5 and 6:
|
|
% 'Ch #1 Calib' and 'Ch #2 Calib') for one wavelength - that can be used
|
|
% for further comparison with other experiments and discussion. Also
|
|
% exported is HONO in ppt (channel2-channel1 after calibration).
|
|
%
|
|
|
|
%% Matlab: Initialise
|
|
%
|
|
% This starts Matlab and defines some common settings such as the path to
|
|
% the Lopap data. Any modifications can be done at the end of this file in
|
|
% where the local function _localInitializeMatlab_ is stored.
|
|
|
|
|
|
% clear variables in workspace, clear text in command window
|
|
clearvars
|
|
clc
|
|
% set the path to the data and define some custom colours for plotting
|
|
[fileLocation, myColorMap] = localInitializeMatlab;
|
|
% <Adapt>: Date when Lopap recording was started. Defines names of Lopap
|
|
% files and folders. Seconds are irrelevant, but format is important.
|
|
LopapParameters.MeasurementDate = datenum('15-Nov-2021 14:31:00');
|
|
% <Adapt>: Date when Lopap calibration for this measurement was started.
|
|
% Defines names of Lopap files and folders. Seconds are irrelevant, but
|
|
% format is important.
|
|
LopapParameters.CalibrationDate = datenum('11-March-2021 09:51:00');
|
|
%%
|
|
|
|
% Print info to command window
|
|
disp('The data is read from:');
|
|
disp(fullfile(fileLocation.server,fileLocation.dataPath,datestr(LopapParameters.MeasurementDate,'yyyymmdd_HHMM')));
|
|
disp(' ')
|
|
disp('Date of experiment:')
|
|
disp(datestr(LopapParameters.MeasurementDate));
|
|
try
|
|
disp(' ')
|
|
disp('Date of calibration:')
|
|
disp(datestr(LopapParameters.CalibrationDate));
|
|
catch
|
|
end
|
|
disp(' ')
|
|
disp('Date of analyis:')
|
|
disp(datestr(today));
|
|
|
|
%% Process: Import data
|
|
%
|
|
% Reads and imports data from Lopap *.dat, *.spec, and *.prj files and the
|
|
% calibration results and settings from a *.mat file (*.mat file needs to
|
|
% be in same folder as this file).
|
|
%
|
|
% * *lopapReferenceWavelength*: This _string variable_ holds text with
|
|
% stating the reference wavelength for channel 1 and 2 used to process the
|
|
% data by the Lopap software.
|
|
% * *LopapDataCh1 & LopapDataCh2*: These _time tables_ hold the data that
|
|
% have been processed by the Lopap Software during the data acquisition. It
|
|
% contains the absorption for a number
|
|
% of selected wavelength. The absorption is the log of the intensity at the
|
|
% reference wavelength relative to the intensity at each wavelength of
|
|
% interest. The timetables hold the time in each row and the wavelength in
|
|
% the columns. The content is thus identical to that shown in the
|
|
% "measurement window" of the Lopap software.
|
|
% * *LopapSpecCh1,LopapSpecCh2*: The _time tables_ hold the full spectrum
|
|
% for each time. Time is in the rows, wavelength in the columns. The
|
|
% wavelength are read from the *.prj file, the spectra data from the *.spec
|
|
% file. The information is identical to that shown in the "spectrum window"
|
|
% of the Lopap software.
|
|
% * *LopapParametersCalibration*: Holds the date, wavelength,
|
|
% concentrations, flows, temperature & pressure of the calibration
|
|
% measurement.
|
|
% * *LopapCalibCalibration* holds the mean, standard deviation, mixing ratio
|
|
% and fit results of the calibration. The fit results can be used to
|
|
% calibrate this data-set. It's a linear fit via 0 of signal intensity vs.
|
|
% HONO in ppt.
|
|
|
|
if isfile(['LopapMatlabData' datestr(LopapParameters.MeasurementDate,'yyyymmdd_HHMM') '.mat'])
|
|
load(['LopapMatlabData' datestr(LopapParameters.MeasurementDate,'yyyymmdd_HHMM') '.mat'])
|
|
disp('Lopap data loaded from mat file')
|
|
else
|
|
[LopapParameters.instrumentReferenceWavelength, LopapDataCh1,LopapDataCh2,LopapSpecCh1,LopapSpecCh2] ...
|
|
= importLopap(LopapParameters.MeasurementDate,fileLocation);
|
|
disp('Lopap data imported from intrument')
|
|
save(['LopapMatlabData' datestr(LopapParameters.MeasurementDate,'yyyymmdd_HHMM') '.mat'],'LopapDataCh1','LopapDataCh2','LopapParameters','LopapSpecCh1','LopapSpecCh2')
|
|
end
|
|
% if the calibration file exist, it will read the results and the
|
|
% reference wavelength and signal wavelength from that file
|
|
if isfile(['LopapMatlabData' datestr(LopapParameters.CalibrationDate,'yyyymmdd_HHMM') 'Calib.mat'])
|
|
LopapParametersCalibration = load(['LopapMatlabData' datestr(LopapParameters.CalibrationDate,'yyyymmdd_HHMM') 'Calib.mat'],'LopapParameters');
|
|
LopapCalibCalibration = load(['LopapMatlabData' datestr(LopapParameters.CalibrationDate,'yyyymmdd_HHMM') 'Calib.mat'],'calib');
|
|
LopapParameters.wavelengthR = LopapParametersCalibration.LopapParameters.wavelengthR;
|
|
LopapParameters.wavelengthS = LopapParametersCalibration.LopapParameters.wavelengthS;
|
|
disp('Calibration data loaded from mat file')
|
|
else
|
|
% otherwise, you can choose these wavelength here
|
|
disp('No calibration done yet!')
|
|
% <Adapt>: Choose a reference wavelength. Default is 650 nm.
|
|
LopapParameters.wavelengthR = 650; %nm, reference intensity
|
|
% <Adapt>: Choose a signal wavelength to calculate the absorption with time
|
|
% from the spectra
|
|
LopapParameters.wavelengthS = 530; %nm, signal intensity
|
|
|
|
end
|
|
%% Matlab: Run mode
|
|
%
|
|
% <Adapt>:
|
|
%
|
|
% * runs without user interaction and without ability to modify data
|
|
% ranges, when set to 0; use this to publish.
|
|
% * if set to 1: stops for user interaction,
|
|
% modify data ranges is enabled.Use this to run.
|
|
LopapParameters.Interactive = 1;
|
|
|
|
%% LabBook : Define data ranges
|
|
%%
|
|
% These settings can be modified by selecting data ranges in a plot later.
|
|
% So, you do not necessarily need to type the dates and times here.
|
|
|
|
% <Adapt> (Optional - comment if no needed) state the start and end
|
|
% time of the time that you want to look at (to exclude very noisy
|
|
% signal in the beginning and at the end of the data)
|
|
TimeRange.dataRange = [datenum('15-Nov-2021 16:30:00') datenum('15-Nov-2021 17:20:00')];
|
|
% <Adapt>: State the time for the first spectrum that you like to
|
|
% compare (to confirm nitrite)
|
|
TimeRange.specCompareOne = datenum('15-Nov-2021 16:49:30');
|
|
% <Adapt>: State the time for one spectrum of the second spectrum that
|
|
% you like to compare (to confirm nitrite)
|
|
TimeRange.specCompareTwo = datenum('15-Nov-2021 17:02:00');
|
|
% <Adapt>: Choose a start and end time for one as many intervals that can
|
|
% be used to fit the background. Background is the signal when R1&R2 was
|
|
% attached to the Lopap with zero air entering the sampling coil.
|
|
TimeRange.backgroundFit = [datenum('15-Nov-2021 15:10:00') datenum('15-Nov-2021 15:50:00')];% ;...
|
|
% datenum('16-Sep-2020 15:40:50') datenum('16-Sep-2020 15:51:06')];
|
|
|
|
|
|
|
|
% confirm that all dates are reasonable
|
|
tmp = fieldnames(TimeRange);
|
|
for ii = 1:length(tmp)
|
|
mustBeLopapReasonableDate(TimeRange.(tmp{ii}))
|
|
end
|
|
clearvars tmp*
|
|
|
|
%% Process: Modify data ranges
|
|
%
|
|
% Select the range to modify in the pop-up window and the number of fit
|
|
% ranges for the background fit in the 2nd pop-up window. Then, a figure
|
|
% will show, select the data ranges in the figure:
|
|
%
|
|
% * a line for calibration range, mean zero air and mean
|
|
% nitrite standard. Select the range by keeping the mouse pushed while
|
|
% moving from start to end time.
|
|
% * a line for each background region, default is 2. Select the range by
|
|
% keeping the mouse pushed while moving from start to end time.
|
|
% * a point for spectrum with reagents and spectrum with nitrite. Click
|
|
% once to select a specific time.
|
|
%
|
|
% * LopapParameters.Interactive needs to be 1 for this to run.
|
|
%
|
|
% # Run this section several times to modify several time regions
|
|
% # Press cancel in the pop-up window if you do not want to modify any
|
|
% region.
|
|
|
|
TimeRange = modifyLopapTimeRanges(TimeRange, LopapParameters, LopapDataCh1, LopapDataCh2);
|
|
clearvars -except Lopap* fileLocation myColorMap LopapParameters TimeRange*
|
|
|
|
|
|
%% Process: Find closest match of selected dates in data set
|
|
%
|
|
% The data is sampled at specific times with a certain interval. The
|
|
% selected or chosen dates might not necessarily exactly match the data.
|
|
% Here, closest match to the given dates are selected.
|
|
|
|
tmp.d1 = TimeRange.specCompareOne;
|
|
tmp.d2 = LopapSpecCh1.Time;
|
|
[~,ind1] = min(abs(bsxfun(@minus,datenum(tmp.d2),datenum(tmp.d1)')));
|
|
TimeRange.specCompareOne = tmp.d2(ind1,:);
|
|
|
|
tmp.d1 = TimeRange.specCompareTwo ;
|
|
tmp.d2 = LopapSpecCh1.Time;
|
|
[~,ind1] = min(abs(bsxfun(@minus,datenum(tmp.d2),datenum(tmp.d1)')));
|
|
TimeRange.specCompareTwo = tmp.d2(ind1,:);
|
|
|
|
% save current state of
|
|
clearvars -except Lopap* fileLocation myColorMap LopapParameters TimeRange*
|
|
save(['LopapMatlabData' datestr(LopapParameters.MeasurementDate,'yyyymmdd_HHMM') '.mat'],'LopapDataCh1','LopapDataCh2','LopapParameters','LopapSpecCh1','LopapSpecCh2')
|
|
|
|
%% LabBook: Data ranges used in this work
|
|
%
|
|
% This plots the
|
|
|
|
for ii=1:size(TimeRange.backgroundFit,1)
|
|
fprintf('Background range: %s to %s \n',datestr(TimeRange.backgroundFit(ii,1)), datestr(TimeRange.backgroundFit(ii,2)))
|
|
end
|
|
fprintf('Comparision Spectrum 1: %s \n',datestr(TimeRange.specCompareOne(1)))
|
|
fprintf('Comparision Spectrum 2: %s \n',datestr(TimeRange.specCompareTwo(1)))
|
|
|
|
|
|
%% Plot all data
|
|
%
|
|
% Here, we plot the data as shown in the "Measurement window" of the Lopap
|
|
% software. That is, the processed $I^{*}_{i}$ data for all wavelength as
|
|
% defined in the settings of the Lopap software.
|
|
%
|
|
%
|
|
% For every measurement wavelength I_i the program calculates the
|
|
% measurement (absorption) value I_i^* from the spectral intensity on the
|
|
% measurement wavelength I_i and a reference wavelength I_r with the
|
|
% following operation:
|
|
%
|
|
%
|
|
% $$I^{*}_{i} = log_{10} (\frac{I_r}{I_i})$$
|
|
%
|
|
%
|
|
%
|
|
% The plots show time on the x-axis and the ABS intensity on the y axis for
|
|
% each wavelength in separate graphs. One Figure for each Channel.
|
|
|
|
figure( 'Name', 'LopapChannel1','NumberTitle','off','Position',[10 100 550 700]);
|
|
ch1s=stackedplot(LopapDataCh1);
|
|
title(LopapParameters.instrumentReferenceWavelength(1))
|
|
for ii = 1:width(LopapDataCh1)
|
|
% <Adapt>: The numbers in the brackets give the lower and upper limit
|
|
% of the y-axis. Adapt these to fit your data and remove the % sign.
|
|
% ch1s.AxesProperties(ii).YLimits = [-0.4 -0.1];
|
|
end
|
|
grid ON
|
|
% Add title and axis labels
|
|
xlabel('Lab Time')
|
|
|
|
figure( 'Name', 'LopapChannel2','NumberTitle','off','Position',[600 100 550 700]);
|
|
ch2s=stackedplot(LopapDataCh2);
|
|
title(LopapParameters.instrumentReferenceWavelength(2))
|
|
for ii = 1:width(LopapDataCh2)
|
|
% <Adapt>: The numbers in the brackets give the lower and upper limit
|
|
% of the y-axis. Adapt these to fit your data and remove the % sign.
|
|
% ch2s.AxesProperties(ii).YLimits = [-0.2 0.3];
|
|
end
|
|
grid ON
|
|
% Add title and axis labels
|
|
xlabel('Lab Time')
|
|
clearvars -except Lopap* fileLocation myColorMap LopapParameters TimeRange*
|
|
if LopapParameters.Interactive == 1
|
|
distFig
|
|
fprintf('press any key if you want to proceed\n')
|
|
pause
|
|
%%
|
|
%
|
|
close all
|
|
end
|
|
|
|
%% Plot all data :: selected time range
|
|
%
|
|
if isfield(TimeRange,'dataRange')
|
|
TR = timerange(datestr(TimeRange.dataRange(1)),datestr(TimeRange.dataRange(2)));
|
|
figure( 'Name', 'LopapChannel1','NumberTitle','off','Position',[10 100 550 700]);
|
|
ch1s=stackedplot(LopapDataCh1(TR,:));
|
|
title(LopapParameters.instrumentReferenceWavelength(1))
|
|
for ii = 1:width(LopapDataCh1)
|
|
% <Adapt>: The numbers in the brackets give the lower and upper limit
|
|
% of the y-axis. Adapt these to fit your data and remove the % sign.
|
|
% ch1s.AxesProperties(ii).YLimits = [-0.4 -0.1];
|
|
end
|
|
grid ON
|
|
% Add title and axis labels
|
|
xlabel('Lab Time')
|
|
|
|
figure( 'Name', 'LopapChannel2','NumberTitle','off','Position',[600 100 550 700]);
|
|
ch2s=stackedplot(LopapDataCh2(TR,:));
|
|
title(LopapParameters.instrumentReferenceWavelength(2))
|
|
for ii = 1:width(LopapDataCh2)
|
|
% <Adapt>: The numbers in the brackets give the lower and upper limit
|
|
% of the y-axis. Adapt these to fit your data and remove the % sign.
|
|
% ch2s.AxesProperties(ii).YLimits = [-0.2 0.3];
|
|
end
|
|
grid ON
|
|
% Add title and axis labels
|
|
xlabel('Lab Time')
|
|
clearvars -except Lopap* fileLocation myColorMap LopapParameters TimeRange*
|
|
if LopapParameters.Interactive == 1
|
|
distFig
|
|
fprintf('press any key if you want to proceed\n')
|
|
pause
|
|
%%
|
|
%
|
|
close all
|
|
end
|
|
end
|
|
|
|
|
|
%% Plot selected data with Notes
|
|
%
|
|
% Here we plot the $I^{*}_{i}$ data for one wavelength only.
|
|
|
|
if isfield(TimeRange,'dataRange')
|
|
TR = timerange(datestr(TimeRange.dataRange(1)),datestr(TimeRange.dataRange(2)));
|
|
end
|
|
|
|
ch1f = figure( 'Name', 'LopapChannel1 550','NumberTitle','off','Position',[10 100 550 800]);
|
|
% <Adapt>: The numbers in the curled brackets give wavelength for which you'd
|
|
% like to display the data. The numbers need to be exactly match the
|
|
% labels in the previous figure.
|
|
if isfield(TimeRange,'dataRange')
|
|
ch1ax=plot(LopapDataCh1(TR,:).Time,LopapDataCh1(TR,:).('550.7'));
|
|
else
|
|
ch1ax=plot(LopapDataCh1.Time,LopapDataCh1.('550.7'));
|
|
end
|
|
title(LopapParameters.instrumentReferenceWavelength(1))
|
|
% <Adapt>: The numbers in the brackets give the lower and upper limit
|
|
% of the y-axis. Adapt these to fit your data and remove the % sign.
|
|
%ch1s.AxesProperties.YLimits = [-0.4 -0.1];
|
|
grid ON
|
|
% Add title and axis labels
|
|
xlabel('Lab Time')
|
|
|
|
|
|
ch2f = figure( 'Name', 'LopapChannel2 550','NumberTitle','off','Position',[600 100 550 800]);
|
|
% <Adapt>: The numbers in the curled brackets give wavelength for which you'd
|
|
% like to display the data. The numbers need to be exactly match the
|
|
% labels in the previous figure
|
|
if isfield(TimeRange,'dataRange')
|
|
ch2ax=plot(LopapDataCh2(TR,:).Time,LopapDataCh2(TR,:).('550.5'));
|
|
else
|
|
ch2ax=plot(LopapDataCh2.Time,LopapDataCh2.('550.5'));
|
|
end
|
|
title(LopapParameters.instrumentReferenceWavelength(2))
|
|
% <Adapt>: The numbers in the brackets give the lower and upper limit
|
|
% of the y-axis. Adapt these to fit your data and remove the % sign.
|
|
% ch2s.AxesProperties.YLimits = [-0.2 0.3];
|
|
grid ON
|
|
% Add title and axis labels
|
|
xlabel('Lab Time')
|
|
|
|
clearvars -except Lopap* fileLocation myColorMap lopap* TimeRange* ch1f ch2f
|
|
if LopapParameters.Interactive == 1
|
|
distFig
|
|
fprintf('press any key if you want to proceed\n')
|
|
pause
|
|
%%
|
|
%
|
|
close all
|
|
end
|
|
%% LabBook :: Annotate Figure
|
|
%
|
|
%
|
|
% * 16:07 N2+water
|
|
% * 16:23 N2+R1+R2
|
|
% * 16:37 bubbles in the system
|
|
% * 16:46 N2/O2/RH(78%)+NO2+ flow tube in line + LIGHT
|
|
% * 17:05 N2/O2/RH(78%)+NO2+ flow tube in line è switch off light
|
|
% * 17:15 Close ABS channel and switch the tubes of R1+R2 to the water
|
|
% * 17:21 N2/O2/RH(78%) è open the ABS channel, bypass the reactor and close NO2 supply
|
|
% * 17:30 N2 è switch off O2 supply and the humidifier
|
|
% * 17:32 stop recording
|
|
|
|
% clc
|
|
% ax = ch1f.CurrentAxes;
|
|
% deltaT = 6;
|
|
% eTime = datetime("25-Feb-2021 16:07:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh1.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh1(xPos,:).('550.7'),...
|
|
% '\leftarrow N2+water');
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 16:23:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh1.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh1(xPos,:).('550.7'),...
|
|
% '\leftarrow N2+R1&R2');
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 16:37:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh1.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh1(xPos,:).('550.7'),...
|
|
% '\leftarrow Bubbles!');
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 16:46:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh1.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh1(xPos,:).('550.7'),...
|
|
% {['\leftarrow N2/O2/RH(78%)+NO2+'],[' flow tube in line + LIGHT']});
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 17:05:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh1.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh1(xPos,:).('550.7'),...
|
|
% '\leftarrow light off');
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 17:15:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh1.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh1(xPos,:).('550.7'),...
|
|
% '\leftarrow close ABS, water');
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 17:21:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh1.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh1(xPos,:).('550.7'),...
|
|
% '\leftarrow N2/O2/RH(78%) ABS open');
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% ax = ch2f.CurrentAxes;
|
|
% deltaT = 6;
|
|
% eTime = datetime("25-Feb-2021 16:07:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh2.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh2(xPos,:).('550.5'),...
|
|
% '\leftarrow N2+water');
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 16:23:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh2.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh2(xPos,:).('550.5'),...
|
|
% '\leftarrow N2+R1&R2');
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 16:37:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh2.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh2(xPos,:).('550.5'),...
|
|
% '\leftarrow Bubbles!');
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 16:46:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh2.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh2(xPos,:).('550.5'),...
|
|
% {['\leftarrow N2/O2/RH(78%)+NO2+'],[' flow tube in line + LIGHT']});
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 17:05:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh2.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh2(xPos,:).('550.5'),...
|
|
% '\leftarrow light off');
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 17:15:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh2.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh2(xPos,:).('550.5'),...
|
|
% '\leftarrow close ABS, water');
|
|
% set(ht,'Rotation',90);
|
|
%
|
|
% eTime = datetime("25-Feb-2021 17:21:00")+minutes(deltaT);
|
|
% xPos = find(LopapDataCh2.Time >= eTime,1);
|
|
% ht = text(ax,eTime,LopapDataCh2(xPos,:).('550.5'),...
|
|
% '\leftarrow N2/O2/RH(78%) ABS open');
|
|
% set(ht,'Rotation',90);
|
|
|
|
|
|
%% Plot selected spectra
|
|
%
|
|
% Compare to spectra to see if change is over whole wavelength or just
|
|
% where nitrite absorbs.
|
|
|
|
clc
|
|
close all
|
|
figure('Name', 'LopapSelectedSpectra')
|
|
plot(str2double(LopapSpecCh1.Properties.VariableNames),LopapSpecCh1{datestr(TimeRange.specCompareOne),:},...
|
|
'DisplayName',['#1 ' datestr(TimeRange.specCompareOne) ]) % a time where only R1&R2 was connected to the Lopap
|
|
hold on
|
|
plot(str2double(LopapSpecCh2.Properties.VariableNames),LopapSpecCh2{datestr(TimeRange.specCompareOne),:},...
|
|
'DisplayName',['#2 ' datestr(TimeRange.specCompareOne)],'LineStyle','--') % a time where only R1&R2 was connected to the Lopap
|
|
plot(str2double(LopapSpecCh1.Properties.VariableNames),LopapSpecCh1{datestr(TimeRange.specCompareTwo),:},...
|
|
'DisplayName',['#1 ' datestr(TimeRange.specCompareTwo)]) % a time where nitrite in R1 was connected to the Lopap
|
|
plot(str2double(LopapSpecCh2.Properties.VariableNames),LopapSpecCh2{datestr(TimeRange.specCompareTwo),:},...
|
|
'DisplayName',['#2 ' datestr(TimeRange.specCompareTwo)],'LineStyle','--') % a time where nitrite in R1 was connected to the Lopap
|
|
legend
|
|
box ON
|
|
grid ON
|
|
% Add title and axis labels
|
|
xlabel('wavelength [nm]')
|
|
ylabel('Intensity')
|
|
|
|
clearvars -except Lopap* fileLocation myColorMap LopapParameters TimeRange*
|
|
if LopapParameters.Interactive == 1
|
|
distFig
|
|
fprintf('press any key if you want to proceed\n')
|
|
pause
|
|
%%
|
|
%
|
|
close all
|
|
end
|
|
|
|
%% Process: Absorption spectrum
|
|
%
|
|
% Here, we reprocess the data to derive an absorption spectrum. This should
|
|
% match the spectra shown for nitrite in the Lopap manual.
|
|
|
|
clc
|
|
close all
|
|
indexR(1) = find(str2double(LopapSpecCh1.Properties.VariableNames) >= LopapParameters.wavelengthR,1);
|
|
indexR(2) = find(str2double(LopapSpecCh2.Properties.VariableNames) >= LopapParameters.wavelengthR,1);
|
|
|
|
figure('Name', 'LopapAbsorbtionSpectra')
|
|
plot(str2double(LopapSpecCh1.Properties.VariableNames),log10(LopapSpecCh1{datestr(TimeRange.specCompareTwo),...
|
|
indexR(1)}./LopapSpecCh1{datestr(TimeRange.specCompareTwo),:})-log10(LopapSpecCh1{datestr(TimeRange.specCompareOne),...
|
|
indexR(1)}./LopapSpecCh1{datestr(TimeRange.specCompareOne),:}),'DisplayName','#1')
|
|
hold on
|
|
plot(str2double(LopapSpecCh2.Properties.VariableNames),log10(LopapSpecCh2{datestr(TimeRange.specCompareTwo),...
|
|
indexR(2)}./LopapSpecCh2{datestr(TimeRange.specCompareTwo),:})-log10(LopapSpecCh2{datestr(TimeRange.specCompareOne),...
|
|
indexR(2)}./LopapSpecCh2{datestr(TimeRange.specCompareOne),:}),'DisplayName','#2','LineStyle','--')
|
|
legend
|
|
box ON
|
|
grid ON
|
|
% Add title and axis labels
|
|
xlabel('wavelength [nm]')
|
|
ylabel('ABS (log I_{r}/I_{i}')
|
|
title([datestr(TimeRange.specCompareOne) ' & ' datestr(TimeRange.specCompareTwo)])
|
|
clearvars -except Lopap* fileLocation myColorMap LopapParameters TimeRange*
|
|
if LopapParameters.Interactive == 1
|
|
distFig
|
|
fprintf('press any key if you want to proceed\n')
|
|
pause
|
|
%%
|
|
%
|
|
close all
|
|
end
|
|
|
|
%% Process :: Absorption with time
|
|
%
|
|
% Here, we reprocess the data to get the intensity with time for 1 chosen
|
|
% signal wavelength and 1 reference wavelength. The data is identical to that
|
|
% shown in the "measurement window" of the Lopap software.
|
|
%
|
|
% *The signal and the reference wavelength need to be identical to those
|
|
% used for the calibration* and are therefore taken from the calibration
|
|
% result file if present.
|
|
%
|
|
% The data is written to the _LopapTimeT_ time table. Rows hold the time,
|
|
% columns hold the processed signal for channel 1 and channel 2. Did I
|
|
% mention that it is important that the same signal wavelength and
|
|
% reference wavelength are taken for the calibration and for the
|
|
% experimental data.
|
|
|
|
clc
|
|
close all
|
|
indexS(1) = find(str2double(LopapSpecCh1.Properties.VariableNames) >= LopapParameters.wavelengthS,1);
|
|
indexS(2) = find(str2double(LopapSpecCh2.Properties.VariableNames) >= LopapParameters.wavelengthS,1);
|
|
indexR(1) = find(str2double(LopapSpecCh1.Properties.VariableNames) >= LopapParameters.wavelengthR,1);
|
|
indexR(2) = find(str2double(LopapSpecCh2.Properties.VariableNames) >= LopapParameters.wavelengthR,1);
|
|
LopapTimeT = timetable(LopapSpecCh1.Time,log10(LopapSpecCh1{:,indexR(1)}./LopapSpecCh1{:,indexS(1)}),...
|
|
log10(LopapSpecCh2{:,indexR(2)}./LopapSpecCh2{:,indexS(2)}));
|
|
LopapTimeT.Properties.VariableNames ={'Ch #1','Ch #2'};
|
|
|
|
TR = timerange(datestr(TimeRange.dataRange(1)),datestr(TimeRange.dataRange(2)));
|
|
figure('Name', 'Lopap TimeTable')
|
|
stackedplot(LopapTimeT(TR,:),{{'Ch #1','Ch #2'}});
|
|
title(['Lopap' datestr(LopapParameters.MeasurementDate)])
|
|
clearvars -except Lopap* fileLocation myColorMap LopapParameters TimeRange*
|
|
if LopapParameters.Interactive == 1
|
|
distFig
|
|
fprintf('press any key if you want to proceed\n')
|
|
pause
|
|
%%
|
|
%
|
|
close all
|
|
end
|
|
%% Process :: Background
|
|
%
|
|
% A linear background is fitted and subtracted (may be changed to
|
|
% higher order). Background MUST be measured at the beginning
|
|
% and at the end of the experiment for at least 30 minutes, ideally every
|
|
% few hours. Background is R1&R2 with zero-air (or N2) entering the
|
|
% stripping coil.
|
|
|
|
clc
|
|
close all
|
|
LopapTimeT = fitLopapBkgrd(LopapTimeT,'BkgrdPeriod',TimeRange.backgroundFit,'TimeRangeToPlot',TimeRange.dataRange);
|
|
clearvars -except Lopap* fileLocation myColorMap LopapParameters TimeRange*
|
|
if LopapParameters.Interactive == 1
|
|
distFig
|
|
fprintf('press any key if you want to proceed\n')
|
|
pause
|
|
%%
|
|
%
|
|
close all
|
|
end
|
|
%% Plot bkgrd corrected data
|
|
%
|
|
clc
|
|
close all
|
|
% Plot
|
|
TR = timerange(datestr(TimeRange.dataRange(1)),datestr(TimeRange.dataRange(2)));
|
|
figure('Name', 'Lopap TimeTable Bkgrd')
|
|
s=stackedplot(LopapTimeT(TR,:),{{'Ch #1 Bkgrd','Ch #2 Bkgrd'}});
|
|
title(['Lopap' datestr(LopapParameters.MeasurementDate)])
|
|
s.AxesProperties.YLimits = [-0.01 0.6];
|
|
clearvars -except Lopap* fileLocation myColorMap LopapParameters TimeRange*
|
|
if LopapParameters.Interactive == 1
|
|
distFig
|
|
fprintf('press any key if you want to proceed\n')
|
|
pause
|
|
%%
|
|
%
|
|
close all
|
|
end
|
|
%% Process :: Calibrate
|
|
%
|
|
% The results from the calibration fits are used here to calibrate the
|
|
% signal (intensity -> HONO in ppt).
|
|
|
|
clc
|
|
close all
|
|
if exist('LopapCalibCalibration','var')
|
|
LopapTimeT.('Ch #1 Calib') = LopapCalibCalibration.calib.fitresult.calibChannel1(LopapTimeT.('Ch #1 Bkgrd'));
|
|
LopapTimeT.('Ch #2 Calib') = LopapCalibCalibration.calib.fitresult.calibChannel2(LopapTimeT.('Ch #2 Bkgrd'));
|
|
|
|
disp('Settings of the calibration:')
|
|
disp(' ')
|
|
|
|
fprintf('Flow Reagents: %.2f and %.2f ml/min \n',...
|
|
LopapParametersCalibration.LopapParameters.flowReagents(1),...
|
|
LopapParametersCalibration.LopapParameters.flowReagents(2));
|
|
fprintf('Flow Gas: %.0f ml/min \n',...
|
|
LopapParametersCalibration.LopapParameters.flowGas(1));
|
|
fprintf('Temperature: %.0f K \n',LopapParametersCalibration.LopapParameters.temperature);
|
|
fprintf('Pressure: %.0f mbar \n',LopapParametersCalibration.LopapParameters.pressure);
|
|
fprintf('Reference Wavelength: %.0f nm \n',LopapParametersCalibration.LopapParameters.wavelengthR);
|
|
fprintf('Sample Wavelength: %.0f nm \n',LopapParametersCalibration.LopapParameters.wavelengthS);
|
|
|
|
disp('Settings of this measurement')
|
|
disp('')
|
|
fprintf('Reference Wavelength: %.0f nm \n',LopapParameters.wavelengthR);
|
|
fprintf('Sample Wavelength: %.0f nm \n',LopapParameters.wavelengthS);
|
|
|
|
% Plot
|
|
TR = timerange(datestr(TimeRange.dataRange(1)),datestr(TimeRange.dataRange(2)));
|
|
figure('Name', 'Lopap TimeTable Calibrated')
|
|
s=stackedplot(LopapTimeT(TR,:),{{'Ch #1 Calib','Ch #2 Calib'}});
|
|
title(['Lopap' datestr(LopapParameters.MeasurementDate)])
|
|
s.AxesProperties.YLimits = [-100 2500];
|
|
clearvars -except Lopap* fileLocation myColorMap LopapParameters TimeRange* fitresult calib
|
|
if LopapParameters.Interactive == 1
|
|
distFig
|
|
fprintf('press any key if you want to proceed\n')
|
|
pause
|
|
%%
|
|
%
|
|
close all
|
|
end
|
|
end
|
|
|
|
%% And Finally :: HONO
|
|
%
|
|
% * Channel 1 is from stripping coil 2. Its signal comes from NO2 and other
|
|
% nitrogen oxides that yield nitrite in the stripping solution and/or dye
|
|
% * Channel 2 is from stripping coil 1. Its signal comes from HONO plus
|
|
% the impurities that are also collected in coil 2.
|
|
%
|
|
% HONO is thus calibrated signal coil 2 (Channel 1) - that of coil 1
|
|
% (channel 2).
|
|
|
|
|
|
close all
|
|
if exist('LopapCalibCalibration','var')
|
|
LopapTimeT.('HONO') = LopapTimeT.('Ch #1 Calib')-LopapTimeT.('Ch #2 Calib');
|
|
|
|
% Plot
|
|
TR = timerange(datestr(TimeRange.dataRange(1)),datestr(TimeRange.dataRange(2)));
|
|
figure('Name', 'HONO')
|
|
s=stackedplot(LopapTimeT(TR,:),{'HONO'});
|
|
s.Title=['HONO in ppt with time ' datestr(LopapParameters.MeasurementDate)];
|
|
s.AxesProperties.YLimits = [-10 2500];
|
|
clearvars -except Lopap* fileLocation myColorMap LopapParameters TimeRange* fitresult calib
|
|
if LopapParameters.Interactive == 1
|
|
distFig
|
|
fprintf('press any key if you want to proceed\n')
|
|
pause
|
|
%%
|
|
%
|
|
close all
|
|
end
|
|
end
|
|
%% Save the data
|
|
%
|
|
save(['LopapMatlabData' datestr(LopapParameters.MeasurementDate,'yyyymmdd_HHMM') '.mat'],'LopapDataCh1','LopapDataCh2','LopapParameters','LopapSpecCh1','LopapSpecCh2')
|
|
save(['Lopap' datestr(LopapParameters.MeasurementDate,'yyyymmdd_HHMM') '.mat'],'LopapParameters','LopapTimeT','TimeRange')
|
|
% export to csv
|
|
TT = LopapTimeT(:,{'HONO'});
|
|
writetimetable(TT,['Lopap' datestr(LopapParameters.MeasurementDate,'yyyymmdd_HHMM') '.csv'])
|
|
clearvars TT
|
|
%% Local functions
|
|
function [fileLocation, myColorMap] = localInitializeMatlab
|
|
%INITIALIZEMATLAB Sets Lopap specific settings
|
|
% Adds processing functions to path and defines file locations for mac, windows,
|
|
% and Matlab online (which runs on unix)
|
|
|
|
% change working directory
|
|
path = matlab.desktop.editor.getActiveFilename;
|
|
[filepath,~,~] = fileparts(path);
|
|
cd(filepath);
|
|
|
|
|
|
% Data Server Address
|
|
if ismac
|
|
fileLocation.server = '/Volumes/';
|
|
fileLocation.dataPath = 'data_2411/Lopap';
|
|
% add Lopap functions and general add-ons to path
|
|
addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/Add-Ons');
|
|
addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/Lopap/1.LOPAP_Restliche Daten');
|
|
elseif ispc
|
|
fileLocation.server = '\\fs00\'; %UNC name for file server that hosts Napp shared drive
|
|
fileLocation.dataPath = 'data_2411\Lopap';
|
|
% add Lopap functions and general add-ons to path
|
|
addpath('C:\Users\iezzi_l\switchdrive\Add-Ons');
|
|
addpath('C:\Users\bletry_c\switchdrive\Add-Ons');
|
|
addpath('C:\Users\vieill_l\switchdrive\Add-Ons');
|
|
addpath('C:\Users\iezzi_l\switchdrive\Lopap\1.LOPAP_Restliche Daten');
|
|
addpath('C:\Users\bletry_c\switchdrive\Lopap\1.LOPAP_Restliche Daten');
|
|
addpath('C:\Users\vieill_l\switchdrive\Lopap\1.LOPAP_Restliche Daten');
|
|
% addpath('\\fs02\5601_surface_chemistry\People\Marc\Switchdrive\PSI_Matlab\Add-Ons');
|
|
% addpath('\\fs02\5601_surface_chemistry\People\Marc\Switchdrive\PSI_Matlab\Lopap\1.LOPAP_Restliche Daten');
|
|
|
|
elseif isunix
|
|
fileLocation.server = '/';
|
|
fileLocation.dataPath = 'Lopap/';
|
|
end
|
|
|
|
% Color maps
|
|
myColorMap.red = colormap(autumn(7));
|
|
myColorMap.blue = colormap(winter(7));
|
|
|
|
close all
|
|
end
|
|
|
|
|
|
|