beamtime/nappFileList.m - Fix h5 LensMode: translate numeric codes to descriptive text (e.g. 1 -> T_HiPPHAXPES) to match what .ibw files already store, applied across all three h5read fallback branches, not just the oldest-format one beamtime/nappGenerateSpectra.m - Bug fixes beamtime/nappPlot.m - Bug fixes import/importData.m (new) - Ground script for one beamtime: import (nappFileList, nappGenerateSpectra), sample/spot and photon-energy assignment per row range, campaign metadata (CustomProperties) and column descriptions/units set inline, tidy-up, and export to .csv/.mat/.h5 (via nappExportH5). Leaves FileList in the workspace for PublishReport.m and callOpenbisSync.m to run against afterward. import/nappExportH5.m (new) - Export FileList + campaign metadata + raw source files to a self-contained HDF5 archive - Low-level HDF5 API (H5F/H5G/H5D/H5A/H5T/H5S/H5P) to fix H5FD_truncate/"too many open files" errors from the top-level h5create/h5write functions each reopening the file internally - Explicit rowIndex attribute per row group, since HDF5 group listing order isn't guaranteed to match table row order openBIS/ (new) - nappSyncToOpenbis.py, callOpenbisSync.m, testpybis.m, README.md - openBIS sync pipeline: create-or-update per row matched by $name, correct lowercase property codes, timestamp formatting, parent linking, raw file upload, plot/photo/video thumbnail embedding, config/engine split for maintainability -- see README.md for full details
161 lines
11 KiB
Matlab
161 lines
11 KiB
Matlab
%% BeamTime2016PhoenixIceNapp
|
|
|
|
% add ../Functions to path (works on Windows and macOS)
|
|
funcDir = fullfile(fileparts(mfilename('fullpath')), '..', 'Functions');
|
|
funcDir = char(java.io.File(funcDir).getCanonicalPath); % resolves .. and symlinks cross-platform
|
|
if isfolder(funcDir)
|
|
addpath(funcDir);
|
|
else
|
|
warning('Functions directory not found: %s', funcDir);
|
|
end
|
|
|
|
|
|
clearvars
|
|
close all
|
|
clc
|
|
%% Import and Generate Spectra
|
|
% @DEP_IN: BeamTime2016PhoenixIceNapp
|
|
FileList = nappFileList('BeamTime2016PhoenixIceNapp','mode','local');
|
|
FileList = nappGenerateSpectra(FileList);
|
|
|
|
|
|
%% Add photon energy and sample type
|
|
|
|
|
|
idxSpotChange1 = find(matches(FileList.name,"PHOENIX0207207.ibw"));
|
|
idxSpotChange2 = find(matches(FileList.name,"PHOENIX0225225.ibw"));
|
|
idxSpotChange3 = find(matches(FileList.name,"PHOENIX0229229.ibw"));
|
|
idxSpotChange4 = find(matches(FileList.name,"PHOENIX0235235.ibw"));
|
|
idxSpotChange5 = find(matches(FileList.name,"PHOENIX0235235.ibw"));
|
|
idxSpotChange6 = find(matches(FileList.name,"PHOENIX0238238.ibw"));
|
|
|
|
isIBW = endsWith(FileList.name,'.ibw');
|
|
k = find(isIBW);
|
|
for ii = 1:length(k)
|
|
FileList(k(ii),:).xRayEkin_eV{:} = 2200;
|
|
end
|
|
|
|
for ii = 1:idxSpotChange1
|
|
FileList(ii,:).sample{:} = 'NaCl; H2O gas, Spot#1 (0/0/6)';
|
|
end
|
|
for ii = idxSpotChange1+1:idxSpotChange2
|
|
FileList(ii,:).sample{:} = 'NaCl; H2O gas, Spot#2 (0/0.6/6)';
|
|
end
|
|
for ii = idxSpotChange2+1:idxSpotChange3
|
|
FileList(ii,:).sample{:} = 'NaCl; H2O gas, Spot#3 (-1/0.6/6.6)';
|
|
end
|
|
for ii = idxSpotChange3+1:idxSpotChange4
|
|
FileList(ii,:).sample{:} = 'NaCl; H2O gas, Spot#4 (0/0.6/6.1)';
|
|
end
|
|
for ii = idxSpotChange4+1:idxSpotChange5
|
|
FileList(ii,:).sample{:} = 'NaCl; H2O gas, Spot#5 (0.5/1.7/5.8)';
|
|
end
|
|
for ii = idxSpotChange5+1:idxSpotChange6
|
|
FileList(ii,:).sample{:} = 'NaCl; H2O gas, Spot#6 (0/0.9/6)';
|
|
end
|
|
for ii = idxSpotChange6+1:308
|
|
FileList(ii,:).sample{:} = 'NaCl; H2O gas, Spot#6 (-1/0.4/6.4)';
|
|
end
|
|
%% Add meta-data (keywords)
|
|
propNames = ["campaignName","campaignLocation","campaignInstrument","projectName","contact","sourceDirectory","startDate","endDate","dataLevel","publicationDoi", "funding", "contactORCID", "publicationDataDoi", "rawDataDoi", "team"];
|
|
try
|
|
FileList = addprop(FileList, propNames, repmat("table",1,numel(propNames)));
|
|
catch
|
|
% properties already exist from a previous run -- fine, just update values below
|
|
end
|
|
FileList.Properties.CustomProperties.campaignName = "Beamtime Phoenix Spring 2016";
|
|
FileList.Properties.CustomProperties.campaignLocation = "SLS/Phoenix";
|
|
FileList.Properties.CustomProperties.campaignInstrument = "NappEndstation";
|
|
FileList.Properties.CustomProperties.projectName = "NappIce";
|
|
FileList.Properties.CustomProperties.contact = "thorsten.bartels-rausch@psi.ch";
|
|
FileList.Properties.CustomProperties.contactORCID = "0000-0002-7548-2572";
|
|
FileList.Properties.CustomProperties.team = "Thorsten Bartels-Rausch, Xiangrui Kong, Fabrizio Orlando, Luca Artiglia, Astrid Waldner,Thomas Huthwelker,Markus Ammann";
|
|
FileList.Properties.CustomProperties.sourceDirectory = FileList.folder{1};
|
|
FileList.Properties.CustomProperties.startDate = FileList(1,:).lastModifiedDatestr{:};
|
|
FileList.Properties.CustomProperties.endDate = FileList(end,:).lastModifiedDatestr{:};
|
|
FileList.Properties.CustomProperties.dataLevel = 0;
|
|
FileList.Properties.CustomProperties.publicationDoi = "10.5194/tc-15-2001-2021";
|
|
FileList.Properties.CustomProperties.publicationDataDoi = "10.16904/envidat.164";
|
|
FileList.Properties.CustomProperties.rawDataDoi = " ";
|
|
FileList.Properties.CustomProperties.funding = "SNF 149629";
|
|
|
|
|
|
% Adds human-readable column descriptions and units to the standard table
|
|
% properties Properties.VariableDescriptions / Properties.VariableUnits
|
|
|
|
meta.name = struct('desc','File name of the imported data or photo file.', 'unit','');
|
|
meta.folder = struct('desc','Full path to the folder containing the file.', 'unit','');
|
|
meta.creationDate = struct('desc','Acquisition timestamp: from instrument metadata for XPS/NEXAFS files, or OS file creation time for photos. Stored as a datevec [Y M D H MI S].', 'unit','');
|
|
meta.lastModifiedDatenum = struct('desc','OS file modification time, as a MATLAB datenum.', 'unit','');
|
|
meta.lastModifiedDatestr = struct('desc','OS file modification time, as a formatted date string.', 'unit','');
|
|
meta.image = struct('desc','2D spectral map (kinetic energy vs. iteration/scan), normalized to counts per second.', 'unit','counts/s');
|
|
meta.imageRoh = struct('desc','Raw copy of the 2D spectral map.', 'unit','counts/s');
|
|
meta.xRayEkin_eV = struct('desc','X-ray excitation (photon) energy: the scan axis for NEXAFS, or the single excitation energy used for an XPS region.', 'unit','eV');
|
|
meta.xRayEkinRange_eV = struct('desc','[min max] range of the X-ray excitation energy scan.', 'unit','eV');
|
|
meta.scientaPassEnergy_eV = struct('desc','Analyzer pass energy setting.', 'unit','eV');
|
|
meta.scientaDwellTime_ms = struct('desc','Aquisition (step) time per data point.', 'unit','ms');
|
|
meta.regionName = struct('desc','Name of the measured region, e.g. an XPS core level (''C1s''), a survey scan, or a NEXAFS edge.', 'unit','');
|
|
meta.scientaAcquisitionMode = struct('desc','Analyzer acquisition mode: ''Swept'' (scanning) or ''Fixed'' (fixed energy window).', 'unit','');
|
|
meta.scientaEkinRange_eV = struct('desc','[min max] kinetic energy range of the analyzer scan.', 'unit','eV');
|
|
meta.scientaEkinStep_eV = struct('desc','Kinetic energy step size between data points.', 'unit','eV');
|
|
meta.scientaEkin_eV = struct('desc','The kinetic energy axis of the spectrum.', 'unit','eV');
|
|
meta.scientaEkinRoh_eV = struct('desc','Raw copy of the kinetic energy axis of the spectrum, kept alongside scientaEkin_eV in case later processing modifies the data.', 'unit','eV');
|
|
meta.beamlineInt = struct('desc','Beamline (incident photon) intensity, I0, used to normalize NEXAFS signal.', 'unit','a.u.');
|
|
meta.scientaLensMode = struct('desc','Analyzer lens transmission mode.', 'unit','');
|
|
meta.scientaAnalyzerSlit = struct('desc','Analyzer entrance slit setting.', 'unit','');
|
|
meta.scientaWorkfunction_eV = struct('desc','Analyzer work function used in the kinetic-to-binding-energy conversion.', 'unit','eV');
|
|
meta.scientaRegionIterations = struct('desc','Number of repeated scans within one region measurement, averaged together during import.', 'unit','');
|
|
meta.scientaSequenceIterations = struct('desc','Number of sequence repeats.', 'unit','');
|
|
meta.importDate = struct('desc','Timestamp of when this row was generated by nappFileList.', 'unit','');
|
|
meta.analysisDir = struct('desc','Working directory (or calling script''s folder) at the time of import.', 'unit','');
|
|
meta.sample = struct('desc','Sample name or description, from the SpecsLab comment field (.xy files) or set later from the lab journal.', 'unit','');
|
|
meta.sampleTemp_dC = struct('desc','Sample (cryo-holder) temperature, from the LabView log.', 'unit','degC');
|
|
meta.cellPressure_mbar = struct('desc','Sample cell pressure, from the LabView Baratron log.', 'unit','mbar');
|
|
meta.iceTemp_dC = struct('desc','Ice equilibrium temperature, derived from cellPressure_mbar via the Marti & Mauersberger (1993) vapour-pressure parameterization.', 'unit','degC');
|
|
meta.smplX_mm = struct('desc','Sample holder X position.', 'unit','mm');
|
|
meta.smplY_mm = struct('desc','Sample holder Y position.', 'unit','mm');
|
|
meta.smplZ_mm = struct('desc','Sample holder Z position.', 'unit','mm');
|
|
meta.sealingTemp = struct('desc','Sealing temperature, from the LabView log.', 'unit','degC');
|
|
meta.originalFileName = struct('desc','Original file name before a multi-region Specs .xy file was split into one row per region.', 'unit','');
|
|
% added by generate spectra
|
|
meta.spectrum_countsPerSecond = struct('desc','1D spectrum for .ibw/.xy rows in ''mean''/''trapz'' mode: the mean (or trapz) of the image data -- already counts/s, since nappFileList normalizes by dwell time before storing image. Not populated for .h5/NEXAFS rows (their result goes to spectrum_counts instead).', 'unit','counts/s');
|
|
meta.spectrum_counts = struct('desc','1D spectrum: for .h5/NEXAFS rows, the sum or trapezoidal integral of the image over the selected kinetic-energy range (not time-normalized), for any mode; for .ibw/.xy rows, only populated when mode=''sum'' (sum over the selected iteration range).', 'unit','counts');
|
|
meta.logNappGenerateSpectraRange = struct('desc','[start end] range used to generate the spectrum: kinetic-energy limits for .h5 rows, or iteration indices for .ibw/.xy rows.', 'unit','eV (h5) or index (ibw/xy)');
|
|
meta.logNappGenerateSpectraDate = struct('desc','Logs when the spectrum was generated', 'unit','');
|
|
meta.logNappGenerateSpectraMode = struct('desc','Reduction mode used to generate the spectrum for this row (''mean'', ''sum'', ''trapz'', or ''AugerMeitnerMean'').', 'unit','');
|
|
meta.logNappGenerateSpectraCaller = struct('desc','File path of the script or function that called nappGenerateSpectra, for provenance.', 'unit','');
|
|
|
|
varNames = FileList.Properties.VariableNames;
|
|
descriptions = repmat({''}, 1, numel(varNames));
|
|
units = repmat({''}, 1, numel(varNames));
|
|
for k = 1:numel(varNames)
|
|
if isfield(meta, varNames{k})
|
|
descriptions{k} = meta.(varNames{k}).desc;
|
|
units{k} = meta.(varNames{k}).unit;
|
|
end
|
|
end
|
|
FileList.Properties.VariableDescriptions = descriptions;
|
|
FileList.Properties.VariableUnits = units;
|
|
|
|
|
|
%% Tidy up
|
|
FileList = removevars(FileList,{'smplX_mm','smplY_mm','smplZ_mm','scientaAnalyzerSlit','scientaWorkfunction_eV','sealingTemp'});
|
|
FileList.comment = repmat({''}, height(FileList), 1);
|
|
clearvars -except FileList
|
|
%% Export and Save
|
|
ExportList = removevars(FileList, {'image', 'scientaEkin_eV', 'beamlineInt', 'imageRoh', 'scientaEkinRoh_eV', 'xRayEkin_eV', 'spectrum_countsPerSecond', 'spectrum_counts' });
|
|
% @DEP_OUT: Apr2016_DataTable.csv
|
|
writetable(ExportList,fullfile([datestr(ExportList.lastModifiedDatenum(1),'mmmYYYY') '_DataList.csv']),'Delimiter',',');
|
|
|
|
% write to command line
|
|
whos('FileList'); % basic size/type info
|
|
disp('--- Table Properties ---')
|
|
disp(FileList.Properties) % show table properties (Description, UserData, VariableDescriptions, etc.)
|
|
disp('--- Summary of Table ---')
|
|
summary(FileList) % concise summary of variables and types
|
|
%%
|
|
clearvars -except FileList
|
|
% @DEP_OUT: Apr2016_DataTable.mat
|
|
save("Apr2016_DataTable.mat")
|
|
% @DEP_OUT: Apr2016_DataTable.h5
|
|
nappExportH5(FileList, "Apr2016_DataTable.h5"); |