Files
nappMATLAB-toolbox/beamtime/plotRgaData.m
T

117 lines
4.3 KiB
Matlab

function ax = plotRgaData(tbl, opts)
%PLOTRGADATA Plot RGA partial pressures vs time (companion to plotCryoData).
%
% ax = plotRgaData(tbl)
% ax = plotRgaData(tbl, TimeRange=[t1 t2], Masses=["m28" "m18"])
%
% Plots every channel column of an rgaImportData table against its shared
% datetime axis. If Masses is given, a second figure shows a stackedplot
% of those ions over the same time window. Returns a struct with the
% axes/chart handles.
%
% Name-value arguments (type "plotRgaData(tbl, " and tab for suggestions):
% TimeRange (1x2 datetime) subset window [start end]. Default: full range.
% Masses (string) mass labels for the stackedplot, with or without
% the leading "m": "m28", "28", ["m28" "m18"]. Default: none,
% i.e. the stackedplot is skipped unless masses are requested.
%
% By default the y-axis of the first plot is linear (RGA scans contain
% small near-noise negatives that a log axis cannot show). To switch to
% the classic semilog view afterwards:
% set(ax.partial, 'YScale', 'log');
% (values <= 0 are simply not drawn on a log axis).
%
% EXAMPLE
% tbl = rgaImportData('rga1_Jul_01_2026_08-23-06_AM.txt');
% ax = plotRgaData(tbl); % overlay only
% ax = plotRgaData(tbl, TimeRange=[t1 t2]); % zoom to a window
% ax = plotRgaData(tbl, Masses=["m28" "m18" "m44"]); % overlay + ion stack
%
% See also RGAIMPORTDATA, PLOTCRYODATA, STACKEDPLOT
arguments
tbl table
opts.TimeRange (1,2) datetime = [NaT NaT]
opts.Masses (1,:) string = string.empty
end
%--- Extract datetime column ---
dt = tbl.datetime;
%--- If a real time range was given, subset the table (shared by both plots) ---
if ~any(isnat(opts.TimeRange))
mask = dt >= opts.TimeRange(1) & dt <= opts.TimeRange(2);
tbl = tbl(mask, :);
dt = dt(mask);
end
%--- Channel columns = everything except datetime & time_s ---
chVars = setdiff(tbl.Properties.VariableNames, {'datetime','time_s'}, 'stable');
units = 'a.u.';
if isfield(tbl.Properties.UserData, 'units')
units = tbl.Properties.UserData.units;
end
%--- Plot 1: all partial pressures overlaid ---
figure;
tl = tiledlayout(1, 1);
tl.TileSpacing = 'compact';
tl.Padding = 'compact';
ax.partial = nexttile;
hold on;
for k = 1:numel(chVars)
plot(dt, tbl.(chVars{k}), '-', 'LineWidth', 1, ...
'DisplayName', prettyName(chVars{k}));
end
grid on;
ylabel(sprintf('Partial pressure [%s]', units));
xlabel('Date & Time');
title('RGA partial pressures');
legend('Location', 'best', 'Interpreter', 'none');
% Match plotCryoData's datetime tick style
ax.partial.XAxis.TickLabelFormat = 'dd-MMM HH:mm';
%--- Plot 2: selected ions as a stackedplot (only if masses requested) ---
ax.stacked = [];
if ~isempty(opts.Masses)
sel = selectIons(chVars, opts.Masses);
if isempty(sel)
warning('plotRgaData:noIonMatch', ...
'No channels matched the requested mass label(s): %s', ...
strjoin(cellstr(opts.Masses), ', '));
else
figure;
ax.stacked = stackedplot(tbl, sel, 'XVariable', 'datetime');
ax.stacked.Title = sprintf('Selected ions [%s]', units);
ax.stacked.XLabel = 'Date & Time';
ax.stacked.DisplayLabels = cellfun(@prettyName, sel, 'UniformOutput', false);
ax.stacked.GridVisible = 'on';
end
end
end
% -------------------------------------------------------------------------
function sel = selectIons(chVars, masses)
% Return the channel names whose mass label matches any entry in masses.
% masses may be given with or without the leading "m" ("m28", "28").
keep = false(1, numel(chVars));
for j = 1:numel(masses)
lbl = masses(j);
if ~startsWith(lbl, "m")
lbl = "m" + lbl;
end
keep = keep | endsWith(string(chVars), "_" + lbl);
end
sel = chVars(keep);
end
% -------------------------------------------------------------------------
function s = prettyName(v)
% "Water_m18" -> "Water (m18)"
s = regexprep(v, '_m(\d+)$', ' (m$1)');
s = strrep(s, '_', ' ');
end