Skip to content

Commit

Permalink
Adding MATLAB scripts for SI and main figures
Browse files Browse the repository at this point in the history
  • Loading branch information
Kipnis Abraham committed Dec 7, 2023
1 parent a238991 commit 7a73f9f
Show file tree
Hide file tree
Showing 21 changed files with 3,489 additions and 0 deletions.
56 changes: 56 additions & 0 deletions AaltoAtoms/MATLAB/Createc data import tools/BiasOffset.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
function [offset] = BiasOffset(options)

arguments
options.file char = 'no'
options.path char = 'no'
end

%BIASOFFSET Check the bias offset of a VERT spectrum
% Call in a loop for several spectra
% Optional name-value pair inputs
% - file: VERT file name
% - path: path to said VERT file
% Output:
% - offset: the bias where the current crosses zero [mV]
%
% NOTE: USE WITH METALS ONLY! Does not work with a gap at Fermi

%% Import the data
% Get a file and path in case it wasn't supplied
if strcmp(options.file, 'no')
[file, path] = uigetfile('*.VERT',...
'Select the files to plot', ...
'Multiselect', 'off');
else
file = options.file;
path = options.path;
end

% Exit in case no files were imported
if isfloat(file)
disp('No file selected: exiting')
return;
end

% Get the correct data line
A = regexp(fileread([path '\' file]),'\n','split');
dataLine = find(contains(A,'DATA'), 1, 'last') + 2;

[Bias, I, ~] = ImportVERTfile([path '\' file], [dataLine, inf]);

%% Find the bias where current crosses zero

% If the spectra have several directions, use only the forward direction
[Bias, ia, ~] = unique(Bias, 'stable');
I = I(ia);

% Also, make sure the current vector is unique. Sometimes it is not.
[I, ib, ~] = unique(I, 'stable');
Bias = Bias(ib);

% Interpolate to get the offset
offset = interp1(I, Bias, 0);


end

254 changes: 254 additions & 0 deletions AaltoAtoms/MATLAB/Createc data import tools/CustomVERTImport.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
function [Data, header] = CustomVERTImport(options)
arguments
options.files = 'no';
options.path = 'no';
options.normalisation string = 'IMax';
options.direction string = 'all';
options.BiasUnit char = 'mV'
options.correctBiasOffset logical = true;
end

%CUSTOMVERTIMPORT Imports all your Createc VERT files, however you like them
% Imports VERT Files (see import functions for details), applies
% normalisations.
% Inputs (name-value pairs):
% - files: the list of VERT files to be plotted. Default opens a file
% browser.
% - path: path to the folder containing the VERT files. Default opens
% a file browser.
% - normalisation: How to normalise the data
% - 'raw' (default): plotting raw data (with NaN values removed)
% - 'IMax': normalise all spectra with the current at the start
% of the spectrum.
% - 'StartNorm': normalise all spectra to the starting value
% - 'avg': normalise each spectra to it's mean
% - direction: which direction to take the spectra
% - 'all' (default): plot all points in the files
% - 'fwd': plot only the forward direction of bias sweeps
% - 'bwd': -||- backward direction
% - 'avg': averages the points in the forward and backward
% directions
% - BiasUnit: either 'mV' (default) or 'V' for volts
% - correctBiasOffset: apply a simple bias offset (default true)
% More optional inputs can be added as needed!
% Outputs:
% - h: handle to the generated figure
% - data: A struct with a bunch of stuff like Bias, I, dIdV etc.
% - header: Header of the first file to see what's what
%
% Adapted from PlotVERTFunction 3.9.2021
% Example on how to call the function:
% >> % [Data, header] = CustomVERTImport('files', files, ...
% 'path', path,...
% 'direction', 'fwd',...
% 'normalisation', 'avg');

%% Import
% Use the supplied path and files if able
if strcmp(options.files, 'no')
[files, path] = uigetfile('*.VERT',...
'Select the files to plot', ...
'Multiselect', 'on');
else
files = options.files;
path = options.path;
end

% Exit in case no files were imported
if isfloat(files)
disp('No file selected: exiting')
return;
end

%% Initialize necessary parameters
% Number of point spectra (NP). Also, read a VERT file to know what's what
if ischar(files)
% One spectrum
NP = 1;

% Get the correct data line
A = regexp(fileread([path files]),'\n','split');
dataLine = find(contains(A,'DATA'), 1, 'last') + 2;

[Bias, ~, ~] = ImportVERTfile([path files], [dataLine, inf]);
header = ImportVERTHeader([path files]);

if options.correctBiasOffset
Bias = Bias - BiasOffset('file', files, 'path', path);
end
else
% Several spectra
NP = length(files);

% Get the correct data line
A = regexp(fileread([path files{1}]),'\n','split');
dataLine = find(contains(A,'DATA'), 1, 'last') + 2;

[Bias, ~, ~] = ImportVERTfile([path files{1}], [dataLine, inf]);
header = ImportVERTHeader([path files{1}]);

% Line length from headers
Pos1 = [header.XPos_nm, header.YPos_nm];

Header2 = ImportVERTHeader([path files{end}]);
Pos2 = [Header2.XPos_nm, Header2.YPos_nm];

LineLength = norm(Pos2- Pos1);
% LineDist = linspace(0, LineLength, NP);
Line_nm = [0 LineLength];

if options.correctBiasOffset
Bias = Bias - BiasOffset('file', files{1}, 'path', path);
end
end

% Get rid of NaN values
Bias = rmmissing(Bias);

% Remove duplicate points from the beginning and end
NSearch = 40;

[~,iStart,~] = unique(Bias(1:NSearch), 'last');
NEStart = iStart(end);

[~,iEnd,~] = unique(Bias(end-NSearch+1:end), 'first');
NEEnd = length(Bias) - NSearch + max(iEnd);

% Indexing works without sorting
BiasFilt = Bias(NEStart:NEEnd);

% Number of energy points: one way, both ways, or average
if strcmp(options.direction, 'all')
NE = length(BiasFilt);
else
NE = length(unique(BiasFilt));
end

% Mid point initialisation: reverts to NEEnd if the spectrum only has one
% direction
NEMid = find(Bias == min(Bias), 1);

% In case the starting bias is smaller than the end
if NEMid == NEStart
NEMid = find(Bias == max(Bias) ,1);
end

% dIdV and I matrix initialisation
dIdV = zeros(NE, NP);
I = zeros(NE, NP);

%% Extract the data
for ii = 1:NP
% Filename initialisation based on NP
if NP ~= 1
filename = [path files{ii}];
VertGain = GetHeaderParam('VertManGain', 'files',files{ii}, 'path', path);
else
filename = [path files];
VertGain = header.VertManGain;
end

[~, I_cur, LIX] = ImportVERTfile(filename, [dataLine, inf]);

% Get rid of NaNs
LIX = rmmissing(LIX);
I_currm = rmmissing(I_cur);

% Fix the current with preamp gain value
% (Note that 'GainPreamplifier' is the scanning preamp gain)
if VertGain ~= 9
I_currm = I_currm.*10^(9 - VertGain);
end

%% Directions
% If the spectra are taken in one direction, things get simple

if length(BiasFilt) == length(unique(BiasFilt))
% disp('No backward direction: plotting forward direction instead')
dIdV(:,ii) = LIX(NEStart:NEEnd);
I(:,ii) = I_currm(NEStart:NEEnd);

else
% Take the backward and forward channels
LIXfw = LIX(NEStart:NEMid);
LIXbw = flipud(LIX(NEMid:NEEnd));

Ifw = I_currm(NEStart:NEMid);
Ibw = flipud(I_currm(NEMid:NEEnd));

switch options.direction
case 'all'
% won't work nicely with heat maps with several directions
dIdV(:,ii) = LIX(NEStart:NEEnd);
I(:,ii) = I_currm(NEStart:NEEnd);

case 'avg'
dIdV(:,ii) = (LIXfw + LIXbw)/2;.../mean(I_cur(1:NEStart));
I(:,ii) = (Ifw + Ibw)/2;

case 'fwd'
dIdV(:,ii) = LIXfw;
I(:,ii) = Ifw;

case 'bwd'
% If the spectra are only taken in one direction, take the
% forward direction instead

dIdV(:,ii) = LIXbw;
I(:,ii) = Ibw;

end
end

%% Normalisations
switch options.normalisation
case 'raw'
continue

case 'IMax'
dIdV(:,ii) = dIdV(:,ii)./I(1, ii);

case 'StartNorm'
dIdV(:,ii) = dIdV(:,ii)./dIdV(1, ii);

case 'avg'
dIdV(:,ii) = dIdV(:,ii)./mean(dIdV(:,ii));
end

end

%% Adjust the bias vector based on directions
switch options.direction
case 'all'
% Default initialisation is good: no need to do anything
case 'bwd'
BiasFilt = flipud(Bias(NEMid:NEEnd));
otherwise
BiasFilt = Bias(NEStart:NEMid);
end

%% Bias unit
if strcmp(options.BiasUnit, 'V')
BiasFilt = 1e-3.*BiasFilt;
end

%% Produce the data struct
% Always available ones
Data.files = files;
Data.path = path;
Data.dIdV = dIdV;
Data.Bias = BiasFilt;
Data.I = I;
Data.NP = NP;
Data.NE = NE;

% Conditional ones
if NP > 1
Data.LineLength = LineLength;
else
Data.LineLength = [];
end


end

62 changes: 62 additions & 0 deletions AaltoAtoms/MATLAB/Createc data import tools/GetHeaderParam.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
function [param] = GetHeaderParam(paramName, options)
arguments
paramName char
options.files = 'no'
options.path = 'no'
end

%GETHEADERPARAM Returns the value(s) of a VERT file header parameter
% Inputs:
% - paramName: char with the parameter name needed (see ImportVertHeader
% for the list of parameter names)
% - files: the files from which the header will be extracted. Default
% opens a file browser.
% - path: path of said files.
% Output:
% - param: a vector of numerical parameter values
%
% FIXME: One path per function call: use loops to go through several paths
% FIXME: Make param a struct or cell array to store multiple types of
% header parameters.

%% File names and path
% Use the supplied path and files if able
if strcmp(options.files, 'no')
[files, path] = uigetfile('*.VERT',...
'Select the files to plot', ...
'Multiselect', 'on');
else
files = options.files;
path = options.path;
end

% Exit in case no files were imported
if isfloat(files)
disp('No file selected: exiting')
return;
end

%% Do the header imports in a loop
% Number of point spectra (NP)
if ischar(files)
% One spectrum
NP = 1;
else
% Several spectra
NP = length(files);
end

% FIXME: taking only numerical values for now
param = zeros(1,NP);

if NP == 1
header = ImportVERTHeader([path '/' files]);
% param = getfield(header, paramName);
param = header.(paramName);
else
for ii = 1:NP
header = ImportVERTHeader([path '/' files{ii}]);
param(ii) = header.(paramName);
end
end

Loading

0 comments on commit 7a73f9f

Please sign in to comment.