226 lines
10 KiB
Matlab
226 lines
10 KiB
Matlab
function DataTable = nappCopyShift(DataTable,varargin)
|
|
%NAPPCOPYSHIFT Copy energy shift from one XPS region to spectra of the same sequence but other regions.
|
|
% This function transfers energy shift calibration data (kinetic or binding
|
|
% energy) from a reference region to spectra of the same sequence iteration in a different
|
|
% region. It matches spectra based on filename and acquisition timestamp,
|
|
% enabling consistent energy axis calibration across XPS
|
|
% measurements of the same sequence (e.g., copying O1s shift to C1s spectra acquired simultaneously).
|
|
%
|
|
% This approach ensures that energy calibrations determined from a
|
|
% reference region (typically C1s or O1s) are consistently applied to
|
|
% other regions in the same sequence. Works with both spectral data in
|
|
% binding and in kinetic energy scale and with images - that is can be
|
|
% used to align all sweeps in one image. Multiple destination rows can
|
|
% receive the same shift value if acquired simultaneously (one-to-many
|
|
% copying).
|
|
%
|
|
% SYNTAX
|
|
% ------
|
|
% DataTable = NAPPCOPYSHIFT(DataTable)
|
|
%
|
|
% DataTable = NAPPCOPYSHIFT(DataTable, tableSelection, 'Name', Value)
|
|
%
|
|
% EXAMPLES
|
|
% --------
|
|
% % Copy O1s kinetic energy shift to C1s spectra
|
|
% DataTable = nappCopyShift(DataTable, ...
|
|
% 'regionOld', 'O1s', ...
|
|
% 'regionNew', 'C1s', ...
|
|
% 'energyScale', 'kinetic');
|
|
%
|
|
% % Copy binding energy shift from N1s to Cl2p on selected rows
|
|
% selection = contains(DataTable.name, 'polymer_sample');
|
|
% DataTable = nappCopyShift(DataTable, selection, ...
|
|
% 'regionOld', 'N1s', ...
|
|
% 'regionNew', 'Cl2p', ...
|
|
% 'energyScale', 'binding');
|
|
%
|
|
% % Copy C1s calibration (binding energy) to all matching O1s spectra
|
|
% DataTable = nappCopyShift(DataTable, ...
|
|
% 'regionOld', 'C1s', ...
|
|
% 'regionNew', 'O1s');
|
|
%
|
|
% INPUT ARGUMENTS
|
|
% ---------------
|
|
% DataTable table
|
|
% Data table containing XPS spectra with energy shift calibration data
|
|
% and time stamps. Ideally the napp standard format, but must at least contain:
|
|
% - name field: spectrum identifiers with region designation (e.g.,
|
|
% 'sample_C1s', 'sample_O1s')
|
|
% - lastModifiedDatenum field: acquisition timestamps (MATLAB datenum format)
|
|
% - kineticEnergyShift or bindingEnergyShift field: calibration shift values
|
|
% (created by nappDetermineShiftXps)
|
|
%
|
|
% NAME-VALUE PAIR ARGUMENTS (optional)
|
|
% ------------------------------------
|
|
% 'tableSelection' logical array (default: all rows)
|
|
% Logical index to filter which rows in DataTable contain the source
|
|
% shift data (regionOld spectra). Only spectra in this selection will
|
|
% be processed as source regions. Their shifts will be copied to matching
|
|
% spectra in regionNew (which may or may not be in tableSelection).
|
|
% Example: contains(DataTable.name, 'C1s') to use only C1s as source
|
|
%
|
|
% 'regionOld' char vector (default: 'O1s')
|
|
% Source region containing the energy shift calibration data.
|
|
% Must be one of:
|
|
% - 'O1s'
|
|
% - 'C1s'
|
|
% - 'N1s'
|
|
%
|
|
% 'regionNew' char vector (default: 'C1s')
|
|
% Destination region to which shift data will be copied.
|
|
% Must be one of:
|
|
% - 'O1s'
|
|
% - 'C1s'
|
|
% - 'N1s'
|
|
% - 'Cl2p'
|
|
%
|
|
% 'energyScale' char vector (default: 'kinetic')
|
|
% Energy scale type for shift calibration:
|
|
% - 'kinetic': copies kineticEnergyShift column (used for image analysis)
|
|
% - 'binding': copies bindingEnergyShift column (used for spectral analysis)
|
|
%
|
|
% OUTPUT ARGUMENTS
|
|
% ----------------
|
|
% DataTable table
|
|
% Updated data table with energy shift values copied to destination region
|
|
% spectra. The appropriate column is populated:
|
|
% - kineticEnergyShift (if energyScale = 'kinetic')
|
|
% - bindingEnergyShift (if energyScale = 'binding')
|
|
%
|
|
% Shift values are matched and copied for all spectra in the destination
|
|
% region (regionNew) that share the same acquisition timestamp as spectra
|
|
% in the source region (regionOld, filtered by tableSelection).
|
|
%
|
|
% MATCHING ALGORITHM
|
|
% ------------------
|
|
% The function matches source spectra (regionOld) to destination spectra
|
|
% (regionNew) using:
|
|
% 1. Filename: region name is replaced (O1s → C1s, etc.)
|
|
% 2. Acquisition timestamp: year, month, day, hour, and minute must all match
|
|
%
|
|
% This ensures that shift calibrations from simultaneously acquired reference
|
|
% regions are correctly applied to their complementary spectra. An error is
|
|
% displayed if a matching spectrum cannot be found.
|
|
%
|
|
% NOTES
|
|
% -----
|
|
% - PREREQUISITE: Run nappDetermineShiftXps on the source region (regionOld)
|
|
% BEFORE running this function. This populates the shift column in DataTable.
|
|
% - Timestamp matching is strict: year, month, day, hour, and minute must all
|
|
% match exactly. Second-level precision is not used.
|
|
% - If regionOld and regionNew are the same, no copy operation is performed.
|
|
% - Timestamps with mismatches indicate possible data organization issues and
|
|
% trigger a diagnostic message.
|
|
% - The function operates on selected rows only when tableSelection is provided.
|
|
% Rows outside the selection are not processed as source regions.
|
|
%
|
|
% WORKFLOW EXAMPLE
|
|
% ----------------
|
|
% % Typical usage sequence for multi-region XPS dataset:
|
|
% % 1. Determine shift for reference region (C1s)
|
|
% DataTable = nappDetermineShiftXps(DataTable, ...
|
|
% contains(DataTable.name, 'C1s'), ...
|
|
% 'energyScale', 'binding');
|
|
%
|
|
% % 2. Copy C1s shift to complementary regions
|
|
% DataTable = nappCopyShift(DataTable, ...
|
|
% contains(DataTable.name, 'C1s'), ...
|
|
% 'regionOld', 'C1s', ...
|
|
% 'regionNew', 'O1s', ...
|
|
% 'energyScale', 'binding');
|
|
%
|
|
% DataTable = nappCopyShift(DataTable, ...
|
|
% contains(DataTable.name, 'C1s'), ...
|
|
% 'regionOld', 'C1s', ...
|
|
% 'regionNew', 'N1s', ...
|
|
% 'energyScale', 'binding');
|
|
%
|
|
% SEE ALSO
|
|
% --------
|
|
% nappDetermineShiftXps, nappBindingEnergyXps, nappAlignImages,
|
|
% nappFitGaussXps, datenum
|
|
|
|
% Define conditions and defaults of input
|
|
% Old region must be also selected in tableSelection! it is kind like
|
|
% double.
|
|
defaultRegionOld = 'O1s';
|
|
expectedRegionOld = {'O1s','C1s','N1s'};
|
|
defaultRegionNew = 'C1s';
|
|
expectedRegionNew = {'O1s','C1s','N1s','Cl2p'};
|
|
defaultTableSelection = true(size(DataTable,1));
|
|
defaultEnergyScale = 'kinetic';
|
|
expectedEnergyScale = {'kinetic','binding'};
|
|
|
|
|
|
% Parse input
|
|
p = inputParser;
|
|
addRequired(p,'DataTable',@istable);
|
|
addOptional(p,'tableSelection',defaultTableSelection,@islogical);
|
|
addParameter(p,'regionOld',defaultRegionOld,...
|
|
@(x) any(validatestring(x,expectedRegionOld)));
|
|
addParameter(p,'regionNew',defaultRegionNew,...
|
|
@(x) any(validatestring(x,expectedRegionNew)));
|
|
addParameter(p,'energyScale',defaultEnergyScale,...
|
|
@(x) any(validatestring(x,expectedEnergyScale)));
|
|
parse(p,DataTable,varargin{:});
|
|
|
|
|
|
|
|
% The function operates as follows:
|
|
% 1. For each source spectrum/image (regionOld) in tableSelection:
|
|
% - Extract the energy shift value (kinetic or binding scale)
|
|
% - Extract the acquisition timestamp
|
|
% 2. Generate search criteria by replacing the region name in the source
|
|
% filename (e.g., "sample_O1s" becomes "sample_C1s")
|
|
% 3. Search entire DataTable for destination spectra/images (regionNew) that:
|
|
% - Have the transformed filename
|
|
% - Match the acquisition timestamp exactly (year, month, day, hour, minute)
|
|
% 4. Copy the source energy shift value to all matching destination rows
|
|
|
|
if contains(p.Results.energyScale,'kinetic')
|
|
% repeat this for all columns in input.
|
|
for ii = 1:size(p.Results.DataTable(p.Results.tableSelection,:),1)
|
|
% get name and date
|
|
tmpName = replace(p.Results.DataTable(p.Results.tableSelection,:).name{ii}, ...
|
|
p.Results.regionOld,p.Results.regionNew);
|
|
tmpDate = p.Results.DataTable(p.Results.tableSelection,:).lastModifiedDatenum(ii);
|
|
% select spectra
|
|
tmpDataSelection = contains(p.Results.DataTable.name,tmpName)...
|
|
& ismember(year(p.Results.DataTable.lastModifiedDatenum),year(tmpDate))...
|
|
& ismember(month(p.Results.DataTable.lastModifiedDatenum),month(tmpDate))...
|
|
& ismember(day(p.Results.DataTable.lastModifiedDatenum),day(tmpDate))...
|
|
& ismember(hour(p.Results.DataTable.lastModifiedDatenum),hour(tmpDate))...
|
|
& ismember(minute(p.Results.DataTable.lastModifiedDatenum),minute(tmpDate));
|
|
|
|
if ~any(tmpDataSelection) == 1
|
|
disp('There is something wrong with the data time info')
|
|
disp(tmpName)
|
|
end
|
|
% replace the region in the name and copy the data
|
|
DataTable.kineticEnergyShift(tmpDataSelection,:) = p.Results.DataTable(p.Results.tableSelection,:).kineticEnergyShift(ii);
|
|
end
|
|
elseif contains(p.Results.energyScale,'binding')
|
|
% repeat this for all columns in input.
|
|
for ii = 1:size(p.Results.DataTable(p.Results.tableSelection,:),1)
|
|
% get name and date
|
|
tmpName = replace(p.Results.DataTable(p.Results.tableSelection,:).name{ii}, ...
|
|
p.Results.regionOld,p.Results.regionNew);
|
|
tmpDate = p.Results.DataTable(p.Results.tableSelection,:).lastModifiedDatenum(ii);
|
|
% select spectra
|
|
tmpDataSelection = contains(p.Results.DataTable.name,tmpName)...
|
|
& ismember(year(p.Results.DataTable.lastModifiedDatenum),year(tmpDate))...
|
|
& ismember(month(p.Results.DataTable.lastModifiedDatenum),month(tmpDate))...
|
|
& ismember(day(p.Results.DataTable.lastModifiedDatenum),day(tmpDate))...
|
|
& ismember(hour(p.Results.DataTable.lastModifiedDatenum),hour(tmpDate))...
|
|
& ismember(minute(p.Results.DataTable.lastModifiedDatenum),minute(tmpDate));
|
|
if ~any(tmpDataSelection) == 1
|
|
disp('There is something wrong with the data time info')
|
|
disp(tmpName)
|
|
end
|
|
% replace the region in the name and copy the data
|
|
DataTable.bindingEnergyShift(tmpDataSelection,:) = p.Results.DataTable(p.Results.tableSelection,:).bindingEnergyShift(ii);
|
|
end
|
|
end
|
|
|
|
end |