Colors are not correctly assigned to spectra plotted
26 views (last 30 days)
Show older comments
My script is supposed to assign colors to spectra but it ends up assigning the wrong colors to the spectra: function
displaypeak1D_grouped(X, ppm, shift, data, colorTable)
% displaypeak1D_grouped - Plot spectra grouped by metadata with user-assigned colors
% Includes diagnostic preview of label-to-color mapping
%
% Inputs:
% X : spectra matrix (nSamples x nPoints)
% ppm : chemical shift vector (1 x nPoints)
% shift : vector of chemical shifts to highlight (optional)
% data : struct with fields ID, Sex, TreatmentGroup, Strain
% colorTable : table from namedColorTable(K) with columns R,G,B,Hex,Name
% --- Validate ---
n = size(X,1);
assert(size(X,2) == numel(ppm), 'ppm length must match size(X,2)');
assert(istable(colorTable) && ...
all(ismember({'R','G','B','Hex','Name'}, colorTable.Properties.VariableNames)), ...
'colorTable must have R,G,B,Hex,Name');
req = {'ID','Sex','TreatmentGroup','Strain'};
for f = 1:numel(req)
assert(isfield(data, req{f}), 'Missing data.%s', req{f});
assert(numel(data.(req{f})) == n, 'data.%s length must match rows in X', req{f});
end
% --- Choose grouping variable ---
groupChoice = menu('Select grouping variable:', 'ID','Sex','TreatmentGroup','Strain');
groupFields = {'ID','Sex','TreatmentGroup','Strain'};
selectedGroup = groupFields{groupChoice};
% --- Build labels ---
labels = buildLabelsFlexible(data, selectedGroup);
[uniqueLabels, ~, labelIdxPerSample] = unique(labels, 'stable');
fprintf('Detected labels (order preserved): %s\n', strjoin(uniqueLabels, ', '));
% --- Prompt for colors ---
chosenColors = selectColorsForLabels(uniqueLabels, colorTable);
% --- Scale RGB if needed ---
if max(table2array(chosenColors(:,{'R','G','B'})),[],'all') > 1
chosenColors{:,{'R','G','B'}} = chosenColors{:,{'R','G','B'}} / 255;
end
% --- Build label->RGB map ---
labelColorMap = containers.Map;
for i = 1:numel(uniqueLabels)
rgbRow = table2array(chosenColors(i, {'R','G','B'}));
labelColorMap(uniqueLabels{i}) = rgbRow;
end
% --- Diagnostic preview table ---
T = table;
T.Index = (1:n)'; % row index
T.ID = string(data.ID(:)); % sample IDs
T.Label = string(labels(:)); % extracted labels
T.RGB = zeros(n,3); % assigned colors
for k = 1:n
lbl = labels{k};
if isKey(labelColorMap, lbl)
T.RGB(k,:) = labelColorMap(lbl);
end
end
disp('Diagnostic preview of label-to-color mapping (first 20 rows):');
disp(T(1:min(20,n),:));
% --- Plot spectra ---
figure; hold on;
for k = 1:n
lbl = uniqueLabels{labelIdxPerSample(k)};
rgb = labelColorMap(lbl);
plot(ppm, X(k,:), 'Color', rgb);
end
set(gca,'XDir','reverse');
xlabel('ppm'); ylabel('Intensity');
title(sprintf('Spectra colored by %s', selectedGroup));
% --- Overlay markers ---
if ~isempty(shift)
b = zeros(1, numel(shift));
for i = 1:numel(shift)
[~, b(i)] = min(abs(ppm - shift(i)));
end
scatter(shift, max(X(:, b)), 25, 'k', 'filled');
end
% --- Legend ---
legendHandles = gobjects(numel(uniqueLabels),1);
for i = 1:numel(uniqueLabels)
rgb = labelColorMap(uniqueLabels{i});
legendHandles(i) = plot(NaN, NaN, 'Color', rgb, 'LineWidth', 2);
end
legend(legendHandles, uniqueLabels, 'Location','best');
end
% ===== Helper: buildLabelsFlexible =====
function labels = buildLabelsFlexible(data, selectedGroup)
n = numel(data.ID);
labels = cell(n,1);
switch selectedGroup
case 'ID'
% Match _T0.._T3 exactly, avoid T10 etc.
tokens = regexp(data.ID, '_T([0-3])(?!\d)', 'tokens');
for i = 1:n
if ~isempty(tokens{i})
labels{i} = ['T' tokens{i}{1}{1}];
else
labels{i} = 'Other';
end
end
otherwise
vals = data.(selectedGroup);
labels = cellstr(string(vals));
end
end
% ===== Helper: selectColorsForLabels =====
function chosenColors = selectColorsForLabels(uniqueLabels, colorTable)
chosenColors = colorTable([],:);
for i = 1:numel(uniqueLabels)
prompt = sprintf('Select color for %s', uniqueLabels{i});
[indx, tf] = listdlg('PromptString', prompt, ...
'SelectionMode','single', ...
'ListString', colorTable.Name);
if tf
chosenColors = [chosenColors; colorTable(indx,:)]; %#ok<AGROW>
else
chosenColors = [chosenColors; colorTable(1,:)]; %#ok<AGROW>
end
end
end
This is the function that I am using to plot my spectra based on ID, Strain, and other groups. For instance, if I want to assign colors based on timepoints, the code does well to assign the colors and plot the spectra for visualization but it is not assigning the colors to the right spectra. So spectra with timepoints T2 get colors assigned for T1. Please help me fix this. In the image, the two small peaks color coded blue are T2 spectra and so are supposed to be color coded green instead.

2 Comments
Mathieu NOE
on 13 Nov 2025 at 8:11
hello
it would be nice to have some data to test your code
can you share a mat file ?
dpb
on 13 Nov 2025 at 15:48
Edited: dpb
on 13 Nov 2025 at 16:16
Far too complicated to debug simply by reading code, but seems to be an awfully comlicated data structure and way to go about doing the assignments; I'd be looking to simplify.
But, the issue is going to be here--
for k = 1:n
lbl = uniqueLabels{labelIdxPerSample(k)};
...
in that your logic isn't working as you expect it is to return the expected color.
Set a breakpoint there and study the inputs and see where your logic in the color assignment isn't working as you expect.
As @Mathieu NOE says, without a MINIMUM(*) working example that illustrates the problem you're simply asking for too much independent effort from forum volunteers. Your input case will also need to provide the expected user inputs in the selection section.
(*) "MINIMUM" includes as small a dataset as possible that will produce the symptom. One possible side benefit of this prepration may be that you will discover the cause of the problem and be able to fix it yourself rather than waiting on outside help.
Answers (0)
See Also
Categories
Find more on Annotations in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!