Files
nappMATLAB-toolbox/nappIce/HowTo/nappIceHowTo.m
T
2023-08-09 15:02:10 +02:00

1383 lines
63 KiB
Matlab

%% How to analyse ISS XPS and NEXAFS data using Matlab
%
%% Introduction: Concept
%
% NEXAFS and XPS data from beam times is imported into a MATLAB table. The
% table allows to add meta data such as sample temperature, cell pressure,
% or Scienta settings (pass energy, etc). Further, data from several
% beam times can be imported and then filtered - for example to process all
% gas-phase CO2 PE from the last 5 years; or all ice NEXAFS at -10° to
% -12°C. Functions and the table are organised such that one can always go
% back to raw data to re-do the analysis or continue with processed data.
%
% The basic idea is that a set of MATLAB functions that import the data of
% different format and from various sources and that can be used to perform
% basic XPS and NEXAFS data processing are used, shared, and developed by
% all group members. This requires common data formats and naming. The
% scripts/live scripts/functions that are used to call the common MATLAB
% functions are written, stored, named individually by each user.
%
%
% <html>
% <img src="../Bildschirmfoto 2022-03-24 um 07.17.54.png" width="800">
% </html>
%% Introduction: Function calls
%
% Most functions need the MATLAB data table as input. The output can be
% stored in the same data table adding data to the original data table, or
% in a new one - thus creating a copy. Some functions such as those used
% for plotting do not write data.
%%
%
% InputTable = nappFunctionAbc(InputTable);
%
%%
% This command runs the function nappFunctionAbc on the data table
% _InputTable_ and writes the results into the same table (with the name
% _InputTable_.
%
% The _InputTable_ may hold different data types such as XPS data, NEXAFS,
% and pictures. Mostly, the functions require one and the same data type as
% input. *The _InputTable_ needs to be filtered when passed to a function*
% (see below). Exceptions from this are the |nappGenerateSpectra| and
% |nappPlot| functions that can be called with some limitations with
% mixed data as input (including pictures, that are ignored).
%
%%
%
% OutputTable = nappFunctionAbc(InputTable);
%
%%
%
% This command runs the same function on the data in the table _InputTable and
% writes the results into the data table _OutputTable_ which is a full copy
% of _InputTable_ plus the results of the function nappFunctionAbc.
%
%
% Most functions allow to set a number of optional input parameters, some
% require additional mandatory input. Please check the documentation of
% each function for further help:
%
%%
%
% help nappFunctionAbc
%
%%
%
% The mandatory input comes first in each function call. In the following
% example the data of the _InputTable_ is passed to the function as well as
% the variables _x_ and _y_. The optional function input is given just like
% in any MATLAB function using parameter descriptions: 'option',setting.
% Setting can be a text string in quotes, or a variable (array, logical,
% table, date number, etc). Most common are:
%
%%
%
% OutputTable = nappFunctionAbc(InputTable,x,y,'tableSelection',tmpDataSelection,'...
% 'tableVariable','TableVariable', energyScale','kinetic','mode','mean');
%
%%
% * 'tableSelection': allows to filter the table and run the function only
% on selected table lines. tmpDataSelection is a logical array, see section
% Work with data: Filter table in this document.
% * 'tableVariable': allows to choose the data of the data table that the
% function should work with. See Introduction: Data structure section in
% this document.
% * 'energyScale': allows to use kinetic or binding energy scale to plot or
% perform calculation.
% * 'mode': allows to select options for functions such as using mean or
% sum for calculations, etc.
% * 'showFigures': allows to view or view not figures and function output.
%
% Please consult the help files of each function for a complete list of
% options.
%
%% Introduction: Data structure
%
% It starts with importing the multi-dimensional IgorPro files that the SES
% software saves or with the h5 file structure that is saved for the NEXAFS
% data.
%
% * Upon import of the SES data, region iterations are averaged and
% counts are normalised to 1 s.
% * NEXAFS data...
%
% The data are then saved in a data table, each file in one row and the
% data in columns. Columns are called table variables in MATLAB and in the
% nappFunctions. The data columns are:
%
% * *image*: PE data: Intensity in counts-per-second vs. kinetic energy and sequence
% iteration. Functions that work with image data, overwrite this column.
% * *imageRoh*: a copy of image at the time of data import.
% * *spectrum_countsPerSecond* and *spectrum_counts*: Hold the spectra that
% are computed from the image. These data columns are modified by
% nappFunctions that work with spectrum data.
% * *spectrumRoh_countsPerSecond* and *spectrumRoh_counts*: a copy of the
% spectrum data at time of generation.
%
% In other words, the data in the columns spectrum_countsPerSecond,
% spectrum_counts, image always hold the processed data and are modified by
% each function call. The Roh data allows to go back and re-do the
% processing. Next to this the data table stores analyser settings such as
% scientaEkin and sample parameters such as temperature and pressure. View
% the data table in the data viewer or command window of MATLAB to see all
% columns. This data structure allows to process all data and then still plot
% images, unprocessed data, or processed data of selected experiments.
%% ToDo
%
% * add code for intensity vs. time plotting
% * add code for average and plot iterations.
% * get rid of peakfind and replace by gauss fitting
% * use gauss fitting function within functions?
% * Tidy html output, and get Yanisha's feedback
% * Add section on how to modify figures after plotting
% * add section on how to access data in table
% * add section on how to merge data tables
% * Work on code and add section how to remove XPS from NEXAFS
% * Work on code and add section on I0 including 2nd order light
% * Add code to add combined spectra to data table as row.
% * Update help files for NEXAFS functions and NEXAFS options in general
% functions.
% * Set-up folders for Yanisha
%% Prepare: Initialise MATLAB
%
% You need to have access to the folder holding the functions and helper
% files. These are shared via switch drive.
%
% *Add the paths to the initializeMatlab function at the end of this
% script* This function needs to be added to the end of each of your
% scripts or live scripts. Below is an example.
%
%%
%
% function [myColorMap, PsiFarbe] = initializeMatlab
% %initializeMatlab Sets NappIce specific settings
% % Adds Napp files 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);
%
% % The fitting routines writes quite a lot of feedback and warnings. I shut them off.
% warning('off','all')
% warning off backtrace
% warning off verbose
%
% % Functions and helper files path:
% if ismac
% % add Napp files to path
% addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/Add-Ons');
% addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/nappIce');
% elseif ispc
% % add Napp files to path
% addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/Add-Ons');
% addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/nappIce');
% elseif isunix
% % add Napp files to path
% addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/Add-Ons');
% addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/nappIce');
% end
%
% % Color maps
% myColorMap.red = colormap(autumn(7));
% myColorMap.blue = colormap(winter(7));
%
% % define PSI cooperate identity colours
% PsiFarbe.hellgrau = [226 226 226]/255;
% PsiFarbe.mittelgrau = [184 184 184]/255;
% PsiFarbe.dunkelgrau = [78 78 77]/255;
% PsiFarbe.blaugrau = [236 236 243]/255; % This is actually not a PSI colour
% PsiFarbe.gelb = [239 200 37]/255;
% PsiFarbe.hellorange = [227 164 31]/255;
% PsiFarbe.dunkelorange = [207 92 22]/255;
% PsiFarbe.hellrot = [164 36 23]/255;
% PsiFarbe.dunkelbraun = [114 85 65]/255;
% PsiFarbe.hellbraun = [127 119 47]/255;
% PsiFarbe.mittelgruen = [135 150 59]/255;
% PsiFarbe.hellgruen = [195 214 47]/255;
% PsiFarbe.dunkelgruen = [72 130 33]/255;
% PsiFarbe.dunkelrot = [104 47 86]/255;
% PsiFarbe.dunkelblau = [37 65 108]/255;
% PsiFarbe.mittelgruenblau = [61 164 168]/255;
% PsiFarbe.hellblau = [58 162 190]/255;
% PsiFarbe.mittelblau = [50 118 158]/255;
%
% end
%%
% The path might be different
% on your computer depending how you have set up SwitchDrive:
%
%%
%
% addpath('C:\Users\bletry_c\switchdrive\PSI_Matlab\nappIce');
% addpath('C:\Users\bletry_c\switchdrive\PSI_Matlab\Add-Ons');
%
%%
% then run the initialiseMatlab function:
%%
% clearvars
% [myColorMap, PsiFarbe] = initializeMatlab;
% close all
% clc
%% Prepare: ISS data structure and path to local copy of ISS data
%
% Data needs to be organised in beam time folders that can be located on the
% Napp drive or locally on your computer. The data folder naming and
% structure within the beam time folder (orange on figure) is strict and
% there must not be any subfolders in the data folders:
%
% <html>
% <img src="../Bildschirmfoto 2022-03-23 um 08.19.22.png" width="400">
% </html>
%%
% * NEXAFS holds *.h5 XAS data
% * Photos holds *.bmp pictures
% * Pressure holds the *.dat LabView files
% * SES holds the *.ibw PE data.
% * To run the scripts, there *needs to be at
% least ONE *.ibw file in the SES folder*
%
%
%
% *beam time folder location*
%
% * The beam time folder can be a subfolder of any number of folders.
% * The beam time folder needs to have the same name, same subfolders, and
% folders above (path) locally and on the NAPP drive. This can be set by
% the user when calling the import function. As standard, we use
% "year:YYYY_MM__monthIssIceNapp"
% * on Napp drive: the beam time folder (and folders above) needs to be
% within the "SC Data" folder
% * locally: the beam time folder (and folders above) needs to be within
% your "MATLAB home folder:NAPP:SC Data" folder
%
%
% The see all import options (few examples given below) check out the
% nappFileList.m help (this works for all nappIce functions):
%%
%
% help nappFileList.m
%
%% Helper functions
%
% * Napp_p_ice(T_current) states and plots the vapour pressure of ice between 200-270 K
% * Napp_p_RH(T_current,RH) calculates the partial pressure of water for a given
% temperature and relative humidity.
% * Napp_RH_p(T_current,partial_pressure_water) calculates the relative humidity for a given
% temperature and water pressure.
%% Import ISS data: Complete beam time folder
%
%%
%
% FileList = nappFileList('2022/2022_02__FebIssIceNapp');
%
%%
% This will create a new data table "FileList" overwriting any previous
% versions of this list with data imported from the local copy of the beam
% time folder with the name "2022_02__FebIssIceNapp" being a subfolder of
% the folder "2022".
%%
clearvars
%%
[myColorMap, PsiFarbe] = initializeMatlab;
close all
clc
%%
if isfile('nappIceHowToData.mat')
load('nappIceHowToData.mat')
disp('data read from mat file')
else
FileList = nappFileList('2022/2022_02__FebIssIceNapp');
% add photon energy to table
FileList = addPhotonEnergy(FileList,[1,8:12,26],1000,2,2022);
FileList = addPhotonEnergy(FileList,[2:3,5,7,13:14,16:18,20:25,27:31,33:35,37:38,40,42,44,46,47,49:51,54:56,60:62,65:66,68,70,73,74,76,77,82],900,2,2022);
FileList = addPhotonEnergy(FileList,[4,6,15,19,58,59,64,67,72,80,81],650,2,2022);
FileList = addPhotonEnergy(FileList,[32,36,39,41,43,45,48,57,63,69,71,75,78,83],1150,2,2022);
FileList = addPhotonEnergy(FileList,79,NaN,2,2022);
% add sample description
FileList = addSampleNotes(FileList,[1,8:11],'Sample holder',2,2022);
FileList = addSampleNotes(FileList,[2:7,35:36,56:60],'Ice with N2',2,2022);
FileList = addSampleNotes(FileList,[12:34,54:55],'Ice',2,2022);
FileList = addSampleNotes(FileList,[16,20],'Ice (bad data)',2,2022);
FileList = addSampleNotes(FileList,[37:51,61:72],'Ice with N2 and phenol in Ar',2,2022);
FileList = addSampleNotes(FileList,44,'Ice with N2 and phenol in Ar (bad data)',2,2022);
FileList = addSampleNotes(FileList,73:76,'H2O gas-phase',2,2022);
FileList = addSampleNotes(FileList,73,'H2O gas-phase (bad data)',2,2022);
FileList = addSampleNotes(FileList,77:83,'CO2 gas-phase',2,2022);
FileList = addSampleNotes(FileList,79,'CO2 gas-phase (bad data)',2,2022);
% import data and add to data table
FileList = nappFileList('2021/2021_10__OctIssIceNapp',FileList);
FileList = nappFileList('2021/2021_08__AugIssIceNapp',FileList);
% add photon energy to table
FileList = addPhotonEnergy(FileList,1:10,1000,8,2021);
FileList = addPhotonEnergy(FileList,36:42,1000,8,2021);
FileList = addPhotonEnergy(FileList,51:72,1000,8,2021);
FileList = addPhotonEnergy(FileList,78:120,1000,8,2021);
FileList = addPhotonEnergy(FileList,1:6,1000,10,2021);
FileList = addPhotonEnergy(FileList,8,500,10,2021);
FileList = addPhotonEnergy(FileList,10,750,10,2021);
FileList = addPhotonEnergy(FileList,13,500,10,2021);
FileList = addPhotonEnergy(FileList,16,500,10,2021);
FileList = addPhotonEnergy(FileList,17,750,10,2021);
FileList = addPhotonEnergy(FileList,18:20,500,10,2021);
FileList = addPhotonEnergy(FileList,21,750,10,2021);
FileList = addPhotonEnergy(FileList,23,500,10,2021);
FileList = addPhotonEnergy(FileList,26,600,10,2021);
FileList = addPhotonEnergy(FileList,27,850,10,2021);
FileList = addPhotonEnergy(FileList,28:31,600,10,2021);
FileList = addPhotonEnergy(FileList,32:51,1000,10,2021);
FileList = addPhotonEnergy(FileList,53:68,1000,10,2021);
FileList = addPhotonEnergy(FileList,[74,76:85,87:91,93:94],1000,10,2021);
% add sample description
FileList = addSampleNotes(FileList,1:10,'MgO in N2',8,2021);
FileList = addSampleNotes(FileList,36:39,'MgO in H2O',8,2021);
FileList = addSampleNotes(FileList,40:44,'MgO in N2',8,2021);
FileList = addSampleNotes(FileList,45:49,'MgO in Ar',8,2021);
FileList = addSampleNotes(FileList,[51,53:55],'MgO in UHV',8,2021);
FileList = addSampleNotes(FileList,56:60,'MgO ice (bad data)',8,2021);
FileList = addSampleNotes(FileList,[61,66:72],'MgO ice in Ar HONO',8,2021);
FileList = addSampleNotes(FileList,61,'MgO ice in Ar HONO (bad data)',8,2021);
FileList = addSampleNotes(FileList,[68,69,70, 72],'MgO ice in Ar HONO on(bad data)',8,2021);
FileList = addSampleNotes(FileList,78:80,'MgO in UHV',8,2021);
FileList = addSampleNotes(FileList,81:82,'MgO in H2O',8,2021);
FileList = addSampleNotes(FileList,83:85,'MgO ice',8,2021);
FileList = addSampleNotes(FileList,86:94,'MgO ice AA in Ar',8,2021);
FileList = addSampleNotes(FileList,[86 88],'MgO ice AA in Ar (bad data)',8,2021); % temporarily, Ar very dominating
FileList = addSampleNotes(FileList,89,'MgO ice AA in Ar (bad data)',8,2021);
FileList = addSampleNotes(FileList,98,'Ar',8,2021);
FileList = addSampleNotes(FileList,99,'SiO2 in H2O',8,2021);
FileList = addSampleNotes(FileList,100:103,'SiO2 ice',8,2021);
FileList = addSampleNotes(FileList,104:110,'SiO2 ice AA in Ar',8,2021);
FileList = addSampleNotes(FileList,111:112,'SiO2 ice',8,2021);
FileList = addSampleNotes(FileList,113:118,'SiO2 ice AA in Ar',8,2021);
FileList = addSampleNotes(FileList,119:120,'CO2',8,2021);
FileList = addSampleNotes(FileList,1,'MgO in N2',10,2021);
FileList = addSampleNotes(FileList,2,'MgO in N2, PE 50, Slits 1/1/1',10,2021);
FileList = addSampleNotes(FileList,3,'MgO in N2, PE 50, Slits 1/1/1',10,2021);
FileList = addSampleNotes(FileList,5,'MgO in N2, PE 50, Slits 1/0.5/0.5',10,2021);
FileList = addSampleNotes(FileList,6,'MgO in N2, PE 50, Slits 1/1/1',10,2021);
FileList = addSampleNotes(FileList,8,'MgO in N2, PE 20, Slits 1/1/1',10,2021);
FileList = addSampleNotes(FileList,10,'MgO in N2, PE 20, Slits 1/1/1',10,2021);
FileList = addSampleNotes(FileList,13,'MgO in N2, PE 20, Slits 1/1/1',10,2021);
FileList = addSampleNotes(FileList,16,'MgO in N2, PE 20, Slits 1/0.8/0.8',10,2021);
FileList = addSampleNotes(FileList,18,'MgO in N2, PE 20, Slits 1/0.8/0.8',10,2021);
FileList = addSampleNotes(FileList,19,'MgO in N2, PE 20, Slits 0.5/1/1',10,2021);
FileList = addSampleNotes(FileList,20,'MgO in N2, PE 20, Slits 0.5/1/1',10,2021);
FileList = addSampleNotes(FileList,21,'MgO in N2, PE 20, Slits 0.5/1/1',10,2021);
FileList = addSampleNotes(FileList,23,'MgO in N2, PE 20, Slits 0.5/1/1',10,2021);
FileList = addSampleNotes(FileList,26,'MgO in N2, PE 50, Slits 0.5/1/1',10,2021);
FileList = addSampleNotes(FileList,27,'MgO in N2, PE 20, Slits 0.5/1/1',10,2021);
FileList = addSampleNotes(FileList,28,'MgO in N2, PE 50, Slits 0.5/0.5/0.5',10,2021);
FileList = addSampleNotes(FileList,29,'MgO in N2, PE 50, Slits 1/1/1',10,2021);
FileList = addSampleNotes(FileList,31,'MgO in N2, PE 20, Slits 1/1/1',10,2021);
FileList = addSampleNotes(FileList,32:33,'MgO in N2',10,2021);
FileList = addSampleNotes(FileList,34:36,'MgO ice',10,2021);
FileList = addSampleNotes(FileList,37:41,'MgO in H2O',10,2021);
FileList = addSampleNotes(FileList,42:51,'MgO ice',10,2021);
FileList = addSampleNotes(FileList,45,'MgO ice (bad data)',10,2021);
FileList = addSampleNotes(FileList,[53:68,70:71],'MgO ice AA in N2' ,10,2021);
FileList = addSampleNotes(FileList,54,'MgO ice AA in N2 (bad data)' ,10,2021);
FileList = addSampleNotes(FileList,68,'MgO ice AA in N2 (bad data)' ,10,2021);
FileList = addSampleNotes(FileList,63,'MgO ice AA in N2 (bad data)' ,10,2021);
FileList = addSampleNotes(FileList, [72,74],'MgO in H2O' ,10,2021);
FileList = addSampleNotes(FileList, [76,78:80],'MgO in N2 AA plus H2O' ,10,2021);
FileList = addSampleNotes(FileList,81:82,'SiO2 in N2',10,2021);
FileList = addSampleNotes(FileList,83:85,'SiO2 ice',10,2021);
FileList = addSampleNotes(FileList,87:90,'SiO2 in H2O',10,2021);
FileList = addSampleNotes(FileList,91,'SiO2 AA in N2',10,2021);
FileList = addSampleNotes(FileList,93:94,'SiO2 in H2O AA',10,2021);
% import
FileList = nappFileList('2020/202008AugustISS',FileList);
FileList = addSampleNotes(FileList,3,'diode upstream',8,2020);
FileList = addSampleNotes(FileList,4,'diode in-cell',8,2020);
FileList = addSampleNotes(FileList,8,'diode upstream',8,2020);
FileList = addSampleNotes(FileList,9,'diode in-cell',8,2020);
FileList = addSampleNotes(FileList,10,'diode in-cell',8,2020);
FileList = addSampleNotes(FileList,11,'diode upstream',8,2020);
FileList = addSampleNotes(FileList,13:23,'O_K-edge ice',8,2020);
FileList = addSampleNotes(FileList,13:18,'O_K-edge ice (bad S/N)',8,2020);
FileList = addSampleNotes(FileList,[15,19,20],'O_K-edge ice (no notes)',8,2020);
%ListNexafs = addSampleNotes(ListNexafs,21:23,'O_K-edge ice (ice unstable)',8,2020);
FileList = addSampleNotes(FileList,24,'diode (no notes)',8,2020);
FileList = addSampleNotes(FileList,25,'diode upstream',8,2020);
FileList = addSampleNotes(FileList,[26,28,30],'O_K-edge gold',8,2020);
FileList = addSampleNotes(FileList,[27,29,31],'O_K-edge gold (no notes)',8,2020);
FileList = addSampleNotes(FileList,[32,33],'(no notes)',8,2020);
FileList = addSampleNotes(FileList,[34,35,37,38],'diode in-cell',8,2020);
FileList = addSampleNotes(FileList,[36,39:42],'diode upstream',8,2020);
FileList = addSampleNotes(FileList,43:45,'O_K-edge gold',8,2020);
FileList = addSampleNotes(FileList,[48,50],'diode upstream',8,2020);
FileList = addSampleNotes(FileList,[49,51,54],'(no notes)',8,2020);
FileList = addSampleNotes(FileList,[43:45,52,53,55:59],'O_K-edge gold',8,2020);
FileList = addSampleNotes(FileList,53,'O_K-edge gas-phase (interference)',8,2020);
FileList = addSampleNotes(FileList,54,'O_K-edge (no data)',8,2020);
FileList = addSampleNotes(FileList,55,'O_K-edge gas-phase',8,2020);
FileList = addSampleNotes(FileList,60,'diode upstream',8,2020);
FileList = addSampleNotes(FileList,[61,63],'O_K-edge ice',8,2020);
% ListNexafs = addSampleNotes(ListNexafs,61,'O_K-edge ice (ice unstable)',8,2020);
FileList = addSampleNotes(FileList,62,'O_K-edge ice (no notes)',8,2020);
FileList = addSampleNotes(FileList,64,'diode upstream',8,2020);
FileList = addSampleNotes(FileList,65,'diode in-cell',8,2020);
FileList = addSampleNotes(FileList,66,'diode in-cell',8,2020);
save('nappIceHowToData.mat','FileList');
end
%% Import ISS data: Error messages
%
% If you get a message like this in the command window
%
% There appears to be no file in the SES folder. Add at least one file first.
% I quit now
%
%%
% and MATLAB quits running the script, please check that there is at least
% a *.ibw file in the SES folder
%%
% If you instead get a message like this
%
% There is something wrong with the path. Check for typo and that the drives are mounted
% I quit now
%
%%
% and MATLAB quits running the script, please check
%
% * that there are no typos in the path names
% * that the drives are mounted.
%% Import ISS data: Add data to existing data table
%
% This will import data from the beam time folder
% "2021/2021_08__AugIssIceNapp" on the NAPP drive adding the data to the data table
% "FileList" in the MATLAB workspace
%%
% FileList = nappFileList('2021/2021_08__AugIssIceNapp',FileList,'mode','nappDrive');
%% Import ISS data: Add new SES or NEXAFS files from local beam time folder
%
% Using the mode 'localNew' the content of the beam time folder will be
% compared to that of the FileList in the workspace and only those files
% not yet imported will be processed. This is a little faster and preserves
% any changes to the FileList. *To prevent data failure of running SES
% measurements, this only works on the local copy of the beam time folder*
%%
%
% FileList = nappFileList('2022/2022_02__FebIssIceNapp',FileList,'mode','localNew');
%
%% Import ISS data: Choose files manually
%
% This will open a windows file explorer window where you can choose as
% many data files to be imported as you want. In this example, a new
% FileList is written, overwriting any previous versions in the workspace.
%%
%
% FileList = nappFileList('2022/2022_02__FebIssIceNapp','mode','nappDrivePick');
%
%
% <html>
% <img src="../Bildschirmfoto 2022-03-23 um 11.14.44.png" width="400">
% </html>
%% Work with data: Excel
%
% The nappFileList.m function also writes a csv file to the beam time
% folder. Open it as xlsx and use Excels formatting and filtering tools to
% work with your data set. So, the xlsx file is edited manually and might
% contain additional information that you have added such as slit settings,
% comments, type of sample, scope of the measurement, etc. The csv file it
% automatically generated and might thus be frequently be over-written. Use
% copy/paste to update the xlsx file with new data, formatting will be
% automatically applied to new data then.
%%
%
%
% <html>
% <img src="../Bildschirmfoto 2019-05-08 um 09.58.47.png" width="800">
% </html>
%% Work with data: Add photon energy to table (XPS)
%
% ISS beamline does not log settings of SES data. Photon energy, which is
% needed to calculate the binding energy later, needs to be added manually.
% This will read the FileList table and add the photon energy "1000" to the
% SES data with file numbers 1,8 to 12, and 26 acquired in February (month
% "2") of the year "2022"). Note, this is only adding to XPS data, NEXAFS
% data are not touched:
%%
%
% FileList = addPhotonEnergy(FileList,[1,8:12,26],1000,2,2022);
%
%% Work with data: Add sample description
%
% Sample description to label figures and for filtering data can be added.
% It does not make sense to use temperature or pressure, as these data are
% written to the table anyway. It does make sense to use standard phrases
% to enable filtering all beam time data. This code example follow the same
% input structure as the addPhotonEnergy function. This function works on
% both NEXAFS and XPS data. One may limit and select either one
% specifically by adding either 'NEXAFS' or 'XPS' strings as last input
% parameter. This is optional, if not specified function runs on both data
% types:
%%
%
% FileList = addSampleNotes(FileList,[1,8:11],'Sample holder',2,2022,'XPS');
% FileList = addSampleNotes(FileList,[1,8:11],'Sample holder',2,2022,'NEXAFS');
% FileList = addSampleNotes(FileList,[2:7,35:36,56:60],'Ice with N2',2,2022);
% FileList = addSampleNotes(FileList,73:76,'H2O gas-phase',2,2022);
% FileList = addSampleNotes(FileList,73,'H2O gas-phase (bad data)',2,2022);
%% Work with data: Filter table
%
% An advantage of the data table is filtering. This works with standard
% MATLAB functions using logical operations. Main motivation of filtering
% is to work with selected subset of data which for example can be
% processed with the same settings, fitted with the same constrains, or
% shall be plotted in one graph for comparison.
%
% Further, the _InputTable_ may hold different data types such as XPS data,
% NEXAFS, and pictures. Mostly, the functions require one and the same data
% type as input. Therefore, *the _InputTable_ needs to be filtered when
% passed to most functions*. Exceptions from this are the
% |nappGenerateSpectra| and |nappPlot| functions that can be called with
% some limitations in the settings with mixed data as input (including
% pictures, that are ignored).
%
% The first example filter CO2 gas-phase C1s PE data that is not "(bad
% data)" and has a pass energy of 50 eV. In the second example, we pick a
% C1s or O1s PE data from the SES file #77 from February 2022. Any table
% column can be used for filtering. "&" means AND "|" is OR.
%
%%
% tmpDataSelection1 = matches(FileList.sample,'CO2 gas-phase') ...
% & ~contains(FileList.sample,'(bad data)')...
% & contains(FileList.name,'C1s')...
% & FileList.scientaPassEnergy_eV == 50 ;
%
% tmpDataSelection2 = (contains(FileList.name,'077_C1s') | contains(FileList.name,'077_O1s')) ...
% (month(FileList.lastModifiedDatenum) == 2) &...
% (year(FileList.lastModifiedDatenum) == 2022);
%%
tmpDataSelection1 = matches(FileList.sample,'CO2 gas-phase') ...
& ~contains(FileList.sample,'(bad data)')...
& contains(FileList.name,'C1s')...
& FileList.scientaPassEnergy_eV == 50 ;
tmpDataSelection2 = (contains(FileList.name,'077_C1s') | contains(FileList.name,'077_O1s'))& ...
(month(FileList.lastModifiedDatenum) == 2) &...
(year(FileList.lastModifiedDatenum) == 2022);
%% Work with data: Display filtered table and selected columns
%
% MATLAB tables allow to address the columns by name. To display only the
% rows that match the filter criteria and only specific columns, code like
% the examples below can be used:
%%
% disp(FileList(tmpDataSelection1,{'name','sample','xRayEkin_eV','scientaPassEnergy_eV','lastModifiedDatestr','sampleTemp_dC',...
% 'cellPressure_mbar' }))
% disp(FileList(tmpDataSelection2,{'name','scientaLensMode','xRayEkinRange_eV','scientaPassEnergy_eV'}))
%%
disp(FileList(tmpDataSelection1,{'name','sample','xRayEkin_eV','scientaPassEnergy_eV','lastModifiedDatestr','sampleTemp_dC',...
'cellPressure_mbar' }))
disp(FileList(tmpDataSelection2,{'name','scientaLensMode','xRayEkinRange_eV','scientaPassEnergy_eV'}))
clearvars tmp*
%%
%
%% Work with data: Modify data in table
%
% There might be bad sweeps (sequence iterations) either with too low
% signal to noise or because some setting was changed during the run. These
% can be removed by directly addressing the data in the images. Same
% procedure, first the data (table row) is filtered, then the image
% modified for the selected data.
%
% *remove one sweep*
%%
%
% tmpDataSelection = contains(FileList.name,'077_C1s')& ...
% (month(FileList.lastModifiedDatenum) == 2) &...
% (year(FileList.lastModifiedDatenum) == 2022);
% FileList(tmpDataSelection,:).image{:}(:,3)=[];
%
% tmpDataSelection = contains(FileList.name,'077_O1s')& ...
% (month(FileList.lastModifiedDatenum) == 2) &...
% (year(FileList.lastModifiedDatenum) == 2022);
% FileList(tmpDataSelection,:).image{:}(:,3)=[];
%
%%
% *remove several sweeps*
%
%%
%
% tmpDataSelection = contains(FileList.name,'059_C1s')& ...
% (month(FileList.lastModifiedDatenum) == 10) &...
% (year(FileList.lastModifiedDatenum) == 2021);
% FileList(tmpDataSelection,:).image{:}(:,5:15)=[];
%%
% *remove all data (complete table rows) outside a specific time window*
%
%%
% tmpTime.start = datenum('30-Apr-2019 02:00:00');
% tmpTime.end = datenum('30-Apr-2019 05:00:00');
% toDelete = Table_FileList.datenum <= tmpTime.start;
% Table_FileList(toDelete,:) = [];
% toDelete = Table_FileList.datenum >= tmpTime.end;
% Table_FileList(toDelete,:) = [];
%%
% *Correct beam line-offset in data*
%
% This will correct 1.6 from the X-ray energies, of particular importance
% for NEXAFS data. One can also do this on selected data.
%%
% beamlineOffset = 1.6;
% FileList.xRayEkin_eV = cellfun(@(x) x+beamlineOffset,FileList.xRayEkin_eV,'UniformOutput',false);
%% Add data (columns) to table
%
% Calculation results for each row can be added to data tables using
% standard Matlab functions. This example illustrates the use of
% anonymous functions, their call for each row using |cellfun|, and
% the generation of additional columns to which (selection of) the data are
% written.
%%
%
% fun1 =@(c) interp1(IzeroAugInCell(:,1),IzeroAugInCell(:,2), c);
% fun2 =@(c) interp1(IzeroAugInCell(:,1),IzeroAugInCell(:,3), c);
% tmpMatch = (month(ListNexafs.lastModifiedDatenum) == 8) &...
% (year(ListNexafs.lastModifiedDatenum) == 2020) |...
% (startsWith(ListNexafs.name, 'sum_Aug'));
% ListNexafs.uhvI0(tmpMatch) = cellfun(fun1, ListNexafs.xRayEkin_eV(tmpMatch) ,'uni' , 0);
% ListNexafs.uhvI0std(tmpMatch) = cellfun(fun2, ListNexafs.xRayEkin_eV(tmpMatch) ,'uni' , 0);
% clearvars tmp* fun*
%% Plot data: XPS images
%
% We use the nappPlot function to plot the images. For this, we specify
% the column of the data table that should be plotted:
% 'tableVarialbe','image' plots the image for all data in FileList that are
% selected by the logical array tmpDataSelection (See _Filtering table_
% above).
%%
%
% nappPlot(FileList,tmpDataSelection,'tableVariable','image');
%
%%
close all
tmpDataSelection = contains(FileList.name,'035_O1s') & FileList.xRayEkinRange_eV(:,1) == 900 ...
& FileList.scientaPassEnergy_eV == 50 ...
& (month(FileList.lastModifiedDatenum) == 2) ...
& (year(FileList.lastModifiedDatenum) == 2022) ...
& (day(FileList.lastModifiedDatenum) >= 27);
nappPlot(FileList,tmpDataSelection,'tableVariable','image');
%% Plot data: XPS and NEXAFS images
%
% This example filters for a XPS file name and a NEXAFS file name and shows
% two things. First, that the XPS file name is not unique and filtering
% thus needs to be combined with extra parameters such as date and second
% how NEXAS and XPS data can be simultaneously passed to the |nappPlot|
% function
%%
% tmpDataSelection = matches(FileList.name,'0067067_O1s_1000eV.ibw') | matches(FileList.name, '0063_20200824_042852_O_K_edge.h5');
% nappPlot(FileList,tmpDataSelection);
%%
tmpDataSelection = matches(FileList.name,'0067067_O1s_1000eV.ibw') | matches(FileList.name, '0063_20200824_042852_O_K_edge.h5');
nappPlot(FileList,tmpDataSelection);
%% Plot data: XPS spectra
%
% We use the nappPlot function to plot the spectra by selecting
% 'spectrum_countsPerSecond' as 'tableVariable'. Further options include
% the binding or kinetic energy scale, and each spectrum in a separate
% window, or all in one window by setting the 'mode'. This works, of
% course, only after the spectrum has been generated using the function
% nappGenerateSpectra.
%%
%
% nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsPerSecond',...
% 'mode','AllInOne','energyScale','kinetic');
%
%%
close all
tmpDataSelection = matches(FileList.sample,'Ice with N2')...
& ~contains(FileList.sample,'(bad data)')...
& contains(FileList.name,'O1s') & FileList.xRayEkinRange_eV(:,1) == 900 ...
& FileList.scientaPassEnergy_eV == 50 ...
& (month(FileList.lastModifiedDatenum) == 2) ...
& (year(FileList.lastModifiedDatenum) == 2022) ...
& (day(FileList.lastModifiedDatenum) >= 27);
FileList = nappGenerateSpectra(FileList,tmpDataSelection);
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsPerSecond',...
'mode','AllInOne','energyScale','kinetic');
%% Plot data: NEXAFS spectra
%
% We use the same, one-and-only nappPlot function to plot the NEXAFS
% spectra by selecting 'spectrum_counts' as 'tableVariable' and
% 'energyScale' as 'xRay'. Further options include plotting each spectrum
% in a separate window, or all in one window by setting the 'mode'. This
% works, of course, only after the spectrum has been generated using the
% function nappGenerateSpectra.
%%
%
% nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_counts','energyScale','xRay','mode','OneEach')
%
%%
%
close all
clc
tmpDataSelection = contains(FileList.name, '0063_20200824_042852_O_K_edge');
% Sum Auger-Meitner Spectrum
FileList = nappGenerateSpectra(FileList,'tableSelection',tmpDataSelection,'mode','sum');
% Plot
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_counts','energyScale','xRay','mode','OneEach');
%% Plot data: Figure layout
%
% The |nappPlot| function has 3 pre-defined figure layouts optimised for
% the computer screen, for powerpoint presentation or for word (and other
% text) files:
%%
%
% nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_counts','energyScale','xRay','mode','OneEach','figureMode','screen');
%
%%
close all
clc
tmpDataSelection = contains(FileList.name, '0063_20200824_042852_O_K_edge');
% Sum Auger-Meitner Spectrum
FileList = nappGenerateSpectra(FileList,'tableSelection',tmpDataSelection,'mode','sum');
% Plot
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_counts','energyScale','xRay','mode','OneEach','figureMode','screen');
%%
%
% nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_counts','energyScale','xRay','mode','OneEach','figureMode','word');
%
%%
close all
clc
tmpDataSelection = contains(FileList.name, '0063_20200824_042852_O_K_edge');
% Sum Auger-Meitner Spectrum
FileList = nappGenerateSpectra(FileList,'tableSelection',tmpDataSelection,'mode','sum');
% Plot
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_counts','energyScale','xRay','mode','OneEach','figureMode','word');
%%
%
% nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_counts','energyScale','xRay','mode','OneEach','figureMode','powerpoint');
%
%%
close all
clc
tmpDataSelection = contains(FileList.name, '0063_20200824_042852_O_K_edge');
% Sum Auger-Meitner Spectrum
FileList = nappGenerateSpectra(FileList,'tableSelection',tmpDataSelection,'mode','sum');
% Plot
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_counts','energyScale','xRay','mode','OneEach','figureMode','powerpoint');
%% Plot data: Export the Figure (for use in powerpoint)
%
% Either, copy paste the figure, or use this command on the front most
% figure in Matlab:
%%
%
% set(gcf,'InvertHardcopy','on');
% print('NameForFigureFile, '-dpng', '-r220');
%
%% Plot data: Add region labels to survey
%
% Here is an example of how to mark regions of interest in survey plots.
% For this, a survey must be the topmost figure.
%%
% dataObjs = findobj(gcf,'-property','YData');
% tmpxShift = 5; % binding energy shift and mono offset
% tmpxRayEnergy = 900; % of this survey
% tmpyPosition = 0.5E5; % y position of labels, delta to signal height, in axis scale
% tmpyPositionTwo = 0.1E5; % optional, to shift neighouring labels up and dow
% % n
% % Au peaks
% nappAnnotateSurvey(tmpxRayEnergy-57-tmpxShift,tmpyPosition-tmpyPositionTwo,dataObjs(1),'Au5p3/2');
% nappAnnotateSurvey(tmpxRayEnergy-74-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'Au5p5/2');
% nappAnnotateSurvey(tmpxRayEnergy-84-tmpxShift,tmpyPosition,dataObjs(1),'Au4f7/2');
% nappAnnotateSurvey(tmpxRayEnergy-88-tmpxShift,tmpyPosition-tmpyPositionTwo,dataObjs(1),'Au4f5/2');
% nappAnnotateSurvey(tmpxRayEnergy-107-tmpxShift,tmpyPosition,dataObjs(1),'Au5s');
% nappAnnotateSurvey(tmpxRayEnergy-335-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'Au4d1/2');
% nappAnnotateSurvey(tmpxRayEnergy-353-tmpxShift,tmpyPosition,dataObjs(1),'Au4d3/2');
% nappAnnotateSurvey(tmpxRayEnergy-546-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'Au4p3/2');
% nappAnnotateSurvey(tmpxRayEnergy-643-tmpxShift,tmpyPosition,dataObjs(1),'Au4p1/2');
% nappAnnotateSurvey(tmpxRayEnergy-762-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'Au4s');
% nappAnnotateSurvey(tmpxRayEnergy-8-tmpxShift,tmpyPosition,dataObjs(1),'AuVB');
% % usual suspects
% nappAnnotateSurvey(tmpxRayEnergy-285-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'C1s');
% nappAnnotateSurvey(tmpxRayEnergy-534-tmpxShift,tmpyPosition,dataObjs(1),'O1s');
% nappAnnotateSurvey(tmpxRayEnergy-30-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'O2s');
% nappAnnotateSurvey(tmpxRayEnergy-405-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'N1s');
% nappAnnotateSurvey(tmpxRayEnergy-495-tmpxShift,tmpyPosition,dataObjs(1),'Sn3d');
% nappAnnotateSurvey(tmpxRayEnergy-691-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'F1s');
% nappAnnotateSurvey(tmpxRayEnergy-295-tmpxShift,tmpyPosition,dataObjs(1),'K2p');
% nappAnnotateSurvey(tmpxRayEnergy-380-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'K2s');
% nappAnnotateSurvey(tmpxRayEnergy-153-tmpxShift,tmpyPosition,dataObjs(1),'Si2s');
% nappAnnotateSurvey(tmpxRayEnergy-100-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'Si2p');
% nappAnnotateSurvey(tmpxRayEnergy-197-tmpxShift,tmpyPosition,dataObjs(1),'Cl2p');
% nappAnnotateSurvey(tmpxRayEnergy-286-tmpxShift,tmpyPosition-tmpyPositionTwo,dataObjs(1),'Sn3p');
% % Some Auger
% nappAnnotateSurvey(360-tmpxShift,tmpyPosition-tmpyPositionTwo,dataObjs(1),'N KLL');
% nappAnnotateSurvey(500-tmpxShift,tmpyPosition-tmpyPositionTwo,dataObjs(1),'O KLL');
% % tid up
% clearvars tmp*
%%
close all
tmpDataSelection = contains(FileList.name,'007_Survey');
FileList = nappGenerateSpectra(FileList,tmpDataSelection);
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsPerSecond',...
'mode','AllInOne','energyScale','kinetic');
% add text to Figure
dataObjs = findobj(gcf,'-property','YData');
tmpxShift = 6;
tmpxRayEnergy = 900;
tmpyPosition = 0.5E5;
tmpyPositionTwo = 0.1E5;
% Au peaks
nappAnnotateSurvey(tmpxRayEnergy-57-tmpxShift,tmpyPosition-tmpyPositionTwo,dataObjs(1),'Au5p3/2');
nappAnnotateSurvey(tmpxRayEnergy-74-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'Au5p5/2');
nappAnnotateSurvey(tmpxRayEnergy-84-tmpxShift,tmpyPosition,dataObjs(1),'Au4f7/2');
nappAnnotateSurvey(tmpxRayEnergy-88-tmpxShift,tmpyPosition-tmpyPositionTwo,dataObjs(1),'Au4f5/2');
nappAnnotateSurvey(tmpxRayEnergy-107-tmpxShift,tmpyPosition,dataObjs(1),'Au5s');
nappAnnotateSurvey(tmpxRayEnergy-335-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'Au4d1/2');
nappAnnotateSurvey(tmpxRayEnergy-353-tmpxShift,tmpyPosition,dataObjs(1),'Au4d3/2');
nappAnnotateSurvey(tmpxRayEnergy-546-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'Au4p3/2');
nappAnnotateSurvey(tmpxRayEnergy-643-tmpxShift,tmpyPosition,dataObjs(1),'Au4p1/2');
nappAnnotateSurvey(tmpxRayEnergy-762-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'Au4s');
nappAnnotateSurvey(tmpxRayEnergy-8-tmpxShift,tmpyPosition,dataObjs(1),'AuVB');
% usual suspects
nappAnnotateSurvey(tmpxRayEnergy-285-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'C1s');
nappAnnotateSurvey(tmpxRayEnergy-534-tmpxShift,tmpyPosition,dataObjs(1),'O1s');
nappAnnotateSurvey(tmpxRayEnergy-30-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'O2s');
nappAnnotateSurvey(tmpxRayEnergy-405-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'N1s');
nappAnnotateSurvey(tmpxRayEnergy-495-tmpxShift,tmpyPosition,dataObjs(1),'Sn3d');
nappAnnotateSurvey(tmpxRayEnergy-691-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'F1s');
nappAnnotateSurvey(tmpxRayEnergy-295-tmpxShift,tmpyPosition,dataObjs(1),'K2p');
nappAnnotateSurvey(tmpxRayEnergy-380-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'K2s');
nappAnnotateSurvey(tmpxRayEnergy-153-tmpxShift,tmpyPosition,dataObjs(1),'Si2s');
nappAnnotateSurvey(tmpxRayEnergy-100-tmpxShift,tmpyPosition+tmpyPositionTwo,dataObjs(1),'Si2p');
nappAnnotateSurvey(tmpxRayEnergy-197-tmpxShift,tmpyPosition,dataObjs(1),'Cl2p');
nappAnnotateSurvey(tmpxRayEnergy-286-tmpxShift,tmpyPosition-tmpyPositionTwo,dataObjs(1),'Sn3p');
% Some Auger
nappAnnotateSurvey(360-tmpxShift,tmpyPosition-tmpyPositionTwo,dataObjs(1),'N KLL');
nappAnnotateSurvey(500-tmpxShift,tmpyPosition-tmpyPositionTwo,dataObjs(1),'O KLL');
% tid up
clearvars tmp*
%% Process data: Align sequence iterations in images
%
% To shift and align the kinetic energy of each sequence iteration relative
% to each other, one can use
%
% # nappDetermineShiftXps: calculate the kinetic energy shift of each
% sequence iteration of an image relative to one sequence iteration (first
% is default)
% # nappCopyShift: optionally copy the kinetic energy shift to other data
% # nnappAlignImages: shift each sequence iterations of an image so that
% the peak maxima align.
%%
%
% % compile data
% tmpDataSelection = contains(FileList.name,'67_O1s') ...
% & (month(FileList.lastModifiedDatenum) == 8) ...
% & (year(FileList.lastModifiedDatenum) == 2021);
% % plot images
% nappPlot(FileList,tmpDataSelection,'tableVariable','image');
% % align images
% FileList = nappDetermineShiftXps(FileList,'tableSelection',tmpDataSelection,...
% 'showFigures','off','tableVariable','image');
% FileList = nappAlignImages(FileList,'tableSelection',tmpDataSelection,...
% 'tableVariable','image');
% % plot images
% nappPlot(FileList,tmpDataSelection,'tableVariable','image');
%%
close all
clc
% compile data
tmpDataSelection = contains(FileList.name,'67_O1s') ...
& (month(FileList.lastModifiedDatenum) == 8) ...
& (year(FileList.lastModifiedDatenum) == 2021);
% plot images
nappPlot(FileList,tmpDataSelection,'tableVariable','image');
% align images
FileList = nappDetermineShiftXps(FileList,'tableSelection',tmpDataSelection,...
'showFigures','off','tableVariable','image');
FileList = nappAlignImages(FileList,'tableSelection',tmpDataSelection,...
'tableVariable','image');
% plot images
nappPlot(FileList,tmpDataSelection,'tableVariable','image');
%% Process data: Generate XPS spectra
%
% All sequence iterations of an image are summed or the mean of all
% sequence iterations is calculated. The following command calculates the
% average of all sequence iterations from the filtered files in the
% FileList table. The spectrum based on the mean is saved in the column
% 'spectrum_countsPerSecond'.
%%
%
% FileList = nappGenerateSpectra(FileList,tmpDataSelection);
%
%% Process data: Generate NEXAFS spectra
%
% % All Auger spectra of an image are summed. Options include to sum the
% data with the energy interval of the aquisition, or to use the trapz
% function to normalise to 1 eV data spacing. The NEXAFS spectrua are
% always saved in the column 'spectrum_counts'.
%%
%
% FileList = nappGenerateSpectra(FileList,'tableSelection',tmpDataSelection,'mode','sum');
%
%%
close all
clc
tmpDataSelection = contains(FileList.name, '0063_20200824_042852_O_K_edge');
% Sum Auger-Meitner Spectrum
FileList = nappGenerateSpectra(FileList,'tableSelection',tmpDataSelection,'mode','sum');
% Plot
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_counts','energyScale','xRay','mode','OneEach');
%%
%
% FileList = nappGenerateSpectra(FileList,tmpDataSelection);
%
%% Process data: Align XPS spectra to background
%
% To align the spectra to a background the function nappBacktround can
% be used. Options include to compute the mean or a linear regression.
% Here, we calculate the mean between 367 and 370 eV.
%%
%
% FileList = nappBackground(FileList,367,370,'tableSelection',tmpDataSelection,'...
% energyScale','kinetic','mode','mean');
%
%%
close all
clc
tmpDataSelection = matches(FileList.sample,'Ice with N2')...
& ~contains(FileList.sample,'(bad data)')...
& contains(FileList.name,'O1s') & FileList.xRayEkinRange_eV(:,1) == 900 ...
& FileList.scientaPassEnergy_eV == 50 ...
& (month(FileList.lastModifiedDatenum) == 2) ...
& (year(FileList.lastModifiedDatenum) == 2022) ...
& (day(FileList.lastModifiedDatenum) >= 27);
FileList = nappGenerateSpectra(FileList,tmpDataSelection);
FileList = nappBackground(FileList,367,370,'tableSelection',tmpDataSelection,'energyScale','kinetic',...
'mode','mean');
% plot spectra
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsPerSecond',...
'mode','AllInOne','energyScale','kinetic');
%% Process data: Align NEXAFS spectra to background
%
% To align the spectra to a background the function nappBacktround can
% be used. Options include to compute the mean or a linear regression.
% Here, we calculate the mean between 522 and 525 eV xRay energy.
%%
%
% FileList = nappBackground(FileList,522,525,'tableSelection',tmpDataSelection,...
% 'tableVariable','spectrum_counts','energyScale','xRay','mode','mean');
%
%%
close all
clc
tmpDataSelection = contains(FileList.name, '0063_20200824_042852_O_K_edge');
% Sum Auger-Meitner Spectrum
FileList = nappGenerateSpectra(FileList,'tableSelection',tmpDataSelection,'mode','sum');
% Background
FileList = nappBackground(FileList,522,525,'tableSelection',tmpDataSelection,'tableVariable','spectrum_counts','energyScale','xRay',...
'mode','mean');
% Plot
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_counts','energyScale','xRay','mode','OneEach');
%% Process data: Gauss peak fit
%
% Gauss fitting can be used to determine area, width, and position of PE
% peaks. nappFitGaussXps de-convolutes the PE signal using 4 features. The
% fits can be constrained by
%
% * 'widthPosition' (Default): With of all peaks is identical. Position of
% peaks 2-3 is set relative to peak 1.
% * 'position': Position of peaks 2-3 is set relative to peak 1.
% * 'width': all peaks have same width
% * 'unconstrained': Each gauss peak is fitted independent.
% * 'unconstrainedAndWidthPosition': One unconstrained peak #3 (for gas phase
% feature) and 4 peaks constrained in width and/or position
%
%
% The function needs fit parameters as input, such as min and max peak
% area, width, and position; initial values for fitting; and the spectrum
% range.
%
% * spectrum range: define the region of the PE spectrum used for fitting
% (plus and minus from peak 1 position).
% % position of peak 2-4 are relative to peak 1, that of peak 1 absolute
% (either in binding or kinetic energy scale)
% * If you are only interested in less than 4 peaks, choose small dummy
% constrains for those peaks you don't want to fit.
%
%%
% % initial fit parameters
% tmpFitParameters.peakArea = [1E4 5E3 0.1 0.1];
% tmpFitParameters.peakWidth = [2.0 2.0 0.1 0.1];
% tmpFitParameters.peakPos = [363 -1 -2 -3];
% % lower bonds
% tmpFitParameters.peakAreaLowerBond = [1E3 5E3 0.1 0.1];
% tmpFitParameters.peakWidthLowerBond = [2.0 2.0 0.1 0.1];
% tmpFitParameters.peakPosLowerBond = 361;
% % upper bonds
% tmpFitParameters.peakAreaUpperBond = [1E6 10E4 0.1 0.1];
% tmpFitParameters.peakWidthUpperBond = [3.0 2.0 0.1 0.1];
% tmpFitParameters.peakPosUpperBond = 365;
% % spectrum range
% tmpFitParameters.backgroundRange = [5 5];
%
% % „position“ mode
% tmpFitParameters.peakArea = [abs#1 abs#2 abs#3 abs#4];
% tmpFitParameters.peakWidth = [abs#1 abs#2 abs#3 abs#4];
% tmpFitParameters.peakPos = [abs#1 rel#2 rel#3 rel#4];
%
% tmpFitParameters.peakAreaUpperBond = [#1 #2 #3 #4];
% tmpFitParameters.peakWidthUpperBond = [#1 #2 #3 #4];
% tmpFitParameters.peakPosUpperBond = #1;
% tmpFitParameters.peakAreaLowerBond = [#1 #2 #3 #4];
% tmpFitParameters.peakWidthLowerBond = [#1 #2 #3 #4];
% tmpFitParameters.peakPosLowerBond = #1;
%
%
% % „unconstrained“ mode
% tmpFitParameters.peakArea = [abs#1 abs#2 abs#3 abs#4];
% tmpFitParameters.peakWidth = [abs#1 abs#2 abs#3 abs#4];
% tmpFitParameters.peakPos = [abs#1 abs#2 abs#3 abs#4];
%
% tmpFitParameters.peakAreaUpperBond = [#1 #2 #3 #4];
% tmpFitParameters.peakWidthUpperBond = [#1 #2 #3 #4];
% tmpFitParameters.peakPosUpperBond = [#1 #2 #3 #4];
% tmpFitParameters.peakAreaLowerBond = [#1 #2 #3 #4];
% tmpFitParameters.peakWidthLowerBond = [#1 #2 #3 #4];
% tmpFitParameters.peakPosLowerBond = [#1 #2 #3 #4];
%
%
% % „ widthPosition“ mode
% tmpFitParameters.peakArea = [abs#1 abs#2 abs#3 abs#4];
% tmpFitParameters.peakWidth = [abs#1-#4];
% tmpFitParameters.peakPos = [abs#1 rel#2 rel#3 rel#4];
%
% tmpFitParameters.peakAreaUpperBond = [#1 #2 #3 #4];
% tmpFitParameters.peakWidthUpperBond = #1-#4;
% tmpFitParameters.peakPosUpperBond = #1;
% tmpFitParameters.peakAreaLowerBond = [#1 #2 #3 #4];
% tmpFitParameters.peakWidthLowerBond = #1-#4;
% tmpFitParameters.peakPosLowerBond = #1;
%
% % „ width“ mode
% tmpFitParameters.peakArea = [abs#1 abs#2 abs#3 abs#4];
% tmpFitParameters.peakWidth = [abs#1-#4];
% tmpFitParameters.peakPos = [abs#1 abs#2 abs#3 abs#4];
%
% tmpFitParameters.peakAreaUpperBond = [#1 #2 #3 #4];
% tmpFitParameters.peakWidthUpperBond = #1-#4;
% tmpFitParameters.peakPosUpperBond = [#1 #2 #3 #4];
% tmpFitParameters.peakAreaLowerBond = [#1 #2 #3 #4];
% tmpFitParameters.peakWidthLowerBond = #1-#4;
% tmpFitParameters.peakPosLowerBond = [#1 #2 #3 #4];
%
%
% % „ unconstrainedAndWidthPosition" mode (novel: rel distance fit parameter)
% tmpFitParameters.peakArea = [abs#1 abs#2 abs#3 abs#4 abs#5];
% tmpFitParameters.peakWidth = [abs#1,2,4,5 abs#3];
% tmpFitParameters.peakPos = [rel#1 abs#2 abs#3 abs#4 abs#5];
%
% tmpFitParameters.peakAreaUpperBond = [#1 #2 #3 #4 #5];
% tmpFitParameters.peakWidthUpperBond = [#1,2,4,5 #3];
% tmpFitParameters.peakPosUpperBond = [#1 #2 #3 #4 #5];
% tmpFitParameters.peakAreaLowerBond = [#1 #2 #3 #4];
% tmpFitParameters.peakWidthLowerBond = [#1,2,4,5 #3];
% tmpFitParameters.peakPosLowerBond = [#1 #2 #3 #4];
%
%
% FileList = nappFitGaussXps(FileList,tmpDataSelection,tmpFitParameters,'tableSelection',tmpDataSelection,...
% 'energyScale','kinetic','mode','position','showFigures','on');
%%
% % The fit results are written to the data table. Peak position is only
% written to the table if in binding energy mode. Further, results are
% plotted to the command line and fits are shown in graphs:
%%
close all
tmpDataSelection = matches(FileList.sample,'Ice with N2')...
& ~contains(FileList.sample,'(bad data)')...
& contains(FileList.name,'O1s') & FileList.xRayEkinRange_eV(:,1) == 900 ...
& FileList.scientaPassEnergy_eV == 50 ...
& (month(FileList.lastModifiedDatenum) == 2) ...
& (year(FileList.lastModifiedDatenum) == 2022) ...
& (day(FileList.lastModifiedDatenum) >= 27);
FileList = nappBackground(FileList,367,370,'tableSelection',tmpDataSelection,'energyScale','kinetic',...
'mode','mean');
tmpFitParameters.peakArea = [1E4 5E3 0.1 0.1];
tmpFitParameters.peakWidth = [2.0 2.0 0.1 0.1];
tmpFitParameters.peakPos = [363 -1 -2 -3]; % position of peak 2-4 are relative to peak 1
tmpFitParameters.peakAreaLowerBond = [1E3 5E3 0.1 0.1];
tmpFitParameters.peakWidthLowerBond = [2.0 2.0 0.1 0.1];
tmpFitParameters.peakPosLowerBond = 361;
tmpFitParameters.peakAreaUpperBond = [1E6 10E4 0.1 0.1];
tmpFitParameters.peakWidthUpperBond = [3.0 2.0 0.1 0.1];
tmpFitParameters.peakPosUpperBond = 365;
tmpFitParameters.backgroundRange = [5 5];
FileList = nappFitGaussXps(FileList,tmpDataSelection,tmpFitParameters,'tableSelection',tmpDataSelection,...
'energyScale','kinetic','mode','position','showFigures','on');
%% Process data: Norm spectra
%
% To normalise spectra, nappScaleToArea can be used. A typical example is
% to normalise C1s to the O1s peak area to compensate for changes in the
% working distance. The function uses the peakArea table column, thus
% nappFitGaussXps needs to run first. Results are written to the table
% variable spectrum_countsNorm (as the unit is no longer countsPerSecond).
% To normalise C1s to the O1s peak area, select C1s spectra using a logical
% (tmpDataSelection), and choose C1s for regionOld and O1s for regionNew:
%
% * regionOld: C1s (default) or O1s - region that will be normalised
% * regionNew: O1s (default) or C1s - peak area that will be used to normalise
%
%%
%
% FileList = nappScale(FileList,tmpDataSelection,'regionOld','C1s','regionNew','O1s');
% nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsNorm');
%
%%
close all
clc
tmpDataSelection = matches(FileList.sample,'Ice with N2')...
& ~contains(FileList.sample,'(bad data)')...
& contains(FileList.name,'O1s') & FileList.xRayEkinRange_eV(:,1) == 900 ...
& FileList.scientaPassEnergy_eV == 50 ...
& (month(FileList.lastModifiedDatenum) == 2) ...
& (year(FileList.lastModifiedDatenum) == 2022) ...
& (day(FileList.lastModifiedDatenum) >= 27);
% plot spectra
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsPerSecond',...
'mode','AllInOne','energyScale','kinetic');
% scale to area
FileList = nappScale(FileList,tmpDataSelection,'regionOld','O1s','regionNew','O1s');
FileList = nappBackground(FileList,367,370,'tableSelection',tmpDataSelection,'energyScale','kinetic',...
'mode','mean','tableVariable','spectrum_countsNorm');
% plot spectra
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsNorm',...
'mode','AllInOne','energyScale','kinetic');
tmpDataSelection = matches(FileList.sample,'Ice with N2')...
& ~contains(FileList.sample,'(bad data)')...
& contains(FileList.name,'C1s') & FileList.xRayEkinRange_eV(:,1) == 900 ...
& FileList.scientaPassEnergy_eV == 50 ...
& (month(FileList.lastModifiedDatenum) == 2) ...
& (year(FileList.lastModifiedDatenum) == 2022) ...
& (day(FileList.lastModifiedDatenum) >= 27);
% Generate spectra
FileList = nappGenerateSpectra(FileList,tmpDataSelection);
% plot spectra
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsPerSecond',...
'mode','AllInOne','energyScale','kinetic');
% scale to area
FileList = nappScale(FileList,tmpDataSelection,'regionOld','C1s','regionNew','O1s');
FileList = nappBackground(FileList,615,617,'tableSelection',tmpDataSelection,'energyScale','kinetic',...
'mode','mean','tableVariable','spectrum_countsNorm');
% plot spectra
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsNorm');
%% Process data: Binding energy scale
%
% To calculate the binding energy, you need to
%
% # nappDetermineShiftXps: calculate the kinetic energy shift relative to a reference value
% # nappCopyShift: optionally copy the kinetic energy shift to other data
% # nappBindingEnergyXps: calculate the binding energy based on the kinetic
% energy shift either determined relative to a reference or copied to the
% individual data.
%
% The following example shows how the kinetic energy shift is calculated
% based on selected O1s spectra relative to 535 eV, copied to the C1s data
% with the same file number, and finally the binding energy of the C1s data is
% calculated (based on the observed shift of the O1s of the same sequence
% run) and plotted
%%
%
% close all
% % generate spectra for C1s and O1s
% tmpDataSelection = matches(FileList.sample,'Ice with N2')...
% & ~contains(FileList.sample,'(bad data)')...
% & (contains(FileList.name,'O1s') | contains(FileList.name,'C1s'))...
% & FileList.xRayEkinRange_eV(:,1) == 900 ...
% & FileList.scientaPassEnergy_eV == 50 ...
% & (month(FileList.lastModifiedDatenum) == 2) ...
% & (year(FileList.lastModifiedDatenum) == 2022) ...
% & (day(FileList.lastModifiedDatenum) >= 27);
% FileList = nappGenerateSpectra(FileList,tmpDataSelection);
% FileList = nappBackground(FileList,367,370,'tableSelection',tmpDataSelection,'energyScale','kinetic',...
% 'mode','mean');
% % determine shift of O1s
% tmpDataSelection = matches(FileList.sample,'Ice with N2')...
% & ~contains(FileList.sample,'(bad data)')...
% & contains(FileList.name,'O1s')...
% & FileList.xRayEkinRange_eV(:,1) == 900 ...
% & FileList.scientaPassEnergy_eV == 50 ...
% & (month(FileList.lastModifiedDatenum) == 2) ...
% & (year(FileList.lastModifiedDatenum) == 2022) ...
% & (day(FileList.lastModifiedDatenum) >= 27);
% FileList = nappDetermineShiftXps(FileList,'tableSelection',tmpDataSelection,...
% 'showFigures','off','tableVariable','spectrum_countsPerSecond','binEnReference',533);
% % copy shift from O1s to C1s
% FileList = nappCopyShift(FileList,tmpDataSelection,'energyScale','binding');
% % calculate binding energy of these C1s
% tmpDataSelection = matches(FileList.sample,'Ice with N2')...
% & ~contains(FileList.sample,'(bad data)')...
% & contains(FileList.name,'C1s') & FileList.xRayEkinRange_eV(:,1) == 900 ...
% & FileList.scientaPassEnergy_eV == 50 ...
% & (month(FileList.lastModifiedDatenum) == 2) ...
% & (year(FileList.lastModifiedDatenum) == 2022) ...
% & (day(FileList.lastModifiedDatenum) >= 27);
% FileList = nappBindingEnergyXps(FileList,'tableSelection',tmpDataSelection);
% % plot C1s spectra
% nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsPerSecond',...
% 'mode','AllInOne','energyScale','kinetic');
% nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsPerSecond',...
% 'mode','AllInOne','energyScale','binding');
%%
%
close all
tmpDataSelection = matches(FileList.sample,'Ice with N2')...
& ~contains(FileList.sample,'(bad data)')...
& (contains(FileList.name,'O1s') | contains(FileList.name,'C1s'))...
& FileList.xRayEkinRange_eV(:,1) == 900 ...
& FileList.scientaPassEnergy_eV == 50 ...
& (month(FileList.lastModifiedDatenum) == 2) ...
& (year(FileList.lastModifiedDatenum) == 2022) ...
& (day(FileList.lastModifiedDatenum) >= 27);
FileList = nappGenerateSpectra(FileList,tmpDataSelection);
FileList = nappBackground(FileList,367,370,'tableSelection',tmpDataSelection,'energyScale','kinetic',...
'mode','mean');
% determine shift of O1s
tmpDataSelection = matches(FileList.sample,'Ice with N2')...
& ~contains(FileList.sample,'(bad data)')...
& contains(FileList.name,'O1s')...
& FileList.xRayEkinRange_eV(:,1) == 900 ...
& FileList.scientaPassEnergy_eV == 50 ...
& (month(FileList.lastModifiedDatenum) == 2) ...
& (year(FileList.lastModifiedDatenum) == 2022) ...
& (day(FileList.lastModifiedDatenum) >= 27);
FileList = nappDetermineShiftXps(FileList,'tableSelection',tmpDataSelection,...
'showFigures','off','tableVariable','spectrum_countsPerSecond','binEnReference',533);
% copy shift from O1s to C1s
FileList = nappCopyShift(FileList,tmpDataSelection,'energyScale','binding');
% calculate binding energy of these C1s
tmpDataSelection = matches(FileList.sample,'Ice with N2')...
& ~contains(FileList.sample,'(bad data)')...
& contains(FileList.name,'C1s') & FileList.xRayEkinRange_eV(:,1) == 900 ...
& FileList.scientaPassEnergy_eV == 50 ...
& (month(FileList.lastModifiedDatenum) == 2) ...
& (year(FileList.lastModifiedDatenum) == 2022) ...
& (day(FileList.lastModifiedDatenum) >= 27);
FileList = nappBindingEnergyXps(FileList,'tableSelection',tmpDataSelection);
% plot C1s spectra
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsPerSecond',...
'mode','AllInOne','energyScale','kinetic');
nappPlot(FileList,tmpDataSelection,'tableVariable','spectrum_countsPerSecond',...
'mode','AllInOne','energyScale','binding');
%% Process data: Combine spectra
%
% To get better statistics (signal-to-noise), repeated measurements can be
% added or averaged into one spectrum. The results are written into a
% matrix with energy in column 1, counts in column2, and standard deviation
% in column 3 (only for mean). So, the nappFunctions can no longer be used
% for this data format.
%%
%
% tmpDataSelection = contains(FileList.name,'C1s')...
% & contains(FileList.sample,'MgO ice AA')...
% & ~endsWith(FileList.sample,'(bad data)')...
% & FileList.sampleTemp_dC >= -26 & FileList.sampleTemp_dC <= -24;
% MgO_C1s_Warm = nappCombineSpectra(FileList,'tableRow',1,...
% 'tableSelection',tmpDataSelection,'tableVariable',...
% 'spectrum_countsPerSecond','EnergyScale','binding','mode','average');
%%
close all
tmpDataSelection = contains(FileList.name,'C1s')...
& contains(FileList.sample,'MgO ice AA')...
& ~endsWith(FileList.sample,'(bad data)')...
& FileList.sampleTemp_dC >= -26 & FileList.sampleTemp_dC <= -24;
FileList = nappGenerateSpectra(FileList,tmpDataSelection);
MgO_C1s_Warm = nappCombineSpectra(FileList,'tableRow',1,...
'tableSelection',tmpDataSelection,'tableVariable',...
'spectrum_countsPerSecond','EnergyScale','kinetic','mode','average');
figure
% axes('Parent',gcf,'XDir','reverse')
hold(gca,'on');
plot(MgO_C1s_Warm(:,1),MgO_C1s_Warm(:,2),'--','linewidth',2)
title('acetic acid adsorption')
legend({'ice on MgO, -25°C'},...
'location','SouthOutside','Orientation','horizontal')
xlim([704,714]);
xlabel('kinetic energy [eV]')
ylabel('PE [counts per second]')
%%
function [myColorMap, PsiFarbe] = initializeMatlab
%initializeMatlab Sets NappIce specific settings
% Adds Napp files 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);
% The fitting routines writes quite a lot of feedback and warnings. I shut them off.
warning('off','all')
warning off backtrace
warning off verbose
% Functions and helper files path:
if ismac
% add Napp files to path
addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/Add-Ons');
addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/nappIce');
elseif ispc
% add Napp files to path
addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/Add-Ons');
addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/nappIce');
elseif isunix
% add Napp files to path
addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/Add-Ons');
addpath('/Users/bartels-rausch/SwitchDrive/PSI_Matlab/nappIce');
end
% Color maps
myColorMap.red = colormap(autumn(7));
myColorMap.blue = colormap(winter(7));
% define PSI cooperate identity colours
PsiFarbe.hellgrau = [226 226 226]/255;
PsiFarbe.mittelgrau = [184 184 184]/255;
PsiFarbe.dunkelgrau = [78 78 77]/255;
PsiFarbe.blaugrau = [236 236 243]/255; % This is actually not a PSI colour
PsiFarbe.gelb = [239 200 37]/255;
PsiFarbe.hellorange = [227 164 31]/255;
PsiFarbe.dunkelorange = [207 92 22]/255;
PsiFarbe.hellrot = [164 36 23]/255;
PsiFarbe.dunkelbraun = [114 85 65]/255;
PsiFarbe.hellbraun = [127 119 47]/255;
PsiFarbe.mittelgruen = [135 150 59]/255;
PsiFarbe.hellgruen = [195 214 47]/255;
PsiFarbe.dunkelgruen = [72 130 33]/255;
PsiFarbe.dunkelrot = [104 47 86]/255;
PsiFarbe.dunkelblau = [37 65 108]/255;
PsiFarbe.mittelgruenblau = [61 164 168]/255;
PsiFarbe.hellblau = [58 162 190]/255;
PsiFarbe.mittelblau = [50 118 158]/255;
end