Updated to new PShell file structure and added abiltiy to read several spectra in each h5 file
This commit is contained in:
1 parent
723714c85d
commit
efff7c29f5
1 file changed
+359
-60
+359
-60
@@ -78,6 +78,8 @@ function ListFiles = nappFileList(dataPath,varargin)
|
||||
% * April 2021, X-ray kinetic energy and images are now made unique
|
||||
% * March 2022, input now using varargin
|
||||
% * March 2022, strict data structure required for local and remote sources
|
||||
% * November 2025, PShell h5 files for NEXAFS have a new structure; added
|
||||
% creation date to mac for NEXAFS.
|
||||
|
||||
%% Input
|
||||
% Define conditions and defaults of input
|
||||
@@ -243,6 +245,78 @@ else
|
||||
|
||||
% The second line of code filters all files that start with Numbers or
|
||||
% letters. All system files starting with a . or ~ are discarded.
|
||||
% =========================================================================
|
||||
% SPLIT HDF5 FILES WITH MULTIPLE DATASETS INTO INDIVIDUAL FILES
|
||||
% =========================================================================
|
||||
%
|
||||
% BACKGROUND:
|
||||
% HDF5 files from the beamline can contain multiple experimental scans
|
||||
% (e.g., scan_1, scan_2, scan_3) stored as separate groups within a
|
||||
% single file. However, the NEXAFS and XPS data processing pipelines
|
||||
% are designed to work with one scan per file.
|
||||
%
|
||||
% PURPOSE:
|
||||
% This script identifies HDF5 files that contain multiple scans and
|
||||
% splits each scan into a separate file with a descriptive name.
|
||||
% Each output file contains only one scan (renamed to scan_1) plus
|
||||
% the logs and metadata groups.
|
||||
%
|
||||
% PROCESS:
|
||||
% 1. Loop through all NEXAFS HDF5 files in the file list
|
||||
% 2. Check if each file contains more than 3 groups (indicating multiple scans)
|
||||
% 3. If it does, split it using the splitH5Scans function
|
||||
% 4. The original file is deleted after splitting
|
||||
%
|
||||
% OUTPUT:
|
||||
% For each multi-scan file, creates separate output files:
|
||||
% Example: 0002_..._O_Kedge.h5 0002_..._O_Kedge_scan_1.h5
|
||||
% 0002_..._O_Kedge_scan_2.h5
|
||||
% =========================================================================
|
||||
|
||||
% Loop through each file in the NEXAFS file list
|
||||
% TmpFileList{2} contains the full paths to all NEXAFS HDF5 files
|
||||
% ii is the loop counter (1, 2, 3, ... up to the total number of files)
|
||||
for ii = 1:size(TmpFileList{2}, 1)
|
||||
|
||||
% Get the filename of the current file being processed
|
||||
current_file = [TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name];
|
||||
|
||||
% Read information about the structure of the HDF5 file
|
||||
% This tells us what groups (datasets) are stored in the file
|
||||
fileinfo = h5info(current_file);
|
||||
|
||||
% Extract the names of all groups at the root level
|
||||
% Example: {'/scan_1', '/scan_2', '/logs', '/__DATA_TYPES__'}
|
||||
groupnames = {fileinfo.Groups.Name};
|
||||
|
||||
% Check if this file has more than 3 groups
|
||||
% Files with more than 3 groups likely contain multiple scans
|
||||
% (the extra groups beyond scans are typically '/logs' and '/__DATA_TYPES__')
|
||||
if numel(groupnames) > 3
|
||||
|
||||
% This file contains multiple scans, so split it
|
||||
% The splitH5Scans function will:
|
||||
% - Create separate files for each scan
|
||||
% - Rename each scan to '/scan_1' within its new file
|
||||
% - Delete the original multi-scan file when done
|
||||
splitH5Scans(current_file);
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
% =========================================================================
|
||||
% NOTE: After this loop completes, all NEXAFS files in data folder
|
||||
% will contain exactly one scan per file, ready for processing
|
||||
% =========================================================================
|
||||
|
||||
% EPICS files in h5 format list all files, then get rid of system files
|
||||
TmpFileList{2} = dir([dataPath_NEXAFS filesep '**' filesep '*.h5']);
|
||||
TmpFileList{2} = TmpFileList{2}(find(~cellfun(@isempty,regexp({TmpFileList{2}.name},'^[a-zA-Z0-9]\w*')))); %#ok<FNDSB>
|
||||
|
||||
disp('*************************************************')
|
||||
disp('* Voila: Splitting NEXAFS files done *')
|
||||
disp('*************************************************')
|
||||
|
||||
% only process new files
|
||||
if (istable(p.Results.DataTable) & matches(p.Results.mode,'localNew')) % do this only if previous list was input to function call
|
||||
@@ -282,20 +356,21 @@ end
|
||||
|
||||
try
|
||||
if contains(p.Results.mode,'data')
|
||||
tmp.fileinfo = dir([dataPath_XPS '/*.xy']);
|
||||
filedate_first = tmp.fileinfo(1).datenum;
|
||||
clearvars name tmp
|
||||
tmp.fileinfo = dir([dataPath_XPS '/*.xy']);
|
||||
filedate_first = tmp.fileinfo(1).datenum;
|
||||
clearvars name tmp
|
||||
else
|
||||
tmp.fileinfo = dir([dataPath_XPS '/*.ibw']);
|
||||
filedate_first = tmp.fileinfo(1).datenum;
|
||||
clearvars name tmp
|
||||
tmp.fileinfo = dir([dataPath_XPS '/*.ibw']);
|
||||
filedate_first = tmp.fileinfo(1).datenum;
|
||||
clearvars name tmp
|
||||
end
|
||||
catch
|
||||
catch
|
||||
warning('There appears to be something wrong with the SES or Specs file.')
|
||||
disp('There appears to be something wrong with the SES or Specs file.')
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
%% Import XPS data to get SES settings
|
||||
%
|
||||
% Uses the IgorPro importer for Matlab:
|
||||
@@ -341,14 +416,14 @@ if contains(p.Results.mode,'data') % for Specs xy data %TODO this is based on fi
|
||||
disp('Problem reading the Specs file')
|
||||
fprintf('Number %.0f: %s \n',ii,[TmpFileList{1}(ii).folder filesep TmpFileList{1}(ii).name])
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
try
|
||||
%% Convert Specs meta data into variables
|
||||
|
||||
% data
|
||||
tmpEndFirstSpectrum = find(diff(tmpSpecsData{1})<0,1); % FIXME: imports only first spectrum
|
||||
tmpEndFirstSpectrum = find(diff(tmpSpecsData{1})<0,1); % FIXME: imports only first spectrum
|
||||
% counts
|
||||
PE.y = tmpSpecsData{2}(1:tmpEndFirstSpectrum);
|
||||
% kinetic energy
|
||||
@@ -563,18 +638,28 @@ for ii = 1:size(TmpFileList{2},1) % do this for each list element
|
||||
|
||||
%if ~isempty(h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/energy'))
|
||||
% creation date of file
|
||||
TmpFileList{2}(ii).creationDate = datevec(NaN);
|
||||
if ismac
|
||||
tmpCommand = sprintf('stat -f "%%SB" "%s"', [TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name]);
|
||||
[~,creation] = system(tmpCommand);
|
||||
TmpFileList{2}(ii).creationDate = datevec(creation);
|
||||
else
|
||||
TmpFileList{2}(ii).creationDate = datevec(NaN);
|
||||
end
|
||||
try
|
||||
% read data
|
||||
%if datenum(filedate_first) <= datenum('21-Nov-2020 00:01:00') % Date not exaclty certain.
|
||||
try
|
||||
TmpImage= h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/spectrum');
|
||||
%else
|
||||
TmpImage= h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/spectrum');
|
||||
catch
|
||||
try
|
||||
TmpImage = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/scienta spectrum');
|
||||
TmpImage= h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/spectrum');
|
||||
%else
|
||||
catch
|
||||
TmpImage = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/detector/data'); % pre-2020 (?) h5 structure
|
||||
try
|
||||
TmpImage = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/scienta spectrum');
|
||||
catch
|
||||
TmpImage = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/detector/data'); % pre-2020 (?) h5 structure
|
||||
end
|
||||
end
|
||||
end
|
||||
% 21.8.20 changed from spectrum to scienta spectrum, later
|
||||
@@ -587,11 +672,16 @@ for ii = 1:size(TmpFileList{2},1) % do this for each list element
|
||||
|
||||
% import Photon Energy (cols)
|
||||
try
|
||||
TmpXrayEkin = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/energy'); % X-ray excitation energy; Photon energy in eV
|
||||
TmpXrayEkin = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/energy'); % X-ray excitation energy; Photon energy in eV
|
||||
TmpXrayEkin(TmpXrayEkin==0)=[];
|
||||
catch
|
||||
TmpXrayEkin = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/PhotonEnergy'); % X-ray excitation energy; Photon energy in eV
|
||||
TmpXrayEkin(TmpXrayEkin==0)=[];
|
||||
try
|
||||
TmpXrayEkin = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/energy'); % X-ray excitation energy; Photon energy in eV
|
||||
TmpXrayEkin(TmpXrayEkin==0)=[];
|
||||
catch
|
||||
TmpXrayEkin = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/PhotonEnergy'); % X-ray excitation energy; Photon energy in eV
|
||||
TmpXrayEkin(TmpXrayEkin==0)=[];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -607,35 +697,45 @@ for ii = 1:size(TmpFileList{2},1) % do this for each list element
|
||||
TmpFileList{2}(ii).image = TmpImage(:,ind);
|
||||
% NEXAFS pass energy
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/PassEnergy'); % in eV
|
||||
TmpFileList{2}(ii).scientaPassEnergy_eV = str2double(tmp(1));
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/snaps/PassEnergy'); % in eV
|
||||
TmpFileList{2}(ii).scientaPassEnergy_eV = str2double(tmp(1,:));
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/PassEnergy'); % in eV
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/PassEnergy'); % in eV
|
||||
TmpFileList{2}(ii).scientaPassEnergy_eV = str2double(tmp(1));
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/PassEnergy'); % in eV
|
||||
|
||||
if tmp(1) == 1
|
||||
TmpFileList{2}(ii).scientaPassEnergy_eV = 20;
|
||||
elseif tmp(1) == 2
|
||||
TmpFileList{2}(ii).scientaPassEnergy_eV = 50;
|
||||
elseif tmp(1) == 3
|
||||
TmpFileList{2}(ii).scientaPassEnergy_eV = 100;
|
||||
elseif tmp(1) == 4
|
||||
TmpFileList{2}(ii).scientaPassEnergy_eV = 200;
|
||||
if tmp(1) == 1
|
||||
TmpFileList{2}(ii).scientaPassEnergy_eV = 20;
|
||||
elseif tmp(1) == 2
|
||||
TmpFileList{2}(ii).scientaPassEnergy_eV = 50;
|
||||
elseif tmp(1) == 3
|
||||
TmpFileList{2}(ii).scientaPassEnergy_eV = 100;
|
||||
elseif tmp(1) == 4
|
||||
TmpFileList{2}(ii).scientaPassEnergy_eV = 200;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% NEXAFS dwell time
|
||||
if datenum(filedate_first) >= datenum('1-Feb-2020 23:59:00')
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/ScientaStepTime')*1000; % in ms
|
||||
% if datenum(filedate_first) >= datenum('1-Feb-2020 23:59:00')
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/snaps/ScientaStepTime')*1000; % in ms
|
||||
|
||||
else
|
||||
catch
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/StepTime')*1000; % in ms
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/ScientaStepTime')*1000; % in ms
|
||||
catch
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/StepTime')*1000; % in ms
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/StepTime')*1000; % in ms
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/ScientaStepTime')*1000;
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/StepTime')*1000; % in ms
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/ScientaStepTime')*1000;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -649,23 +749,31 @@ for ii = 1:size(TmpFileList{2},1) % do this for each list element
|
||||
|
||||
% Acquisition mode
|
||||
try
|
||||
TmpFileList{2}(ii).scientaAcquisitionMode = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/AcquisitionMode');
|
||||
TmpFileList{2}(ii).scientaAcquisitionMode = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/snaps/AcquisitionMode');
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/AcquireMode');
|
||||
if tmp(1) == 0
|
||||
TmpFileList{2}(ii).scientaAcquisitionMode = "Swept";
|
||||
elseif tmp(1) == 1
|
||||
TmpFileList{2}(ii).scientaAcquisitionMode = "Fixed";
|
||||
try
|
||||
TmpFileList{2}(ii).scientaAcquisitionMode = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/AcquisitionMode');
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/AcquireMode');
|
||||
if tmp(1) == 0
|
||||
TmpFileList{2}(ii).scientaAcquisitionMode = "Swept";
|
||||
elseif tmp(1) == 1
|
||||
TmpFileList{2}(ii).scientaAcquisitionMode = "Fixed";
|
||||
end
|
||||
clear tmp
|
||||
end
|
||||
clear tmp
|
||||
end
|
||||
|
||||
if strcmp(TmpFileList{2}(ii).scientaAcquisitionMode,'Fixed')
|
||||
% NEXAFS kinetic energy window - fixed mode
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/ScientaCenterEnergy'); % in eV
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/snaps/ScientaCenterEnergy'); % in eV
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/CenterEnergy'); % in eV
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/ScientaCenterEnergy'); % in eV
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/CenterEnergy'); % in eV
|
||||
end
|
||||
end
|
||||
|
||||
TmpFileList{2}(ii).scientaEkinRange_eV = [double(tmp(1))-TmpFileList{2}(ii).scientaPassEnergy_eV/20 double(tmp(1))+TmpFileList{2}(ii).scientaPassEnergy_eV/20];
|
||||
@@ -677,19 +785,28 @@ for ii = 1:size(TmpFileList{2},1) % do this for each list element
|
||||
else
|
||||
% NEXAFS kinetic energy window - scan mode
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/ScientaLowEnergy'); % in eV
|
||||
tmp2 = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/ScientaHighEnergy');
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/snaps/ScientaLowEnergy'); % in eV
|
||||
tmp2 = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/snaps/ScientaHighEnergy');
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/LowEnergy'); % in eV
|
||||
tmp2 = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/HighEnergy');
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/ScientaLowEnergy'); % in eV
|
||||
tmp2 = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/ScientaHighEnergy');
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/LowEnergy'); % in eV
|
||||
tmp2 = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/HighEnergy');
|
||||
end
|
||||
end
|
||||
TmpFileList{2}(ii).scientaEkinRange_eV = [tmp(1) tmp2(1)];
|
||||
clearvars tmp
|
||||
try
|
||||
TmpFileList{2}(ii).scientaEkinStep_eV = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/StepSize');
|
||||
TmpFileList{2}(ii).scientaEkinStep_eV = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/snaps/StepSize');
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/StepSize');
|
||||
TmpFileList{2}(ii).scientaEkinStep_eV = abs(tmp(1));
|
||||
try
|
||||
TmpFileList{2}(ii).scientaEkinStep_eV = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/StepSize');
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/StepSize');
|
||||
TmpFileList{2}(ii).scientaEkinStep_eV = abs(tmp(1));
|
||||
end
|
||||
end
|
||||
TmpFileList{2}(ii).scientaEkin_eV = [TmpFileList{2}(ii).scientaEkinRange_eV(:,1):TmpFileList{2}(ii).scientaEkinStep_eV(1):TmpFileList{2}(ii).scientaEkinRange_eV(:,2)]';
|
||||
end
|
||||
@@ -697,8 +814,12 @@ for ii = 1:size(TmpFileList{2},1) % do this for each list element
|
||||
clearvars tmp
|
||||
% read I_0
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/i0');
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/i0');
|
||||
catch
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/i0');
|
||||
catch
|
||||
end
|
||||
end
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/RM2I0');
|
||||
@@ -715,22 +836,31 @@ for ii = 1:size(TmpFileList{2},1) % do this for each list element
|
||||
|
||||
% Lens Mode
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/LensMode');
|
||||
TmpFileList{2}(ii).scientaLensMode = tmp{1};
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/snaps/LensMode');
|
||||
TmpFileList{2}(ii).scientaLensMode = tmp;
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/LensMode');
|
||||
TmpFileList{2}(ii).scientaLensMode = num2str(tmp(1));
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/LensMode');
|
||||
TmpFileList{2}(ii).scientaLensMode = tmp{1};
|
||||
catch
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/LensMode');
|
||||
TmpFileList{2}(ii).scientaLensMode = num2str(tmp(1));
|
||||
end
|
||||
end
|
||||
|
||||
clearvars tmp
|
||||
try
|
||||
TmpFileList{2}(ii).scientaRegionIterations = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/NumIterations');
|
||||
TmpFileList{2}(ii).scientaRegionIterations = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan_1/snaps/NumIterations');
|
||||
catch
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/NumIterations');
|
||||
TmpFileList{2}(ii).scientaRegionIterations = double(tmp(1));
|
||||
TmpFileList{2}(ii).scientaRegionIterations = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/NumIterations');
|
||||
catch
|
||||
TmpFileList{2}(ii).scientaRegionIterations = 1;
|
||||
try
|
||||
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/NumIterations');
|
||||
TmpFileList{2}(ii).scientaRegionIterations = double(tmp(1));
|
||||
catch
|
||||
TmpFileList{2}(ii).scientaRegionIterations = 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
TmpFileList{2}(ii).scientaSequenceIterations = 1;
|
||||
@@ -894,6 +1024,22 @@ if matches(p.Results.importLabView,'on')
|
||||
warning('Problem with LabView file')
|
||||
disp('Problem reading LabView file')
|
||||
end
|
||||
|
||||
try
|
||||
% Get list of all files in that folder
|
||||
TmpFileList = dir([dataPath_LabView filesep '**' filesep 'logfile*.txt']);
|
||||
|
||||
% import LabView data
|
||||
LabView = LabView_importData(fullfile(TmpFileList(1).folder,TmpFileList(1).name)); % Overwrite LabView data in workspace, if this is the first import
|
||||
if size(TmpFileList,1) > 1 % for additional data files, add these to the LabView data structure.
|
||||
for ii = 2:size(TmpFileList,1)
|
||||
LabView = LabView_importData(fullfile(TmpFileList(ii).folder,TmpFileList(ii).name),LabView);
|
||||
end
|
||||
end
|
||||
catch
|
||||
warning('Problem with LabView file')
|
||||
disp('Problem reading LabView file')
|
||||
end
|
||||
end
|
||||
disp('*************************************************')
|
||||
disp('* Voila: Done reading LabView data! *')
|
||||
@@ -1356,4 +1502,157 @@ end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
function splitH5Scans(infile)
|
||||
% splitH5Scans - Split an HDF5 file containing multiple scans into separate files
|
||||
%
|
||||
% This function takes an HDF5 file with multiple scan groups (scan_1, scan_2, etc.)
|
||||
% and creates separate files for each scan. Each output file contains only one
|
||||
% scan (renamed to scan_1) plus the logs group. The original file is deleted after
|
||||
% successful splitting.
|
||||
%
|
||||
% SYNTAX:
|
||||
% splitH5Scans(infile)
|
||||
%
|
||||
% INPUT:
|
||||
% infile - String containing the full path to the input HDF5 file
|
||||
% Example: '0002_20251119_145823_O_Kedge_Nov25.h5'
|
||||
%
|
||||
% OUTPUT:
|
||||
% Creates new HDF5 files in the same directory as the input file.
|
||||
% Each file is named: [original_name]_scan_N.h5
|
||||
% Example outputs:
|
||||
% 0002_20251119_145823_O_Kedge_Nov25_scan_1.h5
|
||||
% 0002_20251119_145823_O_Kedge_Nov25_scan_2.h5
|
||||
%
|
||||
% REQUIREMENTS:
|
||||
% - MATLAB with HDF5 support (R2011a or later)
|
||||
% - Input file must have more than 3 root-level groups to be processed
|
||||
%
|
||||
% EXAMPLE:
|
||||
% splitH5Scans('0002_20251119_145823_O_Kedge_Nov25.h5');
|
||||
%
|
||||
% Author: Perplexity and Thorsten
|
||||
% Date: November 2025
|
||||
|
||||
% Read the structure of the HDF5 file to see what groups it contains
|
||||
% h5info returns information about groups, datasets, and attributes
|
||||
fileinfo = h5info(infile);
|
||||
|
||||
% Get the original file's modification date before we start
|
||||
% This will be copied to all new files to preserve the original timestamp
|
||||
orig_file_info = dir(infile);
|
||||
orig_mod_datetime = orig_file_info.date; % Get as datetime object
|
||||
|
||||
|
||||
% Extract the names of all groups at the root level of the file
|
||||
% Example: {'/scan_1', '/scan_2', '/logs', '/__DATA_TYPES__'}
|
||||
groupnames = {fileinfo.Groups.Name};
|
||||
|
||||
% Only process files that have more than 3 groups at the root level
|
||||
% This ensures we only split files with multiple scans
|
||||
if numel(groupnames) > 3
|
||||
|
||||
% Find which groups are scan groups (contain 'scan_' in their name)
|
||||
% This returns a logical array: true for scan groups, false otherwise
|
||||
is_scan = contains(groupnames, 'scan_');
|
||||
|
||||
% Extract only the scan group names
|
||||
% Example: {'/scan_1', '/scan_2'}
|
||||
scan_names = groupnames(is_scan);
|
||||
|
||||
% Split the input filename into its components
|
||||
% filepath: directory where file is located (e.g., 'C:\Data\')
|
||||
% base: filename without extension (e.g., '0002_20251119_145823_O_Kedge_Nov25')
|
||||
% ext: file extension (e.g., '.h5')
|
||||
[filepath, base, ext] = fileparts(infile);
|
||||
|
||||
% If no directory path, use current directory
|
||||
if isempty(filepath)
|
||||
filepath = '.';
|
||||
end
|
||||
|
||||
% Extract the file number prefix and rest of the name using pattern matching
|
||||
% regexp splits '0002_20251119_145823_O_Kedge_Nov25' into:
|
||||
% prefix = '0002_'
|
||||
% rest = '20251119_145823_O_Kedge_Nov25'
|
||||
pieces = regexp(base, '(\d+_)(.*)', 'tokens', 'once');
|
||||
prefix = pieces{1}; % The number at the start (e.g., '0002_')
|
||||
rest = pieces{2}; % Everything after the number
|
||||
|
||||
% Loop through each scan group and create a separate file for it
|
||||
for k = 1:numel(scan_names)
|
||||
|
||||
% Get the full path of the current scan group
|
||||
% Example: '/scan_1' or '/scan_2'
|
||||
scan_group_full = scan_names{k};
|
||||
|
||||
% Remove the leading '/' from the scan name for use in filename
|
||||
% Example: '/scan_2' becomes 'scan_2'
|
||||
scan_name_clean = regexprep(scan_group_full, '^/', '');
|
||||
|
||||
% Build the output filename in the same directory as input file
|
||||
% Example: 'C:\Data\0002_20251119_145823_O_Kedge_Nov25_scan_2.h5'
|
||||
outname = fullfile(filepath, sprintf('%s%s_%s%s', prefix, rest, scan_name_clean, ext));
|
||||
|
||||
% Copy the entire original file to create the new output file
|
||||
% We'll modify this copy to keep only one scan
|
||||
copyfile(infile, outname);
|
||||
|
||||
% Open the new file for reading and writing using low-level HDF5 functions
|
||||
% fid is a file identifier used to reference this file
|
||||
% 'H5F_ACC_RDWR' means read and write access
|
||||
fid = H5F.open(outname, 'H5F_ACC_RDWR', 'H5P_DEFAULT');
|
||||
|
||||
% Delete all scan groups except the one we want to keep
|
||||
% Loop through all scan groups in the original file
|
||||
for j = 1:numel(scan_names)
|
||||
other_scan = scan_names{j}; % Get the name of another scan group
|
||||
|
||||
% If this is not the scan we want to keep, delete it
|
||||
if j ~= k
|
||||
try
|
||||
% H5L.delete removes the link (reference) to the group
|
||||
% This makes the group inaccessible but doesn't free space
|
||||
H5L.delete(fid, other_scan, 'H5P_DEFAULT');
|
||||
catch
|
||||
% If deletion fails (e.g., group doesn't exist), continue
|
||||
% The catch block prevents the script from stopping on errors
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% Rename the kept scan group to '/scan_1' for consistency
|
||||
% This way every output file has a group called '/scan_1'
|
||||
if ~strcmp(scan_group_full, '/scan_1')
|
||||
% H5L.move renames/moves a group within the file
|
||||
% Parameters: source_file, old_path, dest_file, new_path, options
|
||||
H5L.move(fid, scan_group_full, fid, '/scan_1', 'H5P_DEFAULT', 'H5P_DEFAULT');
|
||||
end
|
||||
|
||||
% Close the HDF5 file to save all changes
|
||||
H5F.close(fid);
|
||||
|
||||
% Copy the modification date from the original file to the new file
|
||||
% Convert MATLAB datenum to timestamp format: YYYYMMDDhhmm.ss
|
||||
timestamp_str = string(datetime(orig_mod_datetime), 'yyyyMMddHHmm.ss');
|
||||
if ismac
|
||||
touch_cmd = sprintf('touch -t %s "%s"', timestamp_str, outname);
|
||||
system(touch_cmd);
|
||||
end
|
||||
|
||||
% Print confirmation message showing which file was created
|
||||
% fprintf('Created: %s\n', outname);
|
||||
end
|
||||
|
||||
% After all split files are successfully created, delete the original file
|
||||
delete(infile);
|
||||
% fprintf('Deleted original file: %s\n', infile);
|
||||
|
||||
else
|
||||
% If the file has 3 or fewer groups, it doesn't need splitting
|
||||
% disp('File has three or fewer groups. No processing required.');
|
||||
end
|
||||
|
||||
end
|
||||
Reference in new issue
Block a user