some housekeeping to tidy up

This commit is contained in:
bartels-rausch committed 2026-08-21 10:28:44 +02:00
1 parent 5b9c7608d7
commit 4d6500ba85
101 files changed
+5288 -3361

No files matched your search

-2
View File
@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<MATLABProject xmlns="http://www.mathworks.com/MATLABProjectFile" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"/>
Binary file not shown.
-188
View File
@@ -1,188 +0,0 @@
function D = IBWread(FN);
% IBWread - read Igor wave from IBW file
% D = IBWread('Foo.ibw') reads Igor file Foo.ibw into struct D.
if exist('fullfilename', 'file'), FFN = fullfilename(FN, cd, '.ibw');
else, FFN = FN;
end
% read headers
[D.binHeader, D.waveHeader, FFN] = readIBWheaders(FN);
fid = fopen(FFN,'r');
fid = fopen(FFN,'r');
% For numeric waves, the type field is interpreted bitwise. One of the following bits, as represented by symbols defined in IgorBin.h, will be set:
%
% % #define NT_CMPLX 1 % Complex numbers.
% % #define NT_FP32 2 % 32 bit fp numbers.
% % #define NT_FP64 4 % 64 bit fp numbers.
% % #define NT_I8 8 % 8 bit signed integer. Requires Igor Pro 2.0 or later.
% % #define NT_I16 0x10 % 16 bit integer numbers. Requires Igor Pro 2.0 or later.
% % #define NT_I32 0x20 % 32 bit integer numbers. Requires Igor Pro 2.0 or later.
% % #define NT_UNSIGNED 0x40 % Makes above signed integers unsigned. Requires Igor Pro 3.0 or later.
% NT_FP64 64-bit floating point (double)
% NT_FP32 32-bit floating point (float)
% NT_I32 32 bit integer (long)
% NT_16 16 bit integer (short)
% NT_I8 8 bit integer (char)
datatype = D.waveHeader.type;
CMPLX = rem(datatype,2);
if CMPLX, datatype = datatype-1; end
switch datatype,
case 0, prec = '*char';
case 2, prec = 'single';
case 4, prec = 'double';
case 8, prec = 'int8';
case 16, prec = 'int16';
case 32, prec = 'int32';
case 64+8, prec = 'uint8';
case 64+16, prec = 'uint16';
case 64+32, prec = 'uint32';
otherwise, error('Invalid numerical datatype.');
end
D.bname = D.waveHeader.bname;
% The date/time is store as seconds since midnight, January 1, 1904.
D.creationDate = local_igorTime2vec(D.waveHeader.creationDate);
D.modDate = local_igorTime2vec(D.waveHeader.creationDate);
switch D.binHeader.version,
case 2,
% The version 2 file has the following general layout.
% BinHeader2 structure: 16 bytes
% WaveHeader2 structure excluding wData field; 110 bytes
% Wave data: Variable size
D.Nsam = D.waveHeader.npnts;
D.Ndim = 1;
% X value for point p = hsA*p + hsB
D.dx = D.waveHeader.hsA;
D.x0 = D.waveHeader.hsB;
D.x1 = D.x0+D.Nsam*D.dx;
fseek(fid, 16+110, 'bof');
NN = D.Nsam*(1+double(CMPLX)); % if complex, read twice as many numbers
D.y = fread(fid, NN, prec);
if CMPLX, D.y = D.y(1:2:end) + i*D.y(2:2:end); end; % Re & Im values are interleaved
case 5,
% The version 5 file has the following general layout.
% BinHeader5 structure 64 bytes
% WaveHeader5 structure excluding wData field 320 bytes
% Wave data Variable size
% Optional wave dependency formula Variable size
% Optional wave note data Variable size
D.Nsam = D.waveHeader.npnts;
D.Ndim = sum(D.waveHeader.nDim>0);
% X offset & spacing (documentation is obscure)
D.dx = D.waveHeader.sfA(1:D.Ndim);
D.x0 = D.waveHeader.sfB(1:D.Ndim);
D.x1 = nan; % D.x0+D.Nsam*D.dx;
fseek(fid, 64+320, 'bof');
NN = D.Nsam*(1+double(CMPLX)); % if complex, read twice as many numbers
if isequal(0,datatype), % text data
% Number of bytes of wave data = wfmSize - (sizeof(WaveHeader5) - 4)
NN = D.binHeader.wfmSize-320;
D.y = fread(fid, NN, prec)';
else, % numerical data
D.y = fread(fid, NN, prec);
end
if CMPLX, D.y = D.y(1:2:end) + i*D.y(2:2:end); end; % Re & Im values are interleaved
if ~isempty(D.y) && D.Ndim>1,
D.y = reshape(D.y, D.waveHeader.nDim(1:D.Ndim));
end
end
D.WaveNotes = local_readNotes(fid, D.binHeader);
if isequal(0,datatype), % partition text data into lines using string indices stored @ eof
D = local_partition_text(fid, D);
end
fseek(fid,0,'eof');
D.fileSize = ftell(fid);
fclose(fid);
%===============================
function DV=local_igorTime2vec(it);
% igor time -> date vector a la Matlab
% The date/time is store as seconds since midnight, January 1, 1904.
Nsec_4year = 126230400;
idate_1988 = 21*uint32(Nsec_4year); % # seconds between 1-jan-1904 & 1-jan-1988
it = double(it-idate_1988); % smaller numbers-> use ordinary numbers ("doubles")
M4 = floor(it/Nsec_4year);
YR = double(1988+4*M4);
it = double(it-M4*Nsec_4year);
last_it = it;
while 1, % subtract years as long as they fit
s = etime([YR+1 1 1 0 0 0], [YR 1 1 0 0 0]);
if it<s, break; end % we went too far
YR = YR+1;
it = it-s;
end
MNTH = 1;
while 1, % subtract months as long as they fit
s = etime([YR MNTH+1 1 0 0 0], [YR MNTH 1 0 0 0]);
if it<s, break; end % we went too far
MNTH = MNTH+1;
it = it-s;
end
DAY = 1;
while 1, % subtract days as long as they fit
s = etime([YR MNTH DAY+1 0 0 0], [YR MNTH DAY 0 0 0]);
if it<s, break; end % we went too far
DAY = DAY+1;
it = it-s;
end
HR = floor(it/60^2); it = it-HR*60^2;
MIN = floor(it/60); SEC = it-MIN*60;
DV = [YR, MNTH, DAY, HR, MIN, SEC];
if ~isequal(last_it, etime(DV, [1988+4*M4 1 1 0 0 0])),
error('date error');
end
function Nts = local_readNotes(fid, B);
switch B.version,
case 2,
% BinHeader2 structure 16 bytes
% WaveHeader2 structure excluding wData field 110 bytes
% Wave data Variable size
% 16 bytes of padding 16 bytes
dum = fread(fid,16,'char');
% Optional wave note data
Nts = fread(fid, B.noteSize, '*char').';
case 5,
% BinHeader5 structure 64 bytes
% WaveHeader5 structure excluding wData field 320 bytes
% Wave data Variable size
% Optional wave dependency formula Variable size
dum = fread(fid,B.formulaSize, 'char');
% Optional wave note data Variable size
Nts = fread(fid, B.noteSize, '*char').';
end
function D = local_partition_text(fid, D);
% read sizeindices and chop text accordingly, must be called after reading
% notes
bH = D.binHeader;
% skip other stuff in file
% The version 5 file has the following general layout.
% BinHeader5 structure 64 bytes
% WaveHeader5 structure excluding wData field 320 bytes
% Wave data Variable size
% Optional wave dependency formula Variable size
% Optional wave note data Variable size
% Optional extended data units data Variable size
% Optional extended dimension units data Variable size
% Optional dimension label data Variable size
% String indices used for text waves only Variable size
dum=fseek(fid, -bH.sIndicesSize, 'eof'); % string indices are last in file; it's easier to refer from end-of-file
% bH.sIndicesSize; # bytes of string indices stored for the wave if the wave type is text.
% String indices are used to determine the offset in the file and the number of bytes for each element of the text wave.
sIdx = [0 fread(fid, bH.sIndicesSize/4, 'uint32').'];
for ii=1:numel(sIdx)-1,
STR{ii,1} = D.y(sIdx(ii)+1:sIdx(ii+1));
end
D.y = STR;
% long sIndicesSize; The size of string indicies if this is a text wave.
-136
View File
@@ -1,136 +0,0 @@
function ListFiles = QuickAndDirtyNexafsImport(DataTable)
%% QuickAndDirtyNexafsImport
%
[filePick,pathPick] = uigetfile({'*.h5'},...
'Select One or More Files',...
'MultiSelect', 'on');
% make lists for Nexafs
if ischar(filePick)
filePick = {filePick};
end
for ii = 1:size(filePick,2)
TmpFileList{2}(ii,1) = dir([pathPick filePick{ii}]);
end
for ii = 1:size(filePick,2)
try
TmpImage= h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/spectrum');
%else
catch
try
TmpImage = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/scienta spectrum');
catch
TmpData = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/detector/data');
%convert 3 dim matrix to 2 dim matrix
for i = 1:size(TmpData,3)%iterations
TmpImage(:,i) = TmpData(:,1,(i)); %#ok<*SAGROW>
end
end
end
% import Photon Energy (cols)
try %general try to ensure that script does not stop upon errors.
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
% Make unique
[TmpFileList{2}(ii).xRayEkin_eV, ind] = unique(TmpXrayEkin);
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));
catch
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/PassEnergy'); % in eV
TmpFileList{2}(ii).scientaPassEnergy_eV = str2double(tmp(1));
end
% Acquisition mode
try
TmpFileList{2}(ii).scientaAcquisitionMode = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/AcquisitionMode');
catch
TmpFileList{2}(ii).scientaAcquisitionMode = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/AcquireMode');
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
catch
tmp = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/CenterEnergy'); % in eV
end
TmpFileList{2}(ii).scientaEkinRange_eV = [tmp(1)-TmpFileList{2}(ii).scientaPassEnergy_eV/20 tmp(1)+TmpFileList{2}(ii).scientaPassEnergy_eV/20];
TmpFileList{2}(ii).scientaEkinStep_eV = NaN;
TmpFileList{2}(ii).scientaEkin_eV = linspace(TmpFileList{2}(ii).scientaEkinRange_eV(:,1)...
,TmpFileList{2}(ii).scientaEkinRange_eV(:,2),size(TmpFileList{2}(ii).image,1))';
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');
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
TmpFileList{2}(ii).scientaEkinRange_eV = [tmp(1) tmp2(1)];
try
TmpFileList{2}(ii).scientaEkinStep_eV = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/scan 1/attrs/StepSize');
catch
TmpFileList{2}(ii).scientaEkinStep_eV = h5read([TmpFileList{2}(ii).folder filesep TmpFileList{2}(ii).name],'/entry/instrument/NDAttributes/StepSize');
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
catch
end
end
%% Merge lists into one
%
% get index of non-empty structures
tf =~cellfun(@isempty,TmpFileList);
% merge the non-empty list structures into one structure
ListFiles = cat(1,TmpFileList{tf});
% remove lines with empty images
for ii = 1:size(ListFiles,1)
tmpLogic(ii) = isempty(ListFiles(ii).image);
noncells = tmpLogic;
end
ListFiles(noncells) = [];
clearvars -except ListFiles DataTable
%%
%% Sort by date
% rename date fields and delete those fields not needed
[ListFiles.lastModifiedDatestr] = ListFiles.date;
[ListFiles.lastModifiedDatenum] = ListFiles.datenum;
% First, we need to convert into a table, because structures can not be sorted:
ListFiles = struct2table(ListFiles,'AsArray',true);
% Then, we sort the table based on the time (6th column, datenum)
ListFiles = sortrows(ListFiles,6);
% Then, remove un-needed columns
ListFiles = removevars(ListFiles,{'bytes','isdir','date','datenum'});
% merge tables (append imported data to previous table)
if exist("DataTable",'var')
ListFiles = outerjoinRowToTable(ListFiles,DataTable);
end
% Then, we sort the table based on the time (datenum)
ListFiles = sortrows(ListFiles,'lastModifiedDatenum');
end
-134
View File
@@ -1,134 +0,0 @@
%% Develpment of hdf export and import
%
% from table to our instrument hdf structure
%% Todo
%
% * ensure logging of processing in NEXAFS and XPS to select data, make it
% usfull for string operations (no cells)
% * How to include units and definitions
% * Next, make this work for averageded files
%%
clc
% % add some SES data
%tmpFileImport = load('../beamtimes/20220828BeamTimeIceNappIss/FileList.mat');
% FileList = outerjoinRowToTable(FileList, tmpFileImport.FileList);
clearvars tmp*
% select only data that has been used,
[tmpn1, ~] = cellfun(@size,FileList.spectrum_counts); % spectra have been generated
[tmpn2, ~] = cellfun(@size,FileList.spectrum_countsNorm);
[tmpn3, ~] = cellfun(@size,FileList.spectrum_countsPerSecond);
tmpDataSelection = contains(FileList.sample,lettersPattern) ... % we have added sample notes, so this is data
& ~contains(FileList.sample, '(bad data)') & ~contains(FileList.sample, '(no notes)') ...
& (tmpn1 > 1 | tmpn2 > 1 | tmpn3 > 1); % has actually been proceesed.
tmpUserName = 'ThorstenBR';
tmpFileList = FileList(tmpDataSelection,:);
% get table variables that are data
tmpMissingVariable = ~ismember(tmpFileList.Properties.VariableNames,...
[{'image'}; {'spectrum_counts'}; {'spectrum_countsPerSecond'}; {'spectrum_countsNorm'}; {'xRayEkin_eV'}; {'scientaEkin_eV'}; {'imageRoh'}; {'spectrum_countsPerSecondRoh'};{'beamlineInt'}]);
tmpVariablesToBeAdded = tmpFileList.Properties.VariableNames(tmpMissingVariable);
for ij = 1:size(tmpFileList,1)
% get file name and "instruement" name
tmpPathParts = split(tmpFileList(ij,:).folder,"/");
tmpFileName = [tmpPathParts{end-1} tmpUserName '.h5'];
tmpTopGroupName = tmpPathParts{end};
% write data
h5create(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/image'],...
size(tmpFileList(ij,:).image{:}));
h5write(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/image'],...
tmpFileList(ij,:).image{:})
if %XPS
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/image'],'label','electron emission intensity');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/image'],'units','XPS (y,x): counts per second vs. electron volt; NEXAFS (y,x,z): counts vs. X-ray photon kinetic energy vs. electron kinetic energy');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/image'],'definition','X-ray excited electron emission');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/image'],'comment','XPS: intensity vs. electron kinetic energy for each sequence iteration; NEXAFS: intensity vs. x-ray photon kinetic energy (non-linear scaling) vs. electron kinetic energy');
else %NEXAFS
end
try
h5create(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_counts'],...
size(tmpFileList(ij,:).spectrum_counts{:}));
h5write(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_counts'],...
tmpFileList(ij,:).spectrum_counts{:})
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_counts'],'label','electron emission intensity');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_counts'],'units','arb. unit');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_counts'],'definition','X-ray excited electron emission');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_counts'],'comment',' ');
catch
end
try
h5create(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsPerSecond'],...
size(tmpFileList(ij,:).spectrum_countsPerSecond{:}));
h5write(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsPerSecond'],...
tmpFileList(ij,:).spectrum_countsPerSecond{:})
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsPerSecond'],'label',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsPerSecond'],'units',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsPerSecond'],'definition',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsPerSecond'],'comment',' ');
catch
end
try
h5create(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsNorm'],...
size(tmpFileList(ij,:).spectrum_countsNorm{:}));
h5write(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsNorm'],...
tmpFileList(ij,:).spectrum_countsNorm{:})
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsNorm'],'label',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsNorm'],'units',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsNorm'],'definition',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/spectrum_countsNorm'],'comment',' ');
catch
end
try
h5create(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/beamlineInt'],...
size(tmpFileList(ij,:).beamlineInt{:}));
h5write(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/beamlineInt'],...
tmpFileList(ij,:).beamlineInt{:})
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/beamlineInt'],'label',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/beamlineInt'],'units',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/beamlineInt'],'definition',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/beamlineInt'],'comment',' ');
catch
end
h5create(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/xRayEkin_eV'],...
size(tmpFileList(ij,:).xRayEkin_eV{:}));
h5write(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/xRayEkin_eV'],...
tmpFileList(ij,:).xRayEkin_eV{:})
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/xRayEkin_eV'],'label',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/xRayEkin_eV'],'units',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/xRayEkin_eV'],'definition',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/xRayEkin_eV'],'comment',' ');
h5create(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/scientaEkin_eV'],...
size(tmpFileList(ij,:).scientaEkin_eV{:}));
h5write(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/scientaEkin_eV'],...
tmpFileList(ij,:).scientaEkin_eV{:})
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/scientaEkin_eV'],'label',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/scientaEkin_eV'],'units',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/scientaEkin_eV'],'definition',' ');
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:} '/scientaEkin_eV'],'comment',' ');
% add attributes
tmpCells= []; % create empty array
for ii = 1:size(tmpVariablesToBeAdded,2)
if matches(class(tmpFileList.(tmpVariablesToBeAdded{ii})),'cell')
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:}],tmpVariablesToBeAdded{ii},tmpFileList(ij,:).(tmpVariablesToBeAdded{ii}){:});
tmpCells = [tmpCells,', ' tmpVariablesToBeAdded{ii}];
else
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:}],tmpVariablesToBeAdded{ii},tmpFileList(ij,:).(tmpVariablesToBeAdded{ii}));
end
% write variables that were cells to a list; so upon import the
% variable type can be set again.
h5writeatt(tmpFileName,['/' tmpTopGroupName '/' tmpFileList(ij,:).name{:}],'matlabVariablesThatAreCells',tmpCells);
end
clearvars tmpCells
end
disp('*************************************************')
disp('* Voila: HDF file(s) written *')
disp('*************************************************')
-473
View File
@@ -1,473 +0,0 @@
function [map,num,typ,scheme] = brewermap(N,scheme)
% The complete selection of ColorBrewer colorschemes/palettes (RGB colormaps).
%
% Returns an RGB colormap from Cynthia Brewer's ColorBrewer 2.0 palettes,
% intended for mapping and plots with attractive, distinguishable colors.
%
%%% Basic Syntax %%%
%
% brewermap() % print summary
% map = brewermap(N,scheme)
%
%%% Preset Syntax %%%
%
% old = brewermap(scheme)
% map = brewermap()
% map = brewermap(N)
%
% [...,num,typ] = brewermap(...)
%
%% Colorschemes %%
%
% This product includes color specifications and designs developed by Cynthia Brewer.
% See the ColorBrewer website for further information about each colorscheme,
% colour-blind suitability, licensing, and citations: http://colorbrewer.org/
% Each colorscheme is defined by a set of hand-picked RGB values (nodes).
%
% To reverse the colormap sequence prefix the colorscheme name with '-'.
%
% Diverging | Qualitative | Sequential
% ----------|-------------|------------------
% BrBG | Accent | Blues PuBuGn
% PiYG | Dark2 | BuGn PuRd
% PRGn | Paired | BuPu Purples
% PuOr | Pastel1 | GnBu RdPu
% RdBu | Pastel2 | Greens Reds
% RdGy | Set1 | Greys YlGn
% RdYlBu | Set2 | OrRd YlGnBu
% RdYlGn | Set3 | Oranges YlOrBr
% Spectral | | PuBu YlOrRd
%
% If <N> is greater than the requested colorscheme's defining nodes then:
% - Diverging and Sequential colorschemes are interpolated.
% - Qualitative colorschemes repeat the nodes (i.e. just like LINES does).
% Else:
% - Exact values from the ColorBrewer colorschemes are returned.
%
%% Examples %%
%
%%% New colors for the COLORMAP example %%%
%
% >> S = load('spine');
% >> image(S.X)
% >> colormap(brewermap([],"YlGnBu"))
%
%%% New colors for the SURF example %%%
%
% >> [X,Y,Z] = peaks(30);
% >> surfc(X,Y,Z)
% >> colormap(brewermap([],'RdYlGn'))
% >> axis([-3,3,-3,3,-10,5])
%
%%% Plot a colorscheme's RGB values %%%
%
% >> rgbplot(brewermap(NaN, '+Blues')) % standard
% >> rgbplot(brewermap(NaN, '-Blues')) % reversed
%
%%% View information about a colorscheme %%%
%
% >> [~,num,typ] = brewermap(NaN,'Paired')
% num = 12
% typ = 'Qualitative'
%
%%% Multi-line plot using matrices %%%
%
% >> N = 6;
% >> axes('ColorOrder',brewermap(N,'Pastel2'),'NextPlot','replacechildren')
% >> X = linspace(0,pi*3,1000);
% >> Y = bsxfun(@(x,n)n*sin(x+2*n*pi/N), X(:), 1:N);
% >> plot(X,Y, 'linewidth',4)
%
%%% Multi-line plot in a loop %%%
%
% set(0,'DefaultAxesColorOrder',brewermap(NaN,'Accent'))
% N = 6;
% X = linspace(0,pi*3,1000);
% Y = bsxfun(@(x,n)n*sin(x+2*n*pi/N), X(:), 1:N);
% for n = 1:N
% plot(X(:),Y(:,n), 'linewidth',4);
% hold all
% end
%
%% Input Arguments (**=default) %%
%
% N = NumericScalar, N>=0, an integer to specify the colormap length.
% = []**, map has the same length as MATLAB's inbuilt colormap functions.
% = NaN, map is exactly the defining RGB nodes (useful for line ColorOrder).
% scheme = CharRowVector or StringScalar, a ColorBrewer colorscheme name.
%
%% Output Arguments %%
%
% map = NumericMatrix, size Nx3, a colormap of RGB values between 0 and 1.
% num = NumericVector, the number of nodes defining the ColorBrewer colorscheme.
% typ = CharRowVector, the colorscheme type: 'Diverging'/'Qualitative'/'Sequential'.
%
%% Dependencies %%
%
% * MATLAB R2009a or later.
%
% See also BREWERMAP_NODES BREWERMAP_VIEW PRESET_COLORMAP CUBEHELIX MAXDISTCOLOR
% LBMAP PARULA LINES RGBPLOT COLORMAP COLORBAR PLOT PLOT3 AXES SET CONTOURF
persistent bmc scm txt
%
if isempty(bmc)
bmc = bmStruct();
end
%
%% Input Wrangling %%
%
if nargin==0
N = [];
end
%
err = 'First input <N> must be a real positive scalar numeric or [] or NaN.';
%
if nargout==0 && nargin==0
hdr = { 'Type'; 'Scheme'; 'Nodes'};
tsn = [{bmc.typ};{bmc.str};{bmc.num}];
fprintf('%-12s %-9s %s\n',hdr{:});
fprintf('%-12s %-9s %u\n',tsn{:});
return
elseif isnumeric(N)
if isequal(N,[])
% Default N is the same as MATLAB colormaps:
N = cmDefaultN();
else
assert(isscalar(N),...
'SC:brewermap:N:NotScalarNumeric',err)
assert(isnan(N) || isreal(N)&&isfinite(N)&&fix(N)==N&&N>=0,...
'SC:brewermap:N:NotWholeRealNotNaN',err)
N = double(N);
end
if nargin<2
assert(~isempty(scm),...
'SC:colorbrewer:scheme:NotPreset',...
'Colorscheme must be preset before this call: BREWERMAP(SCHEME)')
scheme = scm;
else
scheme = bm1s2c(scheme);
assert(ischar(scheme)&&ndims(scheme)==2&&size(scheme,1)==1,...
'SC:brewermap:scheme:NotText',...
'Input <scheme> must be a character vector or a string scalar.') %#ok<ISMAT>
end
else % preset
assert(nargin<2,...
'SC:brewermap:WrongArgumentNumber',...
'If calling with two inputs then the 1st input must be numeric.')
scheme = bm1s2c(N);
assert(ischar(scheme)&&ndims(scheme)==2&&size(scheme,1)==1,...
'SC:brewermap:N:NotText',...
'To preset: the scheme must be a character vector or a string scalar.') %#ok<ISMAT>
if strcmpi(scheme,'list')
map = {bmc.str};
num = [bmc.num];
typ = {bmc.typ};
return
end
end
%
isr = strncmp(scheme,'-',1) || strncmp(scheme,'*',1);
isd = strncmp(scheme,'+',1) || isr; % direction
ids = strcmpi(scheme(1+isd:end),{bmc.str});
assert(any(ids),...
'SC:brewermap:scheme:UnknownColorscheme',...
'Unknown colorscheme name: "%s"',scheme)
%
num = bmc(ids).num;
typ = bmc(ids).typ;
%
if ~isnumeric(N) % preset
map = txt;
txt = N;
scm = scheme;
return
elseif N==0
map = nan(0,3);
return
elseif isnan(N)
N = num;
end
%
% Downsample:
[idx,itp] = bmIndex(N,num,typ);
%
map = bmc(ids).rgb(idx,:)/255;
%
% Interpolate:
if itp
%
% Extrapolate a small amount beyond the end nodes:
%ido = linspace(0,num+1,N+2);
%ido = ido(2:end-1);
% Interpolation completely within the end nodes:
ido = linspace(1,num,N);
%
switch typ
case 'Diverging'
mid = ceil(num/2);
idl = 1:mid;
idr = mid:num;
map = [...
interp1(idl,map(idl,:),ido(ido<=mid),'pchip');...
interp1(idr,map(idr,:),ido(ido>mid),'pchip')];
case 'Sequential'
map = interp1(1:num,map,ido,'pchip');
otherwise
error('SC:brewermap:Interp:UnknownType','Unknown colorscheme type.')
end
%
end
%
% Limit output range:
map = max(0,min(1,map));
%
% Reverse row order:
if isr
map = map(end:-1:1,:);
end
%
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%brewermap
function N = cmDefaultN()
% Get the colormap size from the current figure or default colormap.
try
F = get(groot,'CurrentFigure');
catch %#ok<CTCH> pre HG2
N = size(get(gcf,'colormap'),1);
return
end
if isempty(F)
N = size(get(groot,'DefaultFigureColormap'),1);
else
N = size(F.Colormap,1);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%cmDefaultN
function arr = bm1s2c(arr)
% If scalar string then extract the character vector, otherwise data is unchanged.
if isa(arr,'string') && isscalar(arr)
arr = arr{1};
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%bm1s2c
function [idx,itp] = bmIndex(N,num,typ)
% Ensure exactly the same colors as the online ColorBrewer colorschemes.
%
switch typ
case 'Qualitative'
itp = false;
idx = 1+mod(0:N-1,num);
case 'Diverging'
itp = N>num;
switch N
case 1 % extrapolated
idx = 8;
case 2 % extrapolated
idx = [4,12];
case 3
idx = [5,8,11];
case 4
idx = [3,6,10,13];
case 5
idx = [3,6,8,10,13];
case 6
idx = [2,5,7,9,11,14];
case 7
idx = [2,5,7,8,9,11,14];
case 8
idx = [2,4,6,7,9,10,12,14];
case 9
idx = [2,4,6,7,8,9,10,12,14];
case 10
idx = [1,2,4,6,7,9,10,12,14,15];
otherwise
idx = [1,2,4,6,7,8,9,10,12,14,15];
end
case 'Sequential'
itp = N>num;
switch N
case 1 % extrapolated
idx = 6;
case 2 % extrapolated
idx = [4,8];
case 3
idx = [3,6,9];
case 4
idx = [2,5,7,10];
case 5
idx = [2,5,7,9,11];
case 6
idx = [2,4,6,7,9,11];
case 7
idx = [2,4,6,7,8,10,12];
case 8
idx = [1,3,4,6,7,8,10,12];
otherwise
idx = [1,3,4,6,7,8,10,11,13];
end
otherwise
error('SC:brewermap:Index:UnknownType','Unknown colorscheme type.')
end
%
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%bmIndex
function bmc = bmStruct()
% Return a structure of all colorschemes: name, scheme type, RGB values, number of nodes.
% Order: sorted first by <typ>, then case-insensitive sorted by <str>.
bmc(35).str = 'YlOrRd';
bmc(35).typ = 'Sequential';
bmc(35).rgb = [255,255,204;255,255,178;255,237,160;254,217,118;254,204,92;254,178,76;253,141,60;252,78,42;240,59,32;227,26,28;189,0,38;177,0,38;128,0,38];
bmc(34).str = 'YlOrBr';
bmc(34).typ = 'Sequential';
bmc(34).rgb = [255,255,229;255,255,212;255,247,188;254,227,145;254,217,142;254,196,79;254,153,41;236,112,20;217,95,14;204,76,2;153,52,4;140,45,4;102,37,6];
bmc(33).str = 'YlGnBu';
bmc(33).typ = 'Sequential';
bmc(33).rgb = [255,255,217;255,255,204;237,248,177;199,233,180;161,218,180;127,205,187;65,182,196;29,145,192;44,127,184;34,94,168;37,52,148;12,44,132;8,29,88];
bmc(32).str = 'YlGn';
bmc(32).typ = 'Sequential';
bmc(32).rgb = [255,255,229;255,255,204;247,252,185;217,240,163;194,230,153;173,221,142;120,198,121;65,171,93;49,163,84;35,132,67;0,104,55;0,90,50;0,69,41];
bmc(31).str = 'Reds';
bmc(31).typ = 'Sequential';
bmc(31).rgb = [255,245,240;254,229,217;254,224,210;252,187,161;252,174,145;252,146,114;251,106,74;239,59,44;222,45,38;203,24,29;165,15,21;153,0,13;103,0,13];
bmc(30).str = 'RdPu';
bmc(30).typ = 'Sequential';
bmc(30).rgb = [255,247,243;254,235,226;253,224,221;252,197,192;251,180,185;250,159,181;247,104,161;221,52,151;197,27,138;174,1,126;122,1,119;122,1,119;73,0,106];
bmc(29).str = 'Purples';
bmc(29).typ = 'Sequential';
bmc(29).rgb = [252,251,253;242,240,247;239,237,245;218,218,235;203,201,226;188,189,220;158,154,200;128,125,186;117,107,177;106,81,163;84,39,143;74,20,134;63,0,125];
bmc(28).str = 'PuRd';
bmc(28).typ = 'Sequential';
bmc(28).rgb = [247,244,249;241,238,246;231,225,239;212,185,218;215,181,216;201,148,199;223,101,176;231,41,138;221,28,119;206,18,86;152,0,67;145,0,63;103,0,31];
bmc(27).str = 'PuBuGn';
bmc(27).typ = 'Sequential';
bmc(27).rgb = [255,247,251;246,239,247;236,226,240;208,209,230;189,201,225;166,189,219;103,169,207;54,144,192;28,144,153;2,129,138;1,108,89;1,100,80;1,70,54];
bmc(26).str = 'PuBu';
bmc(26).typ = 'Sequential';
bmc(26).rgb = [255,247,251;241,238,246;236,231,242;208,209,230;189,201,225;166,189,219;116,169,207;54,144,192;43,140,190;5,112,176;4,90,141;3,78,123;2,56,88];
bmc(25).str = 'Oranges';
bmc(25).typ = 'Sequential';
bmc(25).rgb = [255,245,235;254,237,222;254,230,206;253,208,162;253,190,133;253,174,107;253,141,60;241,105,19;230,85,13;217,72,1;166,54,3;140,45,4;127,39,4];
bmc(24).str = 'OrRd';
bmc(24).typ = 'Sequential';
bmc(24).rgb = [255,247,236;254,240,217;254,232,200;253,212,158;253,204,138;253,187,132;252,141,89;239,101,72;227,74,51;215,48,31;179,0,0;153,0,0;127,0,0];
bmc(23).str = 'Greys';
bmc(23).typ = 'Sequential';
bmc(23).rgb = [255,255,255;247,247,247;240,240,240;217,217,217;204,204,204;189,189,189;150,150,150;115,115,115;99,99,99;82,82,82;37,37,37;37,37,37;0,0,0];
bmc(22).str = 'Greens';
bmc(22).typ = 'Sequential';
bmc(22).rgb = [247,252,245;237,248,233;229,245,224;199,233,192;186,228,179;161,217,155;116,196,118;65,171,93;49,163,84;35,139,69;0,109,44;0,90,50;0,68,27];
bmc(21).str = 'GnBu';
bmc(21).typ = 'Sequential';
bmc(21).rgb = [247,252,240;240,249,232;224,243,219;204,235,197;186,228,188;168,221,181;123,204,196;78,179,211;67,162,202;43,140,190;8,104,172;8,88,158;8,64,129];
bmc(20).str = 'BuPu';
bmc(20).typ = 'Sequential';
bmc(20).rgb = [247,252,253;237,248,251;224,236,244;191,211,230;179,205,227;158,188,218;140,150,198;140,107,177;136,86,167;136,65,157;129,15,124;110,1,107;77,0,75];
bmc(19).str = 'BuGn';
bmc(19).typ = 'Sequential';
bmc(19).rgb = [247,252,253;237,248,251;229,245,249;204,236,230;178,226,226;153,216,201;102,194,164;65,174,118;44,162,95;35,139,69;0,109,44;0,88,36;0,68,27];
bmc(18).str = 'Blues';
bmc(18).typ = 'Sequential';
bmc(18).rgb = [247,251,255;239,243,255;222,235,247;198,219,239;189,215,231;158,202,225;107,174,214;66,146,198;49,130,189;33,113,181;8,81,156;8,69,148;8,48,107];
bmc(17).str = 'Set3';
bmc(17).typ = 'Qualitative';
bmc(17).rgb = [141,211,199;255,255,179;190,186,218;251,128,114;128,177,211;253,180,98;179,222,105;252,205,229;217,217,217;188,128,189;204,235,197;255,237,111];
bmc(16).str = 'Set2';
bmc(16).typ = 'Qualitative';
bmc(16).rgb = [102,194,165;252,141,98;141,160,203;231,138,195;166,216,84;255,217,47;229,196,148;179,179,179];
bmc(15).str = 'Set1';
bmc(15).typ = 'Qualitative';
bmc(15).rgb = [228,26,28;55,126,184;77,175,74;152,78,163;255,127,0;255,255,51;166,86,40;247,129,191;153,153,153];
bmc(14).str = 'Pastel2';
bmc(14).typ = 'Qualitative';
bmc(14).rgb = [179,226,205;253,205,172;203,213,232;244,202,228;230,245,201;255,242,174;241,226,204;204,204,204];
bmc(13).str = 'Pastel1';
bmc(13).typ = 'Qualitative';
bmc(13).rgb = [251,180,174;179,205,227;204,235,197;222,203,228;254,217,166;255,255,204;229,216,189;253,218,236;242,242,242];
bmc(12).str = 'Paired';
bmc(12).typ = 'Qualitative';
bmc(12).rgb = [166,206,227;31,120,180;178,223,138;51,160,44;251,154,153;227,26,28;253,191,111;255,127,0;202,178,214;106,61,154;255,255,153;177,89,40];
bmc(11).str = 'Dark2';
bmc(11).typ = 'Qualitative';
bmc(11).rgb = [27,158,119;217,95,2;117,112,179;231,41,138;102,166,30;230,171,2;166,118,29;102,102,102];
bmc(10).str = 'Accent';
bmc(10).typ = 'Qualitative';
bmc(10).rgb = [127,201,127;190,174,212;253,192,134;255,255,153;56,108,176;240,2,127;191,91,23;102,102,102];
bmc(09).str = 'Spectral';
bmc(09).typ = 'Diverging';
bmc(09).rgb = [158,1,66;213,62,79;215,25,28;244,109,67;252,141,89;253,174,97;254,224,139;255,255,191;230,245,152;171,221,164;153,213,148;102,194,165;43,131,186;50,136,189;94,79,162];
bmc(08).str = 'RdYlGn';
bmc(08).typ = 'Diverging';
bmc(08).rgb = [165,0,38;215,48,39;215,25,28;244,109,67;252,141,89;253,174,97;254,224,139;255,255,191;217,239,139;166,217,106;145,207,96;102,189,99;26,150,65;26,152,80;0,104,55];
bmc(07).str = 'RdYlBu';
bmc(07).typ = 'Diverging';
bmc(07).rgb = [165,0,38;215,48,39;215,25,28;244,109,67;252,141,89;253,174,97;254,224,144;255,255,191;224,243,248;171,217,233;145,191,219;116,173,209;44,123,182;69,117,180;49,54,149];
bmc(06).str = 'RdGy';
bmc(06).typ = 'Diverging';
bmc(06).rgb = [103,0,31;178,24,43;202,0,32;214,96,77;239,138,98;244,165,130;253,219,199;255,255,255;224,224,224;186,186,186;153,153,153;135,135,135;64,64,64;77,77,77;26,26,26];
bmc(05).str = 'RdBu';
bmc(05).typ = 'Diverging';
bmc(05).rgb = [103,0,31;178,24,43;202,0,32;214,96,77;239,138,98;244,165,130;253,219,199;247,247,247;209,229,240;146,197,222;103,169,207;67,147,195;5,113,176;33,102,172;5,48,97];
bmc(04).str = 'PuOr';
bmc(04).typ = 'Diverging';
bmc(04).rgb = [127,59,8;179,88,6;230,97,1;224,130,20;241,163,64;253,184,99;254,224,182;247,247,247;216,218,235;178,171,210;153,142,195;128,115,172;94,60,153;84,39,136;45,0,75];
bmc(03).str = 'PRGn';
bmc(03).typ = 'Diverging';
bmc(03).rgb = [64,0,75;118,42,131;123,50,148;153,112,171;175,141,195;194,165,207;231,212,232;247,247,247;217,240,211;166,219,160;127,191,123;90,174,97;0,136,55;27,120,55;0,68,27];
bmc(02).str = 'PiYG';
bmc(02).typ = 'Diverging';
bmc(02).rgb = [142,1,82;197,27,125;208,28,139;222,119,174;233,163,201;241,182,218;253,224,239;247,247,247;230,245,208;184,225,134;161,215,106;127,188,65;77,172,38;77,146,33;39,100,25];
bmc(01).str = 'BrBG';
bmc(01).typ = 'Diverging';
bmc(01).rgb = [84,48,5;140,81,10;166,97,26;191,129,45;216,179,101;223,194,125;246,232,195;245,245,245;199,234,229;128,205,193;90,180,172;53,151,143;1,133,113;1,102,94;0,60,48];
% Number of nodes:
for k = 1:numel(bmc)
switch bmc(k).typ
case 'Diverging'
bmc(k).num = 11;
case 'Qualitative'
bmc(k).num = size(bmc(k).rgb,1);
case 'Sequential'
bmc(k).num = 9;
otherwise
error('SC:brewermap:Struct:UnknownType','Unknown colorscheme type.')
end
end
%
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%bmStruct
%
% Code and Implementation:
% Copyright (c) 2014-2025 Stephen Cobeldick
% Color Values Only:
% Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania State University.
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and limitations under the License.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions as source code must retain the above copyright notice, this
% list of conditions and the following disclaimer.
%
% 2. The end-user documentation included with the redistribution, if any, must
% include the following acknowledgment: "This product includes color
% specifications and designs developed by Cynthia Brewer
% (http://colorbrewer.org/)." Alternately, this acknowledgment may appear in the
% software itself, if and wherever such third-party acknowledgments normally appear.
%
% 4. The name "ColorBrewer" must not be used to endorse or promote products
% derived from this software without prior written permission. For written
% permission, please contact Cynthia Brewer at cbrewer@psu.edu.
%
% 5. Products derived from this software may not be called "ColorBrewer", nor
% may "ColorBrewer" appear in their name, without prior written permission of Cynthia Brewer.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%license
-63
View File
@@ -1,63 +0,0 @@
function brewermap_nodes()
% Create a figure showing all ColorBrewer 2.0 colorschemes' defining nodes.
%
% (c) 2014-2025 Stephen Cobeldick
%
% View Cynthia Brewer's ColorBrewer 2.0 colorschemes/palettes in a figure:
%
% * Each row of the figure shows the defining nodes for one colorscheme.
% * Text with all colorschemes' names.
% * Text with all colorschemes' types (Diverging/Qualitative/Sequential).
%
%%% Syntax %%%
%
% brewermap_nodes()
%
%% Dependencies %%
%
% * MATLAB R2009a or later.
% * brewermap.m <www.mathworks.com/matlabcentral/fileexchange/45208>
%
% See also BREWERMAP BREWERMAP_VIEW CUBEHELIX MAXDISTCOLOR
% LBMAP PARULA LINES RGBPLOT COLORMAP COLORBAR PLOT PLOT3 AXES SET
persistent cbh axh
%
[mcs,nmn,pyt] = brewermap('list');
%
xmx = max(nmn);
ymx = numel(pyt);
%
if ishghandle(cbh)
figure(cbh);
delete(axh);
else
cbh = figure('HandleVisibility','callback', 'IntegerHandle','off',...
'NumberTitle','off', 'Name',mfilename,...
'MenuBar','figure', 'Toolbar','none', 'Tag',mfilename);
set(cbh,'Units','pixels')
pos = get(cbh,'Position');
pos(1:2) = pos(1:2) - 123;
pos(3:4) = max(pos(3:4),[842,532]);
set(cbh,'Position',pos)
end
%
axh = axes('Parent',cbh, 'Color','none',...
'XTick',0:xmx, 'YTick',0.5:ymx, 'YTickLabel',mcs, 'YDir','reverse');
title(axh,'ColorBrewer Color Schemes (brewermap.m)', 'Interpreter','none')
xlabel(axh,'Scheme Nodes')
ylabel(axh,'Scheme Name')
axf = get(axh,'FontName');
%
for y = 1:ymx
N = nmn(y);
M = brewermap(N,mcs{y});
for x = 1:N
patch([x-1,x-1,x,x],[y-1,y,y,y-1],1, 'FaceColor',M(x,:), 'Parent',axh)
end
text(xmx+0.1,y-0.5,pyt{y}, 'Parent',axh, 'FontName',axf)
end
%
drawnow()
%
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%brewermap_nodes
-408
View File
@@ -1,408 +0,0 @@
function [map,num,typ,scheme] = brewermap_view(N,scheme,isco)
% Create an interactive figure for viewing ColorBrewer colormaps. With demo!
%
% (c) 2014-2025 Stephen Cobeldick
%
% View Cynthia Brewer's ColorBrewer 2.0 colorschemes/palettes in a figure:
%
% * Two colorbars give the colorscheme in color and grayscale.
% * A button toggles between 3D-cube and 2D-lineplot of the RGB values.
% * A button toggles an endless demo cycle through the colorschemes.
% * A button reverses the colormap.
% * Thirty-five buttons select any ColorBrewer colorscheme.
% * Text with the colorscheme's type (Diverging/Qualitative/Sequential).
% * Text with the colorscheme's number of nodes (i.e. defining colors).
%
%%% Syntax %%%
%
% brewermap_view
% brewermap_view(N)
% brewermap_view(N,scheme)
% brewermap_view(N,scheme,isco)
% brewermap_view([],...)
% brewermap_view(axes/figure handle array,...) % see "Adjust Colormaps"
% [map,num,typ] = brewermap_view(...)
%
% Calling the function with an output argument blocks MATLAB execution until
% the figure is deleted: the final colormap and parameters are then returned.
%
%% Adjust Colormaps or Colororders of Figures or Axes %%
%
% For R2014b or later: provide axes or figure handles as the first input
% and their COLORMAP will be updated in real-time by BREWERMAP_VIEW.
% For R2019b or later: set the 3rd input to TRUE to update COLORORDER.
%
% >> S = load('spine');
% >> image(S.X)
% >> brewermap_view(gca) % colormap
%
% >> plot(rand(5,7))
% >> brewermap_view(gca,[],true) % colororder
%
%% Input Arguments (**=default) %%
%
% N = NumericScalar, an integer to define the colormap length.
% = []**, colormap length of two hundred and fifty-six (256).
% = NaN, same length as the defining RGB nodes (useful for Line ColorOrder).
% = Array of axes or figure handles. R2014b or later only.
% scheme = CharRowVector or StringScalar, a ColorBrewer colorscheme name.
% = []** randomly selects a colorscheme.
% isco = LogicalScalar, true/false** updates the colororder/colormap of
% the provided axes or figure handles. R2019b or later only.
%
%% Output Arguments (block code execution until figure is closed) %%
%
% map = NumericMatrix, the colormap defined when the figure is closed.
% num = NumericVector, the number of nodes defining the ColorBrewer colorscheme.
% typ = CharRowVector, the colorscheme type: 'Diverging'/'Qualitative'/'Sequential'.
%
%% Dependencies %%
%
% * MATLAB R2009a or later.
% * brewermap.m <www.mathworks.com/matlabcentral/fileexchange/45208>
%
% See also BREWERMAP BREWERMAP_NODES CUBEHELIX PRESET_COLORMAP MAXDISTCOLOR
% RGBPLOT COLORMAP COLORMAPEDITOR COLORBAR UICONTROL ADDLISTENER
persistent ax2D ln2D ax3D pt3D txtH is2D cbAx cbIm pTxt pSld bEig bGrp bRev scm isr
%
new = isempty(ax2D)||~ishghandle(ax2D);
dfn = 256;
upd = false;
upb = false;
hgv = [];
nmr = dfn;
%
%% Input Wrangling %%
%
if nargin>2 && isco
% >R2019a only!
fnh = @colororder;
else % default
fnh = @colormap;
end
%
err = 'First input <N> must be a real positive scalar numeric or [] or NaN.';
if nargin==0 || isnumeric(N)&&isequal(N,[])
N = dfn;
elseif isnumeric(N)
assert(isscalar(N),'SC:brewermap_view:N:NotScalarNumeric',err)
assert(isreal(N)&&isfinite(N)&&fix(N)==N&&N>0||isnan(N),...
'SC:brewermap_view:N:NotRealPositiveIntegerNorNaN',err)
N = double(N);
elseif all(ishghandle(N(:))) % R2014b or later
assert(all(isgraphics(N(:),'axes')|isgraphics(N(:),'figure')),...
'SC:brewermap_view:N:NotAxesNorFigureHandles',...
'First input <N> may be an array of figure or axes handles.')
hgv = N(:);
nmr = arrayfun(@(h)size(fnh(h),1),hgv);
N = nmr(1);
else
error('SC:brewermap_view:N:UnsupportedInput',err)
end
%
[mcs,nmn,pyt] = brewermap('list');
%
% Check BREWERMAP output:
tmp = find([any(diff(double(char(pyt)),1),2);1]);
assert(isequal(tmp,[9;17;35]),'SC:brewermap_view:BREWERMAP:OutputOrder',...
'The BREWERMAP function returned an unexpected colorscheme sequence.')
%
if nargin<2 || isnumeric(scheme)&&isequal(scheme,[])
% Default pseudo-random colorscheme:
isr = rand(1)>0.5;
scm = mcs{1+mod(round(now*1e7),numel(mcs))}; %#ok<TNOW1>
else
% Parse input colorscheme:
scheme = bmv1s2c(scheme);
assert(ischar(scheme) && ndims(scheme)==2 && size(scheme,1)==1,...
'SC:brewermap_view:scheme:NotCharacterVector',...
'Second input <scheme> must be a 1xN char vector.') %#ok<ISMAT>
% Check if a reversed colormap was requested:
isr = strncmp(scheme,'-',1) || strncmp(scheme,'*',1);
isd = strncmp(scheme,'+',1) || isr;
scm = scheme(1+isd:end);
end
%
if isnan(N)
N = nmn(strcmpi(scm,mcs));
end
%
%% Ensure Figure Exists %%
%
% LHS and RHS slider bounds/limits, and slider step sizes:
lbd = 1;
rbd = dfn;
stp = [1,10]; % [minor,major]
%
% Define the 3D cube axis order:
xyz = 'RGB'; % specify the order here.
[~,xyz] = ismember(xyz,'RGB');
%
if new % Create a new figure.
%
% Figure parameters:
M = 9; % buttons per column
gap = 0.01; % gaps
bth = 0.04; % demo button height
btw = 0.10; % demo button width
bgh = 0.40; % button group height
cbw = 0.23; % colorbar width (both together)
cbh = 1-3*gap-bth; % colorbar height
axh = 1-bgh-2*gap; % axes height
axw = 1-cbw-2*gap; % axes width
bgw = axw-btw-gap; % button group width
%
figH = figure('HandleVisibility','callback',...
'IntegerHandle','off', 'NumberTitle','off', 'Units','normalized',...
'Name','ColorBrewer Interactive ColorScheme Selector',...
'MenuBar','figure', 'Toolbar','none', 'Tag',mfilename);
%
% Add 2D lineplot:
ax2D = axes('Parent',figH, 'Position',[gap,bgh+gap,axw,axh], 'Box','on',...
'ColorOrder',[1,0,0; 0,1,0; 0,0,1; 0.6,0.6,0.6], 'HitTest','off',...
'Visible','off', 'XLim',[0,1], 'YLim',[0,1], 'XTick',[], 'YTick',[]);
ln2D = line([0,0,0,0;1,1,1,1],[0,0,0,0;1,1,1,1], 'Parent',ax2D,...
'Visible','off', 'Linestyle','-', 'Marker','.');
%
% Add 3D scatterplot:
ax3D = axes('Parent',figH, 'OuterPosition',[0,bgh,axw+2*gap,1-bgh],...
'Visible','on', 'XLim',[0,1], 'YLim',[0,1], 'ZLim',[0,1], 'HitTest','on');
pt3D = patch('Parent',ax3D, 'XData',[0;1], 'YData',[0;1], 'ZData',[0;1],...
'Visible','on', 'LineStyle','none', 'FaceColor','none', 'MarkerEdgeColor','none',...
'Marker','o', 'MarkerFaceColor','flat', 'MarkerSize',10, 'FaceVertexCData',[1,1,0;1,0,1]);
view(ax3D,3);
grid(ax3D,'on')
lbl = {'Red','Green','Blue'};
xlabel(ax3D,lbl{xyz(1)})
ylabel(ax3D,lbl{xyz(2)})
zlabel(ax3D,lbl{xyz(3)})
%
% Add warning text:
txtH = text('Parent',ax2D, 'Units','normalized', 'Position',[1,1],...
'HorizontalAlignment','right', 'VerticalAlignment','top');
%
% Add demo button:
demo = uicontrol(figH, 'Style','togglebutton', 'Units','normalized',...
'Position',[1-cbw/2,1-bth-gap,cbw/2-gap,bth], 'String','Demo',...
'Max',1, 'Min',0, 'Callback',@bmvDemo); %#ok<NASGU>
% Add 2D/3D button:
is2D = uicontrol(figH, 'Style','togglebutton', 'Units','normalized',...
'Position',[1-cbw/1,1-bth-gap,cbw/2-gap,bth], 'String','2D / 3D',...
'Max',1, 'Min',0, 'Callback',@bmv2D3D);
% Add reverse button:
bRev = uicontrol(figH, 'Style','togglebutton', 'Units','normalized',...
'Position',[bgw+2*gap,bgh-bth,btw,bth], 'String','Reverse',...
'Max',1, 'Min',0, 'Callback',@bmvRevM);
%
% Add colorbars:
C(1,1,:) = [1,1,1];
cbAx(2) = axes('Parent',figH, 'Visible','off', 'Units','normalized',...
'Position',[1-cbw/2,gap,cbw/2-gap,cbh], 'YLim',[0.5,1.5],...
'YDir','normal', 'HitTest','off');
cbAx(1) = axes('Parent',figH, 'Visible','off', 'Units','normalized',...
'Position',[1-cbw/1,gap,cbw/2-gap,cbh], 'YLim',[0.5,1.5],...
'YDir','normal', 'HitTest','off');
cbIm(2) = image('Parent',cbAx(2), 'CData',C);
cbIm(1) = image('Parent',cbAx(1), 'CData',C);
%
% Add parameter sliders, listeners, and corresponding text:
sv = mean([lbd,rbd],2);
pTxt = uicontrol(figH,'Style','text', 'Units','normalized',...
'Position',[bgw+2*gap,bgh-2*bth-gap,btw,bth], 'String','X');
pSld = uicontrol(figH,'Style','slider', 'Units','normalized',...
'Position',[bgw+2*gap,gap,btw,bgh-2*bth-gap], 'Min',lbd(1), 'Max',rbd(1),...
'SliderStep',stp(1,:)/(rbd(1)-lbd(1)), 'Value',sv(1));
addlistener(pSld, 'Value', 'PostSet',@bmvSldr);
%
% Add colorscheme button group:
bGrp = uibuttongroup('Parent',figH, 'BorderType','none', ...
'Units','normalized', 'Position',[gap,gap,bgw,bgh-gap]);
% Determine button locations:
Z = 1:numel(mcs);
Z = Z+(Z>17);
C = (ceil(Z/M)-1)/4;
R = (M-1-mod(Z-1,M))/M;
% Add colorscheme buttons to group:
for jj = numel(mcs):-1:1
bEig(jj) = uicontrol('Parent',bGrp, 'Style','Toggle', 'String',mcs{jj},...
'Unit','normalized', 'Position',[C(jj),R(jj),1/4,1/M]);
end
set(bGrp,'SelectionChangeFcn',@bmvChgS);
%
end
%
%% Nested Functions %%
%
function str = bmvName()
% Generate the colorscheme name.
pfx = '+-';
ids = strcmpi(scm,mcs);
if any(ids)
str = [pfx(1+isr),mcs{ids}];
else % will throw an error in BREWERMAP:
str = scm;
end
end
%
function bmvUpDt()
% Update all graphics objects in the figure.
%
% Get ColorBrewer colormap and grayscale equivalent:
[map,num,typ] = brewermap(N,bmvName());
mag = map*[0.298936;0.587043;0.114021];
%
% Update colorbar values:
set(cbAx, 'YLim',[0,abs(N)+(N==0)]+0.5);
set(cbIm(1), 'CData',reshape(map,[],1,3))
set(cbIm(2), 'CData', repmat(mag,[1,1,3]))
%
% Update 2D line / 3D patch values:
if get(is2D, 'Value')
set(ln2D, 'XData',linspace(0,1,abs(N)));
set(ln2D,{'YData'},num2cell([map,mag],1).');
else % 3D
set(pt3D,...
'XData',map(:,xyz(1)),...
'YData',map(:,xyz(2)),...
'ZData',map(:,xyz(3)),...
'FaceVertexCData',map)
end
%
% Update reverse button:
set(bRev, 'Value',isr)
%
% Update warning text:
str = {[bmvName(),' '];[typ,' '];sprintf('%d Nodes ',num)};
set(txtH,'String',str);
%
% Update parameter value text:
set(pTxt(1), 'String',sprintf('N = %.0f',N));
%
% Update external axes/figure colormaps/colororders:
nmr(1) = N;
for k = 1:numel(hgv)
fnh(hgv(k),brewermap(nmr(k),bmvName()));
end
%
drawnow()
end
%
function bmv2D3D(h,~)
% Switch between 2D-line and 3D-cube representation.
%
if get(h,'Value') % 2D
set(ax3D, 'HitTest','off', 'Visible','off')
set(ax2D, 'HitTest','on', 'Visible','on')
set(pt3D, 'Visible','off')
set(ln2D, 'Visible','on')
else % 3D
set(ax2D, 'HitTest','off', 'Visible','off')
set(ax3D, 'HitTest','on', 'Visible','on')
set(ln2D, 'Visible','off')
set(pt3D, 'Visible','on')
end
%
bmvUpDt();
end
%
function bmvChgS(~,e)
% Change the colorscheme.
%
scm = get(e.NewValue,'String');
%
bmvUpDt()
end
%
function bmvRevM(h,~)
% Reverse the colormap.
%
isr = logical(get(h,'Value'));
%
bmvUpDt()
end
%
function bmvSldr(~,~)
% Update the slider position.
%
if ~upd
return
end
%
N = round(get(pSld,'Value'));
%
bmvUpDt()
end
%
function bmvDemo(h,~)
% Display all ColorBrewer colorschemes sequentially.
%
cnt = 0;
while ishghandle(h)&&get(h,'Value')
cnt = mod(cnt+1,pow2(53));
%
if mod(cnt,23)<1
ids = 1+mod(find(strcmpi(scm,mcs)),numel(mcs));
scm = mcs{ids};
try %#ok<TRYNC>
set(bGrp, 'SelectedObject',bEig(ids));
end
end
%
if mod(cnt,69)<1
isr = ~isr;
end
%
upb = (upb || N<=1) && N<dfn;
N = N - 1 + 2*upb;
%
% Update slider position:
upd = false;
try %#ok<TRYNC>
set(pSld, 'Value',N)
bmvUpDt()
end
upd = true;
%
% Faster/slower:
pause(0.1);
end
%
end
%
%% Initialize the Figure %%
%
set(bGrp,'SelectedObject',bEig(strcmpi(scm,mcs)));
set(pSld,'Value',max(lbd,min(rbd,N)));
upd = true;
bmvUpDt()
%
if nargout
waitfor(ax2D);
scheme = bmvName();
else
clear map
end
%
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%brewermap_view
function arr = bmv1s2c(arr)
% If scalar string then extract the character vector, otherwise data is unchanged.
if isa(arr,'string') && isscalar(arr)
arr = arr{1};
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%bmv1s2c
%
% Copyright (c) 2014-2025 Stephen Cobeldick
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and limitations under the License.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%license
+20
View File
@@ -0,0 +1,20 @@
import sys
input_path = '/Users/bartels-rausch/Documents/GitLab/functionsMatlab/beamtime/nappFileList.m'
output_path = '/Users/bartels-rausch/Documents/GitLab/functionsMatlab/beamtime/nappFileList_clean.m'
try:
with open(input_path, 'rb') as f:
content = f.read()
# Try decoding as utf-8, replace errors
text = content.decode('utf-8', errors='replace')
with open(output_path, 'w', encoding='utf-8') as f:
f.write(text)
print(f"Successfully cleaned file to {output_path}")
except Exception as e:
print(f"Error: {e}")
-831
View File
@@ -1,831 +0,0 @@
function distFig(varargin)
% ===== Syntax ============================================================
% distFig(...,'Screen',Value)
% distFig(...,'Position',Value)
%
% distFig(...,'Rows',Value)
% distFig(...,'Columns',Value)
%
% distFig(...,'Not',Value)
% distFig(...,'Only',Value)
% distFig(...,'Offset',Value)
%
% distFig(...,'Adjust',Value)
% distFig(...,'Extra',Value)
% distFig(...,'Menu',Value)
% distFig(...,'Transpose',Value)
% distFig(...,'Simulink',Value)
% distFig(...,'Tight',Value)
% distFig(...,'Scale',Value)
% distFig(...,'ScaleOrigin',Value)
% distFig(...,'FreezeSize',Value)
% distFig(...,'Order',Value)
%
% ===== Description =======================================================
% distFig(...,'Screen',Value) assigns where the figures will be
% distributed.
% Synonyms for 'Screen' are 'Scr' and 'S'. Value can be:
% 'C' / 'Center' (Default)
% 'W' / 'West' / 'L' / 'Left'
% 'E' / 'East' / 'R' / 'Right'
% 'N' / 'North' / 'T' / 'Top'
% 'S' / 'South' / 'B' / 'Bottom'
% 'Main' / 'Primary'
% 'Ext' / 'External' / 'Secondary'
%
% distFig(...,'Position',Value) assigns in which part of the screen the
% figures will be distributed.
% Synonyms for 'Position' are 'Pos' and 'P'. Value can be:
% 'C' / 'Center' (Default)
% 'W' / 'West' / 'L' / 'Left'
% 'E' / 'East' / 'R' / 'Right'
% 'N' / 'North' / 'T' / 'Top'
% 'S' / 'South' / 'B' / 'Bottom'
% 'NW'
% 'NE'
% 'SW'
% 'SE'
%
% distFig(...,'Rows',Value) assigns how many rows the figures will be
% distributed on.
% Synonyms for 'Rows' are 'R'. Value can be:
% 1...n
% 'Auto' / -1
% 'Auto' indicates that it automatically calculates the number of required
% rows.
%
% distFig(...,'Columns',Value) assigns how many rows the figures will be
% distributed on.
% Synonyms for 'Columns' are 'Cols' and 'C'. Value can be:
% 1...n
% 'Auto' / -1
% 'Auto' indicates that it automatically calculates the number of required
% columns.
%
% distFig(...,'Not',Value) excludes specified figures from the distribution
% list. Value must be an array with the excluded figure numbers. The
% default value is []. The input argument 'gcf' (get current figure) can be
% used as well.
%
% distFig(...,'Only',Value) does only distribute specified figures. Value
% must be an array with the figure which will be distributed. The
% default value is []. The input argument 'gcf' (get current figure) can be
% used as well.
%
% distFig(...,'Offset',Value) can be used to shift all figures on the
% distribution list. Synonyms for 'Offset' is 'O'. Value must be an integer
% larger or equal to zero. The default offset value is 0.
%
% distFig(...,'Adjust',Value) can be used to adjust all figure positions.
% For instance, if all figures should be moved 20 pixels to the right,
% which is not possible with the other features, Value should be [20,0].
% If Value is below 1, the scalars indicate the relative adjustment to the
% screen. If the selected monitor is [1920,1080] pixels, a Values of
% [0.25,-0.5] moves all figures with [480,540] pixels.
% Synonyms for 'Ajust' is 'A'. Value can be:
% [Integer,Integer] (In order to adjust by a specific ammount)
% [Scalar,Scalar]( < 1) (To adjust a relative ammount of the monitor size)
% The default value is [0,0].
%
% distFig(...,'Extra',Value) is used to handle the extra figures, which
% might not fit into 'Rows' * 'Cols'. For instance, 5 figure are to be
% distributed on a 2x2 = 4 area. The fifth figure is then places on top of
% the first figure if 'Extra' is 'restart'. It can be ignored by setting
% 'Extra' to 'ignore', in which the fifth figure will not be distributed.
%
% distFig(...,'Menu',Value) can be used to modify the menu bar.
% Value can be:
% 'figure'
% 'none'
%
% distFig(...,'Transpose',Value) can be used to tranpose the order of
% distributing. The values must be logical and the default value is false.
%
% distFig(...,'Simulink',Value) can be used to handle simulink figures.
% Value can be:
% 'include' (Default)
% 'exclude'
% 'only'
% If value is true, simulink figures will be distributed along with the
% other figures. If value if 'exclude' simulink figures will be
% excluded from the distribution list. If value is 'only', only the
% simulink figures will be distributed and not the ordinary figures.
%
% distFig(...,'Tight',Value) can be used to stretch the figure to the
% border of the figure, so no unnecessary "whitespace" is present.
% Value must be logical and the default value if false.
%
% distFig(...,'Scale',Value) can be used to scale the figure matrix. Both
% horizontal and vertical scaling can be applied, but also similar scaling.
% Value is a single scalar for similar scaling, but is a 2x1 matrix for
% specific scaling in each direction. For instance, distFig('Scale',0.5)
% scales all figures by 50% relative to the upper left corner of the
% distribution area (Default Scale-origin). distFig('Scale',[0.8,0.4])
% scales the figures by 80% and 40% in the horizontal and vertical
% directions respectivly relative to the default scale-origin.
%
% distFig(...,'ScaleOrigin',Value) can be used in combination with the
% 'Scale' option. Value is a 2x1 matrix with the origin. If these values
% are between 0 and 1 the relative monitor size is used, whereas larger
% values should be rounded indicating pixel values. For instance,
% distFig('Scale',0.5,'ScaleOrigin',[0.5,1]) scales the figures relative
% to the midpoint on the right hand side of the selected monitor. For a
% monitor with resolution 1920x1080, this would be equal to
% distFig('Scale',0.5,'ScaleOrigin',[1920,960]).
% The default scale origin is in the upper left corner of the distribution
% area.
% Synonyms for 'ScaleOrigin' are 'Origin', 'Orig' and 'Scaleorig'.
%
% distFig(...,'FreezeSize',Value) can be used to freeze the sizes of the
% figures before distribution. Currently, this function anchors the figures
% to the upper left corner of the original position, yet keeping the
% original size - it does not calculate new positions, so the figures may
% overlap.
% Synonym for 'FreezeSize' is 'Freeze'.
%
% distFig(...,'Order',Value) can be used to control the plotting order. For
% instance, distFig('Only',[5,6,7,8],'Order',[2,1,4,3]) will plot figure
% 5,6,7 and 8 in the order of 6,5,8 and 7. The ordering argument is thus
% related to the input of 'Only'.
%
% ===== Examples ==========================================================
% distFig();
% This will distribute all open figures on the primary screen in two rows.
%
% distFig('Screen','Left','Position','Right','Only',[1,2,4])
% This will only distribute figure 1, 2 and 4 on the right part of the left
% screen.
%
% distFig('Offset',2,'Not',[1,2])
% This will distribute all figure but figure 1 and 2 in the same pattern as
% distFig(), but figure 1 and 2 will not be distributed, but instead there will
% be blank spots where they would have been distributed.
%
% ===== Note ==============================================================
% If you find any errors or bugs with this version please contact me on
% AndersSSimonsen@GMail.com or write a comment on file exchange - then I'll
% take a look at it. :)
%
% This function will only work in MATLAB 2014b and onwards due to the
% massive overhaul in the figure handle system - I will not support
% previous versions.
% =========================================================================
% ===== Version ===========================================================
% =========================================================================
% Anders Schou Simonsen, AndersSSimonsen@GMail.com
% Version 5.5
% 31/03-2015
% =========================================================================
% ===== Default values ====================================================
% =========================================================================
Rows = -1;
Cols = -1;
Scr = 'C';
Pos = 'C';
Tight = false;
Menu = '';
Transpose = false;
Extra = 'restart';
Offset = 0;
Not = [];
Only = [];
Simulink = 'include';
Adjust = [0,0];
Scale = 1;
Scale_Orig = [];
FreezeSize = false;
Order = [];
% =========================================================================
% ===== Get inputs ========================================================
% =========================================================================
if (mod(nargin,2) ~= 0)
error('Uneven number of inputs! Returning...');
end
for i = 1:2:nargin
if (ischar(varargin{i+1}))
varargin{i+1} = lower(varargin{i+1});
end
switch lower(varargin{i})
case {'scr','screen','s'}
% =============================================================
Allow = {
'C' 'c' 'center' 'main' 'primary'
'W' 'w' 'west' 'l' 'left'
'E' 'e' 'east' 'r' 'right'
'N' 'n' 'north' 't' 'top'
'S' 's' 'south' 'b' 'bottom'
'Ext' 'ext' 'external' 'secondary' NaN
};
Trigger = any(strcmp(Allow,varargin{i+1}),2);
if (~any(Trigger))
warning('Input ''%s'' not recognized for ''%s''!',varargin{i+1},varargin{i});
else
Scr = Allow{Trigger,1};
end
case {'pos','position','p'}
% =============================================================
Allow = {
'C' 'c' 'center' NaN NaN
'W' 'w' 'west' 'l' 'left'
'E' 'e' 'east' 'r' 'right'
'N' 'n' 'north' 't' 'top'
'S' 's' 'south' 'b' 'bottom'
'NW' 'nw' NaN NaN NaN
'NE' 'ne' NaN NaN NaN
'SW' 'sw' NaN NaN NaN
'SE' 'se' NaN NaN NaN
};
Trigger = any(strcmp(Allow,varargin{i+1}),2);
if (~any(Trigger))
warning('Input ''%s'' not recognized for ''%s''!',varargin{i+1},varargin{i});
else
Pos = Allow{Trigger,1};
end
case {'rows','r'}
% =============================================================
if (strcmp(varargin{i+1},'auto'))
Rows = -1;
else
if ~((isnumeric(varargin{i+1})) && (mod(varargin{i+1},1) == 0))
warning('Input to ''%s'' must be a round numeric value!',varargin{i});
else
Rows = varargin{i+1};
end
end
case {'cols','columns','c'}
% =============================================================
if (strcmp(varargin{i+1},'auto'))
Cols = -1;
else
if ~((isnumeric(varargin{i+1})) && (mod(varargin{i+1},1) == 0))
warning('Input to ''%s'' must be a round numeric value!',varargin{i});
else
Cols = varargin{i+1};
end
end
case {'ext','extra'}
% =============================================================
Allow = {
'ignore'
'restart'
};
Trigger = any(strcmp(Allow,varargin{i+1}),2);
if (~any(Trigger))
warning('Input ''%s'' not recognized for ''%s''!',varargin{i+1},varargin{i});
else
Extra = Allow{Trigger,1};
end
case {'menu','bar'}
% =============================================================
Allow = {
'figure'
'none'
};
Trigger = any(strcmp(Allow,varargin{i+1}),2);
if (~any(Trigger))
warning('Input ''%s'' not recognized for ''%s''!',varargin{i+1},varargin{i});
else
Menu = Allow{Trigger,1};
end
case {'transpose'}
% =============================================================
if (~islogical(varargin{i+1}))
warning('Input to ''%s'' must be logical!',varargin{i});
else
Transpose = varargin{i+1};
end
case {'offset','o'}
% =============================================================
if ~((isnumeric(varargin{i+1})) && (mod(varargin{i+1},1) == 0))
warning('Input to ''%s'' must be a round numeric value!',varargin{i});
else
Offset = varargin{i+1};
end
case {'adjust','a'}
% =============================================================
if ~(isnumeric(varargin{i+1}))
warning('Input to ''%s'' must be numeric!',varargin{i});
elseif (numel(varargin{i+1}) ~= 2)
warning('Input to ''%s'' must be a (1 x 2) matrix with integers or scalars less than one!',varargin{i});
elseif (all(mod(varargin{i+1},1) == 0))
Adjust = varargin{i+1};
else
if (any(varargin{i+1} > 1))
warning('Input to ''%s'' must be either integers or scalars less than one!',varargin{i});
else
Adjust = varargin{i+1};
end
end
case {'not'}
% =============================================================
if ~((isnumeric(varargin{i+1}) && all(mod(varargin{i+1},1) == 0)) || isobject(varargin{i+1}))
warning('Input to ''%s'' must be round numeric values!',varargin{i});
else
if (isobject(varargin{i+1}))
Not = get(varargin{i+1},'Number');
if (iscell(Not))
Not = cell2mat(Not);
end
else
Not = varargin{i+1};
end
end
case {'only'}
% =============================================================
if ~((isnumeric(varargin{i+1}) && all(mod(varargin{i+1},1) == 0)) || isobject(varargin{i+1}))
warning('Input to ''%s'' must be round numeric values!',varargin{i});
else
if (isobject(varargin{i+1}))
Only = get(varargin{i+1},'Number');
if (iscell(Only))
Only = cell2mat(Only);
end
else
Only = varargin{i+1};
end
end
case {'simu','simulink'}
% =============================================================
Allow = {
'include' NaN
'exclude' 'ignore'
'only' NaN
};
Trigger = any(strcmp(Allow,varargin{i+1}),2);
if (~any(Trigger))
warning('Input ''%s'' not recognized for ''%s''!',varargin{i+1},varargin{i});
else
Simulink = Allow{Trigger,1};
end
case {'tight'}
% =============================================================
if (~islogical(varargin{i+1}))
warning('Input to ''%s'' must be logical!',varargin{i});
else
Tight = varargin{i+1};
end
case {'scale'}
% =============================================================
if (~isnumeric(varargin{i+1}) || (numel(varargin{i+1}) > 2))
warning('Input to ''%s'' must be one or two numeric values (x and y scale)!',varargin{i});
else
Scale = varargin{i+1};
end
case {'origin','orig','scaleorig','scaleorigin'}
% =============================================================
if (~isnumeric(varargin{i+1}) || (numel(varargin{i+1}) ~= 2))
warning('Input to ''%s'' must be two numeric values (x0 and y0)!',varargin{i});
else
Scale_Orig = varargin{i+1};
end
case {'freezesize','freeze'}
% =============================================================
if (~islogical(varargin{i+1}))
warning('Input to ''%s'' must be logical!',varargin{i});
else
FreezeSize = varargin{i+1};
end
case {'order'}
% =============================================================
if ~(isnumeric(varargin{i+1}) && all(mod(varargin{i+1},1) == 0))
warning('Input to ''%s'' must be round numeric values!',varargin{i});
else
Order = varargin{i+1};
end
otherwise
% =============================================================
fprintf('Input ''%s'' not recognized!',varargin{i});
end
end
% =========================================================================
% ===== Constants =========================================================
% =========================================================================
% ===== Limits ============================================================
Limits = {...
'C' [0,1] [0,1]
'W' [0,0.5] [0,1]
'E' [0.5,1] [0,1]
'N' [0,1] [0.5,1]
'NW' [0,0.5] [0.5,1]
'NE' [0.5,1] [0.5,1]
'S' [0,1] [0,0.5]
'SW' [0,0.5] [0,0.5]
'SE' [0.5,1] [0,0.5]
};
% ===== Screen angles =====================================================
Screens = {...
(-pi * 1 / 4) (+pi * 1 / 4) 'E'
(-pi * 3 / 4) (-pi * 1 / 4) 'S'
(+pi * 1 / 4) (+pi * 3 / 4) 'N'
(+pi * 3 / 4) Inf 'W'
-Inf (-pi * 3 / 4) 'W'
};
% ===== Taskbar height ====================================================
Taskbar_Height = 40;
% =========================================================================
% ===== Figure list =======================================================
% =========================================================================
% ===== All figures =======================================================
Fig_Object = findall(0,'type','figure');
if (isempty(Fig_Object))
fprintf('distFig: No figures to distribute!\n');
return;
end
% ===== Remove not visible figures ========================================
Visible = arrayfun(@(n) (strcmp(get(Fig_Object(n),'Visible'),'on')),1:numel(Fig_Object));
Fig_Object = Fig_Object(Visible);
% ===== Include simulink figures ==========================================
Fig_Number = {Fig_Object.Number};
Empty = arrayfun(@(n) (isempty(Fig_Number{n})),1:numel(Fig_Number));
Fig_Number(Empty) = {0};
Fig_Number = cell2mat(Fig_Number);
[~,Index] = sort(get(Fig_Object(Fig_Number == 0),'Name'));
Temp = find(Fig_Number == 0);
Fig_Number(Temp(Index)) = -(numel(Index):(-1):1);
% ===== Logical distribution array ========================================
Fig_Dist = true(1,numel(Fig_Object));
% ===== Simulink figures ==================================================
if strcmp(Simulink,'exclude')
Fig_Dist = (Fig_Number > 0);
end
if strcmp(Simulink,'only')
Fig_Dist = (Fig_Number < 0);
end
% ===== Not ===============================================================
Fig_Dist(ismember(Fig_Number,Not)) = false;
% ===== Only ==============================================================
if (~isempty(Only))
Fig_Dist(~ismember(Fig_Number,Only)) = false;
end
% ===== Number of figures =================================================
nFig_Dist = sum(Fig_Dist);
% ===== Return ============================================================
if (nFig_Dist == 0)
return;
end
% =========================================================================
% ===== Monitor ===========================================================
% =========================================================================
% ===== Get monitor positions =============================================
Monitors = get(0,'MonitorPositions');
Monitors_Center = Monitors(:,1:2) + Monitors(:,3:4) / 2;
Monitors_Label = cell(size(Monitors,1),1);
% ===== Center monitor ====================================================
Temp = sum(abs(Monitors(:,1:2) - 1),2);
Trigger_C = find(Temp == min(Temp));
Monitors_Label{Trigger_C} = 'C';
% ===== External monitors =================================================
Dir = Monitors_Center - repmat(Monitors_Center(Trigger_C,:),size(Monitors_Center,1),1);
Theta = atan2(Dir(:,2),Dir(:,1));
for i = 1:numel(Theta)
if (i ~= Trigger_C)
Monitors_Label{i} = Screens{(Theta(i) > [Screens{:,1}]) & (Theta(i) <= [Screens{:,2}]),3};
end
end
% ===== Select monitor ====================================================
Monitor = Monitors(strcmp(Monitors_Label,Scr),:);
if (isempty(Monitor))
if (strcmp(Scr,'Ext'))
if (size(Monitors,1) == 1)
warning('No external monitor could be found!');
Monitor = Monitors(1,:);
else
Monitor = Monitors(find(~strcmp(Monitors_Label,'C'),1,'first'),:);
end
else
warning(['Screen ''%s'' could not be found! (Using ''C'' instead)\nThe following monitors were identified: %s.\n'...
'If the function cannot find the monitor try and restart MATLAB - this will reset the monitor-matrix, which is being used by the function.'],...
Scr,sprintf('%s\b\b\b\b\b',sprintf('''%s'' and ',Monitors_Label{:})));
Monitor = Monitors(strcmp(Monitors_Label,'C'),:);
if (isempty(Monitor))
warning(['distFig cannot find matching monitors - using the first one!',...
'\nPlease report this problem to AndersSSimonsen@GMail.com, where you include this matrix:'],0);
disp(Monitors);
Monitor = Monitors(1,:);
end
end
end
% =========================================================================
% ===== Rows and columns ==================================================
% =========================================================================
Limit = Limits(strcmp(Limits(:,1),Pos),:);
if ((Rows == (-1)) && (Cols == (-1)))
AR_Ideal = 1.2;
AR_Mean = Inf;
for i = 1:50
% ===== Exception =================================================
if ((nFig_Dist + Offset) == 4)
Rows = 2;
Cols = 2;
break;
end
% ===== Temporary rows and columns ================================
Rows = i;
Cols = ceil((nFig_Dist + Offset) / Rows);
% ===== Sizes =====================================================
x = round(linspace(Limit{2}(1),Limit{2}(2),Cols + 1) * Monitor(3)) + 1;
y = round(linspace(Limit{3}(1),Limit{3}(2),Rows + 1) * (Monitor(4) - Taskbar_Height)) + Taskbar_Height + 1;
clear Size;
[Size(:,:,1),Size(:,:,2)] = meshgrid(diff(x),diff(y));
% ===== Output ====================================================
AR_Mean_Prev = AR_Mean;
AR_Mean = mean(mean(Size(:,:,1) ./ Size(:,:,2)));
if (AR_Mean > AR_Ideal)
AR_Error = abs([AR_Ideal - AR_Mean_Prev,AR_Ideal - AR_Mean]);
if (AR_Error(1) < AR_Error(2))
Rows = i - 1;
end
Cols = ceil((nFig_Dist + Offset) / Rows);
clear Size;
break;
end
end
elseif (Rows == (-1))
Rows = ceil((nFig_Dist + Offset) / Cols);
elseif (Cols == (-1))
Cols = ceil((nFig_Dist + Offset) / Rows);
end
% =========================================================================
% ===== Location matrix ===================================================
% =========================================================================
Sets = ceil(nFig_Dist / (Rows * Cols) + Offset);
Mat = nan(Rows,Cols,Sets);
if (Transpose)
Mat = permute(Mat,[2,1,3]);
end
if (isempty(Order))
Order = (1:sum(Fig_Dist));
end
Temp = sort(Fig_Number(Fig_Dist));
if (max(Order) > numel(Temp))
error('The ordering command is related to the input - not the actual figure numbers! Returning...');
end
Mat((1:nFig_Dist) + Offset) = Temp(Order);
if (Transpose)
Mat = permute(Mat,[2,1,3]);
end
if (strcmp(Extra,'ignore'))
Sets = 1;
end
% =========================================================================
% ===== Position and size =================================================
% =========================================================================
% ===== Grid ==============================================================
x = round(linspace(Limit{2}(1),Limit{2}(2),Cols + 1) * Monitor(3)) + 1;
y = round(linspace(Limit{3}(1),Limit{3}(2),Rows + 1) * (Monitor(4) - Taskbar_Height)) + Taskbar_Height + 1;
% ===== Scale =============================================================
if (isempty(Scale_Orig))
Scale_Orig = [x(1),y(end)];
end
if ((all(mod(Scale_Orig,1) == 0)) && (any(Scale_Orig > 1)))
ScaleOrig_Pixel = Scale_Orig;
else
ScaleOrig_Pixel = Monitor(3:4) .* Scale_Orig;
end
if (numel(Scale) == 1)
Scale(2) = Scale(1);
end
x = (x - ScaleOrig_Pixel(1)) * Scale(1) + ScaleOrig_Pixel(1);
y = (y - ScaleOrig_Pixel(2)) * Scale(2) + ScaleOrig_Pixel(2);
% ===== Positon ===========================================================
[FPos(:,:,1),FPos(:,:,2)] = meshgrid(x(1:end-1),y(1:end-1));
FPos(:,:,2) = flipud(FPos(:,:,2));
FPos(:,:,1) = FPos(:,:,1) + Monitor(1) - 1;
FPos(:,:,2) = FPos(:,:,2) + Monitor(2) - 1;
% ===== Size ==============================================================
[Size(:,:,1),Size(:,:,2)] = meshgrid(diff(x),diff(y));
% ===== Adjust ============================================================
if (any(Adjust ~= 0))
if (all(mod(Adjust,1) == 0))
Adjust_Pixels = Adjust;
else
Adjust_Pixels = round(Adjust .* (Monitor(3:4) + [0,-Taskbar_Height]));
end
else
Adjust_Pixels = [0,0];
end
% =========================================================================
% ===== Distribute figures ================================================
% =========================================================================
for s = 1:Sets
for i = 1:size(Mat,1)
for j = 1:size(Mat,2)
if (~isnan(Mat(i,j,s)))
% ===== Position and figure ===============================
Pos_Temp = [squeeze(FPos(i,j,:))' + Adjust_Pixels,squeeze(Size(i,j,:))'];
gcf_Temp = Fig_Object(Fig_Number == Mat(i,j,s));
gca_Temp = get(gcf_Temp,'CurrentAxes');
% ===== Freeze size =======================================
if (FreezeSize)
Pos_Orig = get(gcf_Temp,'Position');
Pos_Temp(2) = Pos_Temp(2) + Pos_Temp(4) - Pos_Orig(4);
Pos_Temp(3:4) = Pos_Orig(3:4);
end
% ===== Focus figures to bring to front ===================
figure(gcf_Temp);
% ===== Set units =========================================
if (~isempty(Menu))
set(gcf_Temp,'MenuBar',Menu);
end
if (Mat(i,j,s) < 0)
drawnow;
end
gca_Units_Prev = get(gca_Temp,'Units');
gcf_Units_Prev = get(gcf_Temp,'Units');
% ===== Distribute figure =================================
set(gca_Temp,'Units','normalized');
set(gcf_Temp,'Units','pixels','OuterPosition',Pos_Temp);
set(gcf_Temp,'Units',gcf_Units_Prev);
% ===== Apply tight =======================================
if ((Tight) && (Mat(i,j,s) > 0))
drawnow;
set(gca_Temp,'Position',[get(gca_Temp,'TightInset') * eye(4,2),1 - get(gca_Temp,'TightInset') * [1,0,1,0;0,1,0,1]']);
end
set(gca_Temp,'Units',gca_Units_Prev);
end
end
end
end
% =========================================================================
% ===== Check for new updates =============================================
% =========================================================================
% This feature check for a new version of distFig. It is only an attempt,
% so it might not work without bugs. It can be disables by setting the
% variable below called "Update" to "false" or by deleting this whole
% section - this won't affect the rest of the function.
%
% It generates a .txt file called "distFig_Update.txt" located in the same
% folder as distFig.m, which holds the date for the last time the function
% checked for updates. In order to not check for updates all the time, the
% function only does this ONCE every 7 days (variable "Check_Interval"),
% and at max once for every started MATLAB session. Also, it uses appdata,
% so if you're using this as well, it might display messages multiple times
% within a session, if an update is available, if appdata is deleted.
%
% The update feature works by scanning the file exchange page for distFig
% for a string value called "datePublished", and compares it to the date of
% the current version (variable "Date_Current"). If these are not the same,
% a hyperlink will be shown to the function page on file exchange page. It
% thus depends on a very specific format, which might differ(?) from
% different languages - I'm not aware whether this is true, so please
% contact me on AndersSSimonsen@GMail.com if you find this to be true, so I
% can fix the feature. :)
% ===== DISABLE THE UPDATE FEATURE BY SETTING THIS VALUE TO false =========
Update = true;
% ===== DISABLE THE UPDATE FEATURE BY SETTING THIS VALUE TO false =========
if (Update)
try
% ===== Initialize ================================================
Date_Current = [2015,03,31];
Check_Interval = 7;
Check = false;
% ===== Path of update file =======================================
Path = mfilename('fullpath');
Path = sprintf('%s\\distFig_Update.txt',Path(1:end-numel('\distFig')));
if (isempty(getappdata(0,'distFig_Update')))
% ===== Set appdata ===========================================
setappdata(0,'distFig_Update',1);
% ===== Read update file ======================================
File_ID = fopen(Path,'r');
Clock = clock;
Date_Today = Clock(1:3);
if (File_ID == (-1))
% ===== Generate update file ==============================
File_ID = fopen(Path,'w');
fprintf(File_ID,'%d %d %d',Date_Today(1),Date_Today(2),Date_Today(3));
fclose(File_ID);
Check = true;
else
% ===== Read last date ====================================
Data = textscan(File_ID,'%s','delimiter','');
if (strcmp(Data{1},'DISABLE'))
Check = false;
else
Date_Last_Checked = cell2mat(textscan(Data{1}{1},'%f %f %f'));
% ===== Write new date ================================
File_ID = fopen(Path,'w');
fprintf(File_ID,'%d %d %d',Date_Today(1),Date_Today(2),Date_Today(3));
fclose(File_ID);
% ===== Check for new updates? ========================
Days_Elapsed = etime([Date_Today,zeros(1,3)],[Date_Last_Checked,zeros(1,3)]) / (60^2 * 24);
if (Days_Elapsed > Check_Interval)
Check = true;
end
end
end
% ===== Check for updates =====================================
if (Check)
% ===== Read File Exchange date ===========================
Data = urlread('http://se.mathworks.com/matlabcentral/fileexchange/37176-distribute-figures');
Temp = Data((-1:100) + regexp(Data,'datePublished'));
Date_Online = cell2mat(textscan(Temp(26:end),'%f-%f-%f'));
% ===== New update available? =============================
if (~all(Date_Current == Date_Online))
setappdata(0,'distFig_Update',2);
setappdata(0,'distFig_Online_Date',Date_Online);
end
end
end
% ===== Message ===================================================
if (getappdata(0,'distFig_Update') == 2)
try
% ===== New version =======================================
Date_Online = getappdata(0,'distFig_Online_Date');
fprintf('New update available for distFig! ');
disp('<a href = "http://se.mathworks.com/matlabcentral/fileexchange/37176-distribute-figures">Download here</a>')
fprintf('\tCurrent version date:\t%02.0f-%02.0f-%02.0f\n',Date_Current(1),Date_Current(2),Date_Current(3));
fprintf('\tOnline version date:\t%02.0f-%02.0f-%02.0f\n',Date_Online(1),Date_Online(2),Date_Online(3));
% ===== Postpone ==========================================
fprintf('Click here to postpone this message for %d days: ',Check_Interval);
Command = sprintf([...
'setappdata(0,''distFig_Update'',1);',...
'fprintf(''distFig update message postponed for %d days!\\n'');'
],Check_Interval);
disp(sprintf('<a href="matlab:%s">Postpone update message</a>',Command)); %#ok<DSPS>
% ===== Disable ===========================================
fprintf('Click here to disable the update feature forever: ');
Command = sprintf([...
'File_ID = fopen(''%s'',''w'');',...
'fprintf(File_ID,''DISABLE'');',...
'fclose(File_ID);',...
'setappdata(0,''distFig_Update'',1);',...
'fprintf(''distFig update feature disabled!\\n'');'
],Path);
disp(sprintf('<a href="matlab:%s">Disable update feature</a>',Command)); %#ok<DSPS>
catch
setappdata(0,'distFig_Update',1);
end
end
catch Error %#ok<NASGU>
% ===== Error handling ============================================
try
Path_Error = [Path(1:end-numel([filesep 'distFig_Update.txt'])), [filesep 'distFig_Error.mat']];
fprintf([
'There was an error in distFig when checking for updates.',...
'\nPlease report this to AndersSSimonsen@GMail.com by sending the error-file "distFig_Error.mat" located in %s. :)\n\n'],Path_Error);
AppData = getappdata(0); %#ok<NASGU>
save(Path_Error);
catch
end
end
end
File diff suppressed because it is too large. Load diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

-24
View File
@@ -1,24 +0,0 @@
function PsiFarbe = getPsiColors()
% Returns a struct with PSI corporate identity colors.
% 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
-107
View File
@@ -1,107 +0,0 @@
function TableLabViewIss = importLabViewIssfile(filenameOrFolder, dataLines)
%IMPORTFILE Import data from a text file or folder
% TableLabViewIss = IMPORTFILE(FILENAME) reads data from text
% file FILENAME and returns the data as a table.
%
% TableLabViewIss = IMPORTFILE(FOLDER) reads all .txt files from
% FOLDER, merges them into a single table (sorted by datetime).
%
% TableLabViewIss = IMPORTFILE(FILE, DATALINES) reads data
% for the specified row interval(s) of text file FILENAME.
%
% Example (single file):
% TableLabViewIss = importLabViewIssfile("/Users/bartels-rausch/Desktop/17-12-2025_09-14datafile.txt", [2, Inf]);
%
% Example (folder):
% TableLabViewIss = importLabViewIssfile("/Users/bartels-rausch/Desktop/DataFolder");
%
% See also READTABLE.
%% Input handling
% If dataLines is not specified, define defaults
if nargin < 2
dataLines = [2, Inf];
end
%% Check if input is a file or folder
if isfolder(filenameOrFolder)
% Process all .txt files in the folder
folderPath = filenameOrFolder;
fileList = dir(fullfile(folderPath, '*.txt'));
if isempty(fileList)
error('No .txt files found in folder: %s', folderPath);
end
fprintf('Found %d .txt files in folder. Processing...\n', length(fileList));
% Initialize empty table
TableLabViewIss = table();
% Loop through each file
for i = 1:length(fileList)
filepath = fullfile(folderPath, fileList(i).name);
fprintf(' [%d/%d] Processing: %s\n', i, length(fileList), fileList(i).name);
% Import this file
tbl_temp = importSingleFile(filepath, dataLines);
% Append to main table
if isempty(TableLabViewIss)
TableLabViewIss = tbl_temp;
else
TableLabViewIss = [TableLabViewIss; tbl_temp];
end
end
% Sort by datetime
[~, sortIdx] = sort(TableLabViewIss.datetime);
TableLabViewIss = TableLabViewIss(sortIdx, :);
fprintf('Merged %d files into single table with %d rows.\n', length(fileList), height(TableLabViewIss));
else
% Process single file
TableLabViewIss = importSingleFile(filenameOrFolder, dataLines);
end
end
%% Helper function to import a single file
function tbl = importSingleFile(filename, dataLines)
% Import options setup
opts = delimitedTextImportOptions("NumVariables", 10);
% Specify range and delimiter
opts.DataLines = dataLines;
opts.Delimiter = "\t";
% Specify column names and types
opts.VariableNames = ["date_DD_MM_JJJJ_", "time_hh_mm_ss_", "pressure_cell_hPa_", "temperature__C_", "x_mm_", "y_mm_", "z_mm_", "Tsealing__C_", "flowCryo_l_min_", "pOut_hPa_"];
opts.VariableTypes = ["datetime", "duration", "double", "double", "double", "double", "double", "double", "double", "double"];
% Specify file level properties
opts.ExtraColumnsRule = "ignore";
opts.EmptyLineRule = "read";
% Specify variable properties
opts = setvaropts(opts, "date_DD_MM_JJJJ_", "InputFormat", "dd.MM.yyyy");
opts = setvaropts(opts, "time_hh_mm_ss_", "InputFormat", "hh:mm:ss.S");
% Import the data as regular table
tbl = readtable(filename, opts);
% Merge date + time into a single datetime column
tbl.datetime = tbl.date_DD_MM_JJJJ_ + tbl.time_hh_mm_ss_;
% Set the datetime display format to show date and time
tbl.datetime.Format = 'dd.MM.yyyy HH:mm:ss.SSS';
% Remove the original date and time columns
tbl(:, ["date_DD_MM_JJJJ_", "time_hh_mm_ss_"]) = [];
% Move datetime to be the first column
tbl = movevars(tbl, "datetime", "Before", 1);
end
-85
View File
@@ -1,85 +0,0 @@
function Table = outerjoinRowToTable(Table,TableRowToBeAdded)
%outerjoinRowToTable Adds one row to a table. Variables that are missing in
%either the table or the row are added with empty values {' '} for cells
%and NaN for doubles. Works with tables that contain both cells and
%doubles.
%
% * Strings in the table are not yet supported.
% * The row that is added needs to be formatted as table
% * Update 2024: Adds several rows, that is tables
% * Update 2026: Handles peakfitting columns with different size.
%
% T = outerjoinRowToTable(TableToAddTo,RowToBeAdded)
%
% tmpTableToBeAdded = table({tmpCombined(:,1)},{tmpCombined(:,2)},{'660eV, m50, 092022'},{'#288,#289,#290.ibw'}, ...
% 'VariableNames',["bindingEnergy_eV","spectrum_countsNorm","sample","name"]);
% SpectrumList = outerjoinRowToTable(SpectrumList,tmpTableToBeAdded);
%
% Thorsten, December 2023
% Original Table has more variables
if ~all(ismember(Table.Properties.VariableNames,TableRowToBeAdded.Properties.VariableNames))
tmpMissingVariable = ~ismember(Table.Properties.VariableNames,TableRowToBeAdded.Properties.VariableNames);
tmpVariablesToBeAdded = Table.Properties.VariableNames(tmpMissingVariable);
for ii = 1:size(tmpVariablesToBeAdded,2)
if matches(class(Table.(tmpVariablesToBeAdded{ii})),'double') || matches(class(Table.(tmpVariablesToBeAdded{ii})),'int32')
tmpContentToBeAdded = NaN(size(TableRowToBeAdded,1),size(Table.(tmpVariablesToBeAdded{ii}),2));
TableRowToBeAdded = addvars(TableRowToBeAdded,tmpContentToBeAdded,'NewVariableNames',tmpVariablesToBeAdded{ii});
elseif matches(class(Table.(tmpVariablesToBeAdded{ii})),'cell')
tmpContentToBeAdded = repmat({' '},size(TableRowToBeAdded,1),size(Table.(tmpVariablesToBeAdded{ii}),2));
TableRowToBeAdded = addvars(TableRowToBeAdded,tmpContentToBeAdded,'NewVariableNames',tmpVariablesToBeAdded{ii});
elseif matches(class(Table.(tmpVariablesToBeAdded{ii})),'string')
tmpContentToBeAdded = repmat({" "},size(TableRowToBeAdded,1),size(Table.(tmpVariablesToBeAdded{ii}),2));
TableRowToBeAdded = addvars(TableRowToBeAdded,tmpContentToBeAdded,'NewVariableNames',tmpVariablesToBeAdded{ii});
end
end
end
% Table to be added has more variables
if ~all(ismember(TableRowToBeAdded.Properties.VariableNames,Table.Properties.VariableNames))
tmpMissingVariable = ~ismember(TableRowToBeAdded.Properties.VariableNames,Table.Properties.VariableNames);
tmpVariablesToBeAdded = TableRowToBeAdded.Properties.VariableNames(tmpMissingVariable);
for ii = 1:size(tmpVariablesToBeAdded,2)
if matches(class(TableRowToBeAdded.(tmpVariablesToBeAdded{ii})),'double') || matches(class(TableRowToBeAdded.(tmpVariablesToBeAdded{ii})),'int32')
tmpContentToBeAdded = NaN(size(Table,1),size(TableRowToBeAdded.(tmpVariablesToBeAdded{ii}),2));
Table = addvars(Table,tmpContentToBeAdded,'NewVariableNames',tmpVariablesToBeAdded{ii});
elseif matches(class(TableRowToBeAdded.(tmpVariablesToBeAdded{ii})),'cell')
tmpContentToBeAdded = repmat({' '},size(Table,1),size(TableRowToBeAdded.(tmpVariablesToBeAdded{ii}),2));
Table = addvars(Table,tmpContentToBeAdded,'NewVariableNames',tmpVariablesToBeAdded{ii});
elseif matches(class(TableRowToBeAdded.(tmpVariablesToBeAdded{ii})),'string')
tmpContentToBeAdded = repmat({" "},size(Table,1),size(TableRowToBeAdded.(tmpVariablesToBeAdded{ii}),2));
Table = addvars(Table,tmpContentToBeAdded,'NewVariableNames',tmpVariablesToBeAdded{ii});
end
end
end
% Reconcile column widths for peak-fit columns.
% These numeric columns can have variable width (one entry per peak),
% so a width mismatch is expected when spectra have different numbers
% of peaks. Pad the narrower side with NaN.
variableWidthColumns = {'peakArea', 'peakPosition', 'peakFWHM', ...
'peakBackground', 'peakEta', 'peakShirleyK'};
for ii = 1:numel(variableWidthColumns)
varName = variableWidthColumns{ii};
if ~ismember(varName, Table.Properties.VariableNames) || ...
~ismember(varName, TableRowToBeAdded.Properties.VariableNames)
continue
end
widthT = size(Table.(varName), 2);
widthR = size(TableRowToBeAdded.(varName), 2);
if widthT < widthR
Table.(varName) = [Table.(varName), ...
NaN(height(Table), widthR - widthT)];
elseif widthR < widthT
TableRowToBeAdded.(varName) = [TableRowToBeAdded.(varName), ...
NaN(height(TableRowToBeAdded), widthT - widthR)];
end
end
% Ensure matching column order before concatenation
TableRowToBeAdded = TableRowToBeAdded(:, Table.Properties.VariableNames);
% Add row to table
Table = [Table;TableRowToBeAdded];
end
-151
View File
@@ -1,151 +0,0 @@
function plotExportedData(dataDirectory)
%plotExportedData Plot all exported ASCII data files in one figure
%
% This function reads all .txt files from the exported data (created by
% exportFigureData) and plots them in a single figure for visual comparison.
% File names are parsed to extract axis labels and legend entries.
%
% SYNTAX:
% plotExportedData() % Uses current working directory
% plotExportedData(dataDirectory) % Uses specified directory path
%
% INPUTS:
% dataDirectory : char or string (optional)
% Path to directory containing exported .txt files.
% If omitted, uses current working directory (pwd).
%
% OUTPUT:
% A new figure with all data plotted as lines. Axis labels and legend
% entries are reconstructed from the file names.
%
% NOTES:
% - Reads all .txt files in the specified directory
% - File name format expected: <FigureTitle>_[<TileTitle>_]<YLabel>_vs_<XLabel>_<LineLabel>.txt
% - Plots are created with underscores converted back to spaces for display
% - X and Y axis labels are set based on parsed filename
% - Legend shows line labels from filenames
% - All data is plotted in a single axes for direct visual comparison
%
% EXAMPLE:
% % After running exportFigureData():
% plotExportedData()
% % or
% plotExportedData('../exported_data/')
% Handle input: use current directory if none provided
if nargin == 0 || isempty(dataDirectory)
dataDirectory = pwd;
end
% Get all .txt files in the directory
fileStruct = dir(fullfile(dataDirectory, '*.txt'));
if isempty(fileStruct)
warning('plotExportedData:NoFiles', 'No .txt files found in %s', dataDirectory);
return;
end
% Create a new figure
fig = figure('Name', 'Exported Data Comparison', 'NumberTitle', 'off');
ax = axes(fig);
hold(ax, 'on');
grid(ax, 'on');
% Storage for axis labels (to ensure consistency)
xLabelStr = '';
yLabelStr = '';
legendEntries = {};
% Loop over all .txt files
for ii = 1:length(fileStruct)
fileName = fileStruct(ii).name;
filePath = fullfile(dataDirectory, fileName);
% Read the data
try
data = readmatrix(filePath);
catch ME
warning('plotExportedData:ReadFailed', 'Could not read file: %s\n%s', fileName, ME.message);
continue;
end
% Check if data has at least 2 columns
if size(data, 2) < 2 || size(data, 1) < 1
warning('plotExportedData:InvalidData', 'File %s does not have valid X,Y columns', fileName);
continue;
end
xData = data(:, 1);
yData = data(:, 2);
% Parse filename to extract labels
% Expected format: <FigureTitle>_[<TileTitle>_]<YLabel>_vs_<XLabel>_<LineLabel>.txt
% Remove .txt extension
nameNoExt = fileName(1:end-4);
% Split by '_vs_' to separate y-axis label from the rest
parts = strsplit(nameNoExt, '_vs_');
if length(parts) >= 2
% Extract line label (after _vs_<XLabel>_)
rightPart = parts{2}; % <XLabel>_<LineLabel>
% Find the last underscore to separate XLabel from LineLabel
underscores = find(rightPart == '_');
if ~isempty(underscores)
lastUnderscore = underscores(end);
xLabelExtracted = rightPart(1:lastUnderscore-1);
lineLabel = rightPart(lastUnderscore+1:end);
else
xLabelExtracted = rightPart;
lineLabel = 'data';
end
% Extract y-axis label (before _vs_)
yLabelExtracted = parts{1};
% Remove figure title (first part before first underscore)
% This is tricky, so we'll keep what we have and note it's approximate
% Convert underscores back to spaces for display
xLabelDisplay = strrep(xLabelExtracted, '_', ' ');
yLabelDisplay = strrep(yLabelExtracted, '_', ' ');
lineLabel = strrep(lineLabel, '_', ' ');
% Store axis labels (use the first valid ones found)
if isempty(xLabelStr)
xLabelStr = xLabelDisplay;
end
if isempty(yLabelStr)
yLabelStr = yLabelDisplay;
end
else
% Fallback if filename parsing fails
lineLabel = nameNoExt;
end
% Plot the data
plot(ax, xData, yData, 'DisplayName', lineLabel, 'LineWidth', 1.5, 'Marker', 'o', 'MarkerSize', 4);
% Store legend entry
legendEntries{end+1} = lineLabel;
end
% Set axis labels
xlabel(ax, xLabelStr, 'Interpreter', 'none');
ylabel(ax, yLabelStr, 'Interpreter', 'none');
title(ax, 'Exported Data Comparison', 'Interpreter', 'none');
% Add legend
if ~isempty(legendEntries)
legend(ax, legendEntries, 'Interpreter', 'none', 'Location', 'best');
end
% Optimize figure appearance
grid(ax, 'on');
hold(ax, 'off');
fprintf('Plotted %d data files from: %s\n', length(fileStruct), dataDirectory);
end
-75
View File
@@ -1,75 +0,0 @@
function map = preset_colormap(N,varargin)
% Wrapper for any COLORMAP function, to provide preset parameter values.
%
% (c) 2020-2025 Stephen Cobeldick
%
%%% Syntax %%%
%
% preset_colormap(@fun,p1,p2,...,pN) % store function with any parameters
% map = preset_colormap(N) % generate colormap
% map = preset_colormap % generate colormap
%
%% Examples %%
%
% >> preset_colormap(@cubehelix,0.25,-0.67,1.5,1)
% >> colormap(preset_colormap)
%
% >> preset_colormap(5)
% ans =
% 0 0 0
% 0.1055 0.2788 0.4895
% 0.1660 0.6705 0.4961
% 0.6463 0.8479 0.5076
% 1.0000 1.0000 1.0000
%
% >> preset_colormap(@brewermap,'PuOr')
% >> load topo
% >> load coast
% >> figure
% >> worldmap(topo, topolegend)
% >> contourfm(topo, topolegend);
% >> contourcmap('preset_colormap', 'Colorbar','on', 'Location','horizontal','TitleString','Contour Intervals in Meters');
% >> plotm(lat, long, 'k')
%
%% Dependencies %%
%
% * MATLAB R2009a or later.
%
% See also BREWERMAP CUBEHELIX CMOCEAN LBMAP COLORMAP CONTOURCMAP
persistent fnh arg
%
if nargin==0 % Default N same as MATLAB colormaps.
N = cmDefaultN();
elseif nargin==1 && isnumeric(N)
assert(isscalar(N) && isreal(N) && fix(N)==N,...
'SC:preset_colormap:N:NotRealScalarNumeric',...
'First input <N> must be a real scalar numeric of the colormap size.')
N = double(N);
else % Store function handle and parameter values.
assert(isa(N,'function_handle'),...
'SC:preset_colormap:N:NotFunctionHandle',...
'First input <N> must be a function handle to a colormap function.')
fnh = N;
arg = varargin;
return
end
%
map = fnh(N,arg{:});
%
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%preset_colormap
function N = cmDefaultN()
% Get the colormap size from the current figure or default colormap.
try
F = get(groot,'CurrentFigure');
catch %#ok<CTCH> pre HG2
N = size(get(gcf,'colormap'),1);
return
end
if isempty(F)
N = size(get(groot,'DefaultFigureColormap'),1);
else
N = size(F.Colormap,1);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%cmDefaultN
-52
View File
@@ -1,52 +0,0 @@
function H = readIBWbinheader(FFN);
% readIBWbinheader - read BinHeader segment of Igor IBW file
% H = readIBWbinheader('foo') reads BinHeader of file Foo.ibw
% IBW version 2,5 only
MAXDIMS = 4;
fid = fopen(FFN,'r');
H.version = fread(fid,1,'int16');
switch H.version,
case 2, % typedef struct BinHeader2 {
H.wfmSize = fread(fid,1,'uint32'); % long wfmSize; // The size of the WaveHeader2 data structure plus the wave data plus 16 bytes of padding.
H.noteSize = fread(fid,1,'uint32'); % long noteSize; // The size of the note text.
H.pictSize = fread(fid,1,'uint32'); % long pictSize; // Reserved. Write zero. Ignore on read.
H.checksum = fread(fid,1,'int16'); % short checksum; // Checksum over this header and the wave header.
case 5,
H.checksum = fread(fid,1,'short');
H.wfmSize = fread(fid,1,'long'); % The size of the WaveHeader5 data structure plus the wave data.
H.formulaSize = fread(fid,1,'long'); % The size of the dependency formula, if any.
H.noteSize = fread(fid,1,'long'); % The size of the note text.
H.dataEUnitsSize = fread(fid,1,'long'); % The size of optional extended data units.
H.dimEUnitsSize = fread(fid,MAXDIMS,'long'); % The size of optional extended dimension units.
H.dimLabelsSize = fread(fid,MAXDIMS,'long'); % The size of optional dimension labels.
H.sIndicesSize = fread(fid,1,'long'); ; % The size of string indicies if this is a text wave.
H.optionsSize1 = fread(fid,1,'long'); ; % Reserved. Write zero. Ignore on read.
H.optionsSize2 = fread(fid,1,'long'); ; % Reserved. Write zero. Ignore on read.
otherwise,
end % switch H.Version
fclose(fid);
if ~ismember(H.version,[2 5]),
error(['Cannot read version ' num2str(H.version) ' IBW files - only versions 2,5 are okay.']);
end
%==FROM IgorBin.h =====================
% #define MAXDIMS 4
%
% typedef struct BinHeader5 {
% short version; // Version number for backwards compatibility.
% short checksum; // Checksum over this header and the wave header.
% long wfmSize; // The size of the WaveHeader5 data structure plus the wave data.
% long formulaSize; // The size of the dependency formula, if any.
% long noteSize; // The size of the note text.
% long dataEUnitsSize; // The size of optional extended data units.
% long dimEUnitsSize[MAXDIMS]; // The size of optional extended dimension units.
% long dimLabelsSize[MAXDIMS]; // The size of optional dimension labels.
% long sIndicesSize; // The size of string indicies if this is a text wave.
% long optionsSize1; // Reserved. Write zero. Ignore on read.
% long optionsSize2; // Reserved. Write zero. Ignore on read.
% } BinHeader5;
-250
View File
@@ -1,250 +0,0 @@
function [BH, H, FFN] = readIBWheaders(FFN);
% readIBWheaders - read BinHeader & WaveHeader segments of Igor IBW file
% [BH, WH, FFN] = readIBWheaders('foo') reads BinHeader & WaveHeader of
% file Foo.ibw - Versions 2 and 5 only. FFN is full filename.
% % 1 byte char
% % 2 bytes short
% % 4 bytes int, long, float, Handle, any kind of pointer
% % 8 bytes double
MAXDIMS = 4;
MAX_WAVE_NAME2 = 18; % Maximum length of wave name in version 1 and 2 files. Does not include the trailing null.
MAX_WAVE_NAME5 = 31; % Maximum length of wave name in version 5 files. Does not include the trailing null.
MAX_UNIT_CHARS = 3;
BH = readIBWbinheader(FFN);
fid = fopen(FFN,'r');
switch BH.version
case 2,
% The version 2 file has the following general layout.
% BinHeader2 structure: 16 bytes
% WaveHeader2 structure excluding wData field; 110 bytes
% Wave data: Variable size
fseek(fid,16,'bof'); % start of wave header of IBW vs 2; % struct WaveHeader2 {
H.type = fread(fid,1, 'uint16'); % short type; % See types (e.g. NT_FP64) above. Zero for text waves.
H.WaveHeader2 = fread(fid,1, 'uint32'); % struct WaveHeader2 **next; // Used in memory only. Write zero. Ignore on read.
H.bname = local_char(fread(fid, MAX_WAVE_NAME2+2, 'char')); % char bname[MAX_WAVE_NAME2+2]; // Name of wave plus trailing null.
H.whVersion = fread(fid,1, 'uint16'); % short whVersion; // Write 0. Ignore on read.
H.srcFldr = fread(fid,1, 'uint16'); % short srcFldr; // Used in memory only. Write zero. Ignore on read.
H.fileName = fread(fid,1, 'uint32'); % Handle fileName; // Used in memory only. Write zero. Ignore on read.
%
H.dataUnits = local_char(fread(fid, MAX_UNIT_CHARS+1, 'char')); % char dataUnits[MAX_UNIT_CHARS+1]; // Natural data units go here - null if none.
H.xUnits = local_char(fread(fid, MAX_UNIT_CHARS+1, 'char')); % char xUnits[MAX_UNIT_CHARS+1]; // Natural x-axis units go here - null if none.
%
H.npnts = fread(fid,1, 'uint32'); % long npnts; // Number of data points in wave.
%
H.aModified = fread(fid,1, 'uint16'); % short aModified; // Used in memory only. Write zero. Ignore on read.
H.hsA = fread(fid,1, 'double'); % double hsA,hsB; // X value for point p = hsA*p + hsB
H.hsB = fread(fid,1, 'double'); % double hsA,hsB; // X value for point p = hsA*p + hsB
%
H.wModified = fread(fid,1, 'uint16'); % short wModified; // Used in memory only. Write zero. Ignore on read.
H.swModified = fread(fid,1, 'uint16'); % short swModified; // Used in memory only. Write zero. Ignore on read.
H.fsValid = fread(fid,1, 'uint16'); % short fsValid; // True if full scale values have meaning.
H.topFullScale = fread(fid,1, 'double'); % double topFullScale,botFullScale; // The min full scale value for wave.
H.botFullScale = fread(fid,1, 'double'); % double topFullScale,botFullScale; // The min full scale value for wave.
%
H.useBits = fread(fid,1, 'char'); % char useBits; // Used in memory only. Write zero. Ignore on read.
H.kindBits = fread(fid,1, 'char'); % char kindBits; // Reserved. Write zero. Ignore on read.
H.formula = fread(fid,1, 'uint32'); % void **formula; // Used in memory only. Write zero. Ignore on read.
H.depID = fread(fid,1, 'uint32'); % long depID; // Used in memory only. Write zero. Ignore on read.
H.creationDate = fread(fid,1, '*uint32'); % unsigned long creationDate; // DateTime of creation. Not used in version 1 files.
H.platform = fread(fid,1, 'uint8'); % unsigned char platform; // 0=unspecified, 1=Macintosh, 2=Windows; Added for Igor Pro 5.5.
% dummy = fread(fid,1, 'uint8'); % align
H.wUnused = fread(fid,1, 'uint8'); % char wUnused[1]; // Reserved. Write zero. Ignore on read.
%
H.modDate = fread(fid,1, '*uint32'); % unsigned long modDate; // DateTime of last modification.
H.waveNoteH = fread(fid,1, 'uint32'); % Handle waveNoteH; // Used in memory only. Write zero. Ignore on read.
%
H.wData = fread(fid,4, 'single').'; % float wData[4]; // The start of the array of waveform data.
case 5,
% The version 5 file has the following general layout.
% BinHeader5 structure: 64 bytes
% WaveHeader5 structure excluding wData field: 320 bytes
% Wave data: Variable size
fseek(fid,64,'bof'); % start of wave header of IBW vs 5
%
H.next = fread(fid,1, 'int32'); % link to next wave in linked list.
%
H.creationDate = fread(fid,1, 'uint32'); % DateTime of creation.
H.modDate = fread(fid,1, 'uint32'); % DateTime of creation.
%
H.npnts = fread(fid,1, 'int32'); % Total number of points (multiply dimensions up to first zero).
H.type = fread(fid,1, 'uint16'); % See types (e.g. NT_FP64) above. Zero for text waves.
H.dLock = fread(fid, 1, 'int16'); % Reserved. Write zero. Ignore on read.
%
H.whpad1 = fread(fid, 6, 'char').'; % Reserved. Write zero. Ignore on read.
H.whVersion = fread(fid, 1, 'int16'); % Write 1. Ignore on read.
H.bname = local_char(fread(fid, MAX_WAVE_NAME5+1, 'char')); % Name of wave plus trailing null.
H.whpad2 = fread(fid, 1, 'int32'); % long Reserved. Write zero. Ignore on read.
H.dFolder = fread(fid, 1, 'int32'); % ptr Used in memory only. Write zero. Ignore on read.
% % Dimensioning info. [0] == rows, [1] == cols etc
H.nDim = fread(fid, MAXDIMS, 'int32').'; % long nDim[MAXDIMS] Number of of items in a dimension -- 0 means no data.
H.sfA = fread(fid, MAXDIMS, 'double').'; % double sfA[MAXDIMS]; Index value for element e of dimension d = sfA[d]*e + sfB[d].
H.sfB = fread(fid, MAXDIMS, 'double').'; % double sfB[MAXDIMS];% double sfB[MAXDIMS];
% %
% % % SI units
H.dataUnits = local_char(fread(fid, MAX_UNIT_CHARS+1, 'char')); % char dataUnits[MAX_UNIT_CHARS+1]; % Natural data units go here - null if none.
H.dimUnits = fread(fid, MAXDIMS*(MAX_UNIT_CHARS+1), '*char').'; % % char dimUnits[MAXDIMS][MAX_UNIT_CHARS+1]; % Natural dimension units go here - null if none.
% %
H.fsValid = fread(fid, 1, 'uint16'); % % short fsValid; % TRUE if full scale values have meaning.
H.whpad3 = fread(fid, 1, 'int16'); % % short whpad3; % Reserved. Write zero. Ignore on read.
H.topFullScale = fread(fid, 1, 'double');
H.botFullScale = fread(fid, 1, 'double'); % % double topFullScale,botFullScale; % The max and max full scale value for wave.
% %
H.dataEUnits = fread(fid, 1, 'int32'); % % Handle dataEUnits; % Used in memory only. Write zero. Ignore on read.
H.dimEUnits = fread(fid, MAXDIMS, 'int32').'; % % Handle dimEUnits[MAXDIMS]; % Used in memory only. Write zero. Ignore on read.
H.dimLabels = fread(fid, MAXDIMS, 'int32').'; % % Handle dimLabels[MAXDIMS]; % Used in memory only. Write zero. Ignore on read.
% %
H.waveNoteH = fread(fid, 1, 'int32'); % % Handle waveNoteH; % Used in memory only. Write zero. Ignore on read.
% %
H.platform = fread(fid, 1, 'uint8'); % % unsigned char platform; % 0=unspecified, 1=Macintosh, 2=Windows; Added for Igor Pro 5.
H.skip_junk________ = fread(fid,80,'char').';
% H. = fread(fid, 1, '');
% % unsigned char spare[3];
% H. = fread(fid, 1, '');
% %
% H. = fread(fid, 1, '');
% % long whUnused[13]; % Reserved. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% %
% H. = fread(fid, 1, '');
% % long vRefNum, dirID; % Used in memory only. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% %
% H. = fread(fid, 1, '');
% % % The following stuff is considered private to Igor.
% H. = fread(fid, 1, '');
% %
% H. = fread(fid, 1, '');
% % short aModified; % Used in memory only. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% % short wModified; % Used in memory only. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% % short swModified; % Used in memory only. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% %
% H. = fread(fid, 1, '');
% % char useBits; % Used in memory only. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% % char kindBits; % Reserved. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% % void **formula; % Used in memory only. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% % long depID; % Used in memory only. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% %
% H. = fread(fid, 1, '');
% % short whpad4; % Reserved. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% % short srcFldr; % Used in memory only. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% % Handle fileName; % Used in memory only. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% %
% H. = fread(fid, 1, '');
% % long **sIndices; % Used in memory only. Write zero. Ignore on read.
% H. = fread(fid, 1, '');
% %
H.wData = fread(fid, 1, 'single');
% % float wData[1]; % The start of the array of data. Must be 64 bit aligned.
% H. = fread(fid, 1, '');
% };
end % switch BH.version
H.EOH_pos = ftell(fid);
fclose(fid);
%==FROM IgorBin.h =====================
% #define MAXDIMS 4
% % #define MAX_WAVE_NAME5 31 // Maximum length of wave name in version 5 files. Does not include the trailing null.
% % #define MAX_UNIT_CHARS 3
% % #define NT_CMPLX 1 % Complex numbers.
% % #define NT_FP32 2 % 32 bit fp numbers.
% % #define NT_FP64 4 % 64 bit fp numbers.
% % #define NT_I8 8 % 8 bit signed integer. Requires Igor Pro 2.0 or later.
% % #define NT_I16 0x10 % 16 bit integer numbers. Requires Igor Pro 2.0 or later.
% % #define NT_I32 0x20 % 32 bit integer numbers. Requires Igor Pro 2.0 or later.
% % #define NT_UNSIGNED 0x40 % Makes above signed integers unsigned. Requires Igor Pro 3.0 or later.
%
% struct WaveHeader5 {
% struct WaveHeader5 **next; % link to next wave in linked list.
%
% unsigned long creationDate; % DateTime of creation.
% unsigned long modDate; % DateTime of last modification.
%
% long npnts; % Total number of points (multiply dimensions up to first zero).
% short type; % See types (e.g. NT_FP64) above. Zero for text waves.
% short dLock; % Reserved. Write zero. Ignore on read.
%
% char whpad1[6]; % Reserved. Write zero. Ignore on read.
% short whVersion; % Write 1. Ignore on read.
% char bname[MAX_WAVE_NAME5+1]; % Name of wave plus trailing null.
% long whpad2; % Reserved. Write zero. Ignore on read.
% struct DataFolder **dFolder; % Used in memory only. Write zero. Ignore on read.
%
% % Dimensioning info. [0] == rows, [1] == cols etc
% long nDim[MAXDIMS]; % Number of of items in a dimension -- 0 means no data.
% double sfA[MAXDIMS]; % Index value for element e of dimension d = sfA[d]*e + sfB[d].
% double sfB[MAXDIMS];
%
% % SI units
% char dataUnits[MAX_UNIT_CHARS+1]; % Natural data units go here - null if none.
% char dimUnits[MAXDIMS][MAX_UNIT_CHARS+1]; % Natural dimension units go here - null if none.
%
% short fsValid; % TRUE if full scale values have meaning.
% short whpad3; % Reserved. Write zero. Ignore on read.
% double topFullScale,botFullScale; % The max and max full scale value for wave.
%
% Handle dataEUnits; % Used in memory only. Write zero. Ignore on read.
% Handle dimEUnits[MAXDIMS]; % Used in memory only. Write zero. Ignore on read.
% Handle dimLabels[MAXDIMS]; % Used in memory only. Write zero. Ignore on read.
%
% Handle waveNoteH; % Used in memory only. Write zero. Ignore on read.
%
% unsigned char platform; % 0=unspecified, 1=Macintosh, 2=Windows; Added for Igor Pro 5.5.
% unsigned char spare[3];
%
% long whUnused[13]; % Reserved. Write zero. Ignore on read.
%
% long vRefNum, dirID; % Used in memory only. Write zero. Ignore on read.
%
% % The following stuff is considered private to Igor.
%
% short aModified; % Used in memory only. Write zero. Ignore on read.
% short wModified; % Used in memory only. Write zero. Ignore on read.
% short swModified; % Used in memory only. Write zero. Ignore on read.
%
% char useBits; % Used in memory only. Write zero. Ignore on read.
% char kindBits; % Reserved. Write zero. Ignore on read.
% void **formula; % Used in memory only. Write zero. Ignore on read.
% long depID; % Used in memory only. Write zero. Ignore on read.
%
% short whpad4; % Reserved. Write zero. Ignore on read.
% short srcFldr; % Used in memory only. Write zero. Ignore on read.
% Handle fileName; % Used in memory only. Write zero. Ignore on read.
%
% long **sIndices; % Used in memory only. Write zero. Ignore on read.
%
% float wData[1]; % The start of the array of data. Must be 64 bit aligned.
% };
function s=local_char(S);
% null-terminated string -> char string
S = S(:).';
S = S(S~=0);
s=char(S);
-130
View File
@@ -1,130 +0,0 @@
function output_table = read_hdf5_as_table(filename,exclude_var_set)
% receives a h5 file written with function table2h5.
% reduced_var_set (cell of character_vectors), not usable yet.
% Last update: 14.08.2023
% By: Juan F. Florez Ospina
% Email: juan.florez-ospina@psi.ch
if ~iscellstr(exclude_var_set)
disp("exclude_var_set needs to be a cell of character vectors, e.g, {'var1','var2'} to be excluded.")
disp("To proceed, exclude_var_set was set to {}. So vars will be excluded.")
exclude_var_set = {};
end
INFO = h5info(filename);
num_rows = length(INFO.Groups);
num_attr1 = length(INFO.Groups(1).Datasets);
num_attr2 = length(INFO.Groups(1).Attributes);
num_cols = num_attr1 + num_attr2;
sz = [num_rows,num_cols];
% Extract group level attributes, they align for all
% groups (here denoting measurements/or rows) of the table in filename .h5
group_columns = {INFO.Groups(1).Attributes.Name};
if num_attr1 == 1 && isempty(INFO.Groups(1).Datasets(num_attr1).Attributes)
dataset_columns = {};
num_attr1 = 0;
num_cols = num_cols - 1;
else
for j = 1 : num_attr1
dataset_columns{j} = INFO.Groups(1).Datasets(j).Attributes.Value;
end
end
%TODO: Implement feature to exclude varibales/columns as well as rows at
%reading time. This requires propagating modifications
% % % Select group and dataset columns to be loaded from hdf5 file, which are
% % % those not in the exclude_var_set.
% % if ~isempty(exclude_var_set)
% % for j = 1 : length(exclude_var_set)
% % % keep all vars except exclude_var_set{j}
% % var_filter = ~strcmp(exclude_var_set{j},group_columns);
% % group_columns = group_columns(var_filter);
% % if sum(var_filter) > 0
% % exclude_var_set(j) = [];
% % end
% % end
% %
% % for j = 1 : length(exclude_var_set)
% % % keep all vars except exclude_var_set{j}
% % var_filter = ~strcmp(exclude_var_set{j},dataset_columns);
% % dataset_columns = dataset_columns(var_filter);
% % if sum(var_filter) > 0
% % exclude_var_set(j) = [];
% % end
% % end
% % end
% Construct cell array with table data, where each row denotes a group, and
% the columns are either datasets or attributes in the given group.
tmp = cell(num_rows,num_cols); % {};
idx = [];
group_columns = {};
for i = 1 : num_rows
disp(['Begin construction of row:',INFO.Groups(i).Name])
for j = 1 : num_cols
if j <= num_attr1
ds_name = [INFO.Groups(i).Name '/' INFO.Groups(i).Datasets(j).Name];
%disp(ds_name)
tmp{i,j} = h5read(filename,ds_name);
if i < 2
column_idx = str2double(INFO.Groups(i).Datasets(j).Name(3:end));
idx = [idx,column_idx];
end
end
if j > num_attr1
Name = INFO.Groups(i).Attributes(j-num_attr1).Name;
Datatype = INFO.Groups(i).Attributes(j-num_attr1).Datatype.Class;
% Detect string attributes and convert them to characters.
% TODO: extend to other necessary data types.
if strcmp(Datatype,'H5T_STRING')
convert_func = @(x) convertStringsToChars(x);
else % no data type conversion is performed
convert_func = @(x) x;
end
tmp{i,j} = convert_func(h5readatt(filename,INFO.Groups(i).Name, Name));
if i < 2
disp(Name)
% Split attribute name into column_tag (containing original
% column idx) and column_name
delimiter_idx = find(INFO.Groups(i).Attributes(j-num_attr1).Name=='_');
% Left most '_' determines the split location
delimiter_idx = delimiter_idx(1);
column_idx = str2double(Name(5:delimiter_idx-1));
group_columns = [group_columns,{Name(delimiter_idx+1:end)}];
%disp([Name(5:delimiter_idx-1),'-',column_name])
idx = [idx,column_idx];
end
end
end
disp(['Ends construction of row:',INFO.Groups(i).Name])
end
% Find original ordering of columns by sorting idx in ascending order
[~, idx_perm] = sort(idx,'ascend');
varNames = [dataset_columns,group_columns];
% Create output_table from cell array using cell2table. This as opposed to
% array2table extract the content of its cells, which facilitates filtering
% operations based on table columns/vars.
%output_table = array2table(tmp(:,idx_perm), 'VariableNames', varNames(idx_perm));
output_table = cell2table(tmp(:,idx_perm), 'VariableNames', varNames(idx_perm));
-97
View File
@@ -1,97 +0,0 @@
function tbl = rgaImportData(fullFileName)
%RGAIMPORTDATA Import an SRS RGA "Pressure vs Time" scan (.txt) into a table.
%
% tbl = rgaImportData(fullFileName) reads an RGA ASCII log and returns a
% table ready for plotRgaData, with:
% datetime - absolute time (start time + Time(s))
% time_s - elapsed scan time in seconds
% one column per active channel, named <Name>_m<mass> (e.g. Water_m18),
% holding the partial pressure in the file's units (usually Torr).
%
% The scan units and channel metadata are stored in
% tbl.Properties.VariableUnits and tbl.Properties.UserData.
%
% Two quirks of this file format are handled:
% * multi-word species names in the channel table (e.g. "Carbn dio")
% * adjacent negative values in the data run together with no space
% (e.g. "-2.8663e-010-2.3529e-010"); values are recovered by matching
% scientific-notation tokens rather than by splitting on whitespace.
%
% EXAMPLE
% tbl = rgaImportData('rga1_Jul_01_2026_08-23-06_AM.txt');
% ax = plotRgaData(tbl);
%
% See also PLOTRGADATA, PLOTCRYODATA
lines = readlines(fullFileName); % string array, keeps blanks
%--- Locate the data block header "Time(s) Channel#1 ..." ---
iData = find(startsWith(strip(lines),'Time(s)'), 1);
if isempty(iData)
error('rgaImportData:noData','Could not find the "Time(s)" data header.');
end
header = lines(1:iData-1); % metadata + channel table
%--- Start time (absolute) ---
iStart = find(startsWith(strip(header),'Start time,'), 1);
if isempty(iStart)
startStr = strip(header(1)); % fall back to first line
else
startStr = strip(extractAfter(header(iStart),','));
end
startStr = regexprep(startStr,'\s+',' '); % collapse the double space
startTime = datetime(startStr, ...
'InputFormat','MMM d, yyyy h:mm:ss a', 'Locale','en_US');
%--- Units ---
units = 'a.u.';
iu = find(startsWith(strip(header),'Units,'), 1);
if ~isempty(iu)
p = strip(split(header(iu),','));
units = char(p(end));
end
%--- Channel definitions (e.g. "1 28.00 Nitrogen 1.00 3 OFF") ---
chanPat = '^\s*(\d+)\s+([\d.]+)\s+(.+?)\s+[\d.]+\s+\d+\s+\w+\s*$';
tok = regexp(header, chanPat, 'tokens', 'once');
tok = tok(~cellfun(@isempty, tok));
nCh = numel(tok);
if nCh == 0
error('rgaImportData:noChannels','No channel definitions found.');
end
chMass = zeros(nCh,1); chName = strings(nCh,1);
for k = 1:nCh
chMass(k) = str2double(tok{k}{2});
chName(k) = strip(string(tok{k}{3}));
end
%--- Data: time before the comma + N scientific-notation values ---
dataLines = lines(iData+1:end);
dataLines = dataLines(strlength(strip(dataLines)) > 0);
n = numel(dataLines);
time_s = str2double(extractBefore(dataLines, ','));
matches = regexp(dataLines, '[-+]?\d+\.\d+[eE][-+]?\d+', 'match');
vals = nan(n, nCh);
for r = 1:n
v = str2double(matches{r});
nn = min(numel(v), nCh);
vals(r,1:nn) = v(1:nn);
end
%--- Assemble table ---
dt = startTime + seconds(time_s);
varNames = arrayfun(@(k) matlab.lang.makeValidName( ...
sprintf('%s_m%d', chName(k), round(chMass(k)))), 1:nCh, 'UniformOutput', false);
tbl = table(dt, time_s, 'VariableNames', {'datetime','time_s'});
for k = 1:nCh
tbl.(varNames{k}) = vals(:,k);
end
tbl.Properties.VariableUnits = [{'', 's'}, repmat({char(units)}, 1, nCh)];
tbl.Properties.UserData = struct( ...
'units', char(units), 'startTime', startTime, ...
'channelName', chName, 'channelMass', chMass);
end
-155
View File
@@ -1,155 +0,0 @@
function success = save_table_as_hdf5(input_table, filename)
% This function takes input_table (of table type), structured with
% Thorsten's FileTable format, and stores it as .h5 file with name
% filename. Each row is treated as a group, where columns can be attributes
% of the group or datasets inside the group.
% Last update: 11.08.2023
% By: Juan F. Florez Ospina
% Email: juan.florez-ospina@psi.ch
if istable(input_table)
string_columns = input_table(:,vartype("string")).Properties.VariableNames;
input_table = convertvars(input_table,string_columns,'cellstr');
% split multicolumn variables
input_table = splitvars(input_table);
column_names = input_table.Properties.VariableNames;
else
success = 0;
return
end
% Create array with indices of column_names
column_names_idx = 1 : length(column_names);
% Divide input_table into tables with numeric and cellstr variables/columns
numeric_table = input_table(:,vartype('numeric')); % group attributes of a timestamped measurement
cellstr_table = input_table(:,vartype('cellstr')); % group datasets of a timestamped measurement
% Record columns/vars original index in reference table
numeric_columns = numeric_table.Properties.VariableNames;
numeric_columns_idx = argwhere_var_in_varset(numeric_columns,column_names);
str_columns = cellstr_table.Properties.VariableNames;
str_columns_idx = argwhere_var_in_varset(str_columns,column_names);
% Based on homogeneous columns/cell arrays, we identify the remaining columns
% with possibly heterogeneous entries. Ideally, these should store numeric
% n-dimensional arrays/datasets.
rest_columns = {};
cntr = 1;
for i = 1 : length(input_table.Properties.VariableNames)
variable = input_table.Properties.VariableNames{i};
is_str = sum(strcmp(variable,str_columns))>0;
is_num = sum(strcmp(variable,numeric_columns))>0;
if ~(is_num || is_str)
rest_columns{cntr} = variable;
disp(variable)
cntr = cntr + 1;
end
end
rest_columns_idx = argwhere_var_in_varset(rest_columns,column_names);
% Create an hdf5 file, where rows are seen as measurements/groups with
% attributes given by numeric and str variables and datasets given by the
% remaining variables as long as they are numeric n-dimensional arrays.
cell_table = input_table(:,rest_columns);
[rows, cols] = size(input_table);
for i = 1 : rows
group_name = strcat("/MEAS_",string(i),"/");
if ~isempty(rest_columns)
for j = 1 : length(rest_columns)
dataset_name = strcat("DS",string(rest_columns_idx(j)));
% Some table entries do not provide direct access to the object
% of interest, but may contain either {object} or {{object}}.
% The following loop solves that problem. TODO: is this generic enough?
data = cell_table{i,column_names{rest_columns_idx(j)}}{1}; % <=> data = cell_table{i,rest_columns{j}}{1};
while iscell(data)
data = data{1};
end
% when there is no data, we still need to provide a valid size
if ~isempty(data)
sz = size(data);
else
sz = [1,1];
end
%%%%
% Group's dataset: Create dataset of size sz in a certain group
h5create(filename, strcat(group_name,dataset_name),sz);
% Dataset's attribute: Add attribute with dataset_name equal to column_name
attr = "column_name";
attr_value = column_names{rest_columns_idx(j)}; % <=> rest_columns{j};
h5writeatt(filename,strcat(group_name,dataset_name),attr,attr_value)
%attr = "column_name_idx";
%attr_value = rest_columns_idx(j); % <=> rest_columns{j};
%h5writeatt(filename,strcat(group_name,dataset_name),attr,attr_value)
% Assign 'data' to the dataset. 'data' has to be of admissible type.
try
h5write(filename,strcat(group_name,dataset_name),data)
catch exception
disp(exception)
%h5write(filename,strcat(group_name,dataset_name),cell_table{i,rest_columns{j}})
end
end
else
dataset_name = "DS_EMPTY";
sz = [1,1];
h5create(filename, strcat(group_name,dataset_name),sz);
end
% Group's attribute: Assign group attributes
for attr_idx = 1 : length(numeric_columns)
attr = column_names{numeric_columns_idx(attr_idx)};% <=> attr = numeric_columns{attr_idx};
attr_value = numeric_table{i,attr};
column_idx_tag = ['ATTR',num2str(numeric_columns_idx(attr_idx)),'_'];
h5writeatt(filename,group_name,[column_idx_tag,attr],attr_value)
%attr = "column_name_idx";
%attr_value = numeric_columns_idx(attr_idx); % <=> rest_columns{j};
%h5writeatt(filename,group_name,attr,attr_value)
end
for attr_idx = 1 : length(str_columns)
attr = column_names{str_columns_idx(attr_idx)}; % <=> attr = str_columns{attr_idx}
attr_value = cellstr_table{i,attr};
column_idx_tag = ['ATTR',num2str(str_columns_idx(attr_idx)),'_'];
h5writeatt(filename,group_name,[column_idx_tag,attr],attr_value)
%attr = "column_name_idx";
%attr_value = str_columns_idx(attr_idx); % <=> rest_columns{j};
%h5writeatt(filename,group_name,attr,attr_value)
end
%h5create(filename,"/g2/DS2",[20 Inf],"Chunksize",[5 5]);
end
success = 1;
function idx = argwhere_var_in_varset(var,varset)
ref_idx = 1 : length(varset);
if iscellstr(var)
idx = [];
for i = 1 : length(var)
logical_idx = strcmp(var{i},varset);
idx = [idx,ref_idx(logical_idx)];
end
else
logical_idx = strcmp(var,varset);
idx = ref_idx(logical_idx);
end
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
BIN
View File
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 101 files, more files were not shown because too many files have changed in this diff. Show more