Complicated colorbar question?

10 vues (au cours des 30 derniers jours)
david hill
david hill le 25 Juin 2020
Modifié(e) : Adam Danz le 30 Juin 2020
Hello.
I have a raster with data values from 0 --> 100. So, easy to plot and have a nice colorbar, either continuous or discrete.
Next, there are a few 'flags' for data quality control. So, there are a number of cells with a value of 200, 201, 202, 203, etc. Those values have special meaning.
So, I would really like to have a plot that displays the valid data cells using a simple colorbar (spanning values 0 --> 100), but then I would like to plot the other cells (say value of 200, or 201, etc.) with clearly contrasting colors so that the user can see the locations where the data has been flagged.
Is something like this possible?
Dave.

Réponse acceptée

Adam Danz
Adam Danz le 25 Juin 2020
Modifié(e) : Adam Danz le 30 Juin 2020
Option 1: use a legend for the codes and a colorbar for the continuous data
The easiest and cleanest method might be to set a different black symbol for each code and to define those symbols within a legend. Then use a colorbar to define the continuous data.
Here's an example just to give a picture of what this may look like.
% Create data
data = randi(101,1,200)-1;
dataMat = reshape(data(randperm(numel(data))),10,[]);
[x,y] = meshgrid(1:size(dataMat,2), 1:size(dataMat,1));
% insert some code values
uniqueCodes = [200,201,202,203];
codeSymbols = {'s','d','^','p'}; % 1 symbol for each code
codeIdx = unique(randi(numel(dataMat),1,30));
codeIdx = ismember(1:numel(dataMat), codeIdx);
dataMat(codeIdx) = randsample(uniqueCodes,sum(codeIdx),true);
% Plot the data, not the code
fig = figure();
ax = axes(fig);
hold(ax,'on')
h1 = scatter(ax, x(~codeIdx),y(~codeIdx),50,dataMat(~codeIdx),'filled');
% Add codes symbols
h2 = arrayfun(@(i)scatter(ax, x(dataMat==uniqueCodes(i)),y(dataMat==uniqueCodes(i)),70,'k','filled','marker',codeSymbols{i}),1:numel(uniqueCodes));
% add colorbar and legend
colorbar()
legend(h2, compose('Code %d',uniqueCodes))
Option 2: Add blocks of discrete colors to a continuous colorbar
This can get complicated. The inline comments in the demo below provide more detail but the main idea is to scale the colorbar so the top ~25% of it is devoted to a discrete set of colors. Then scale the data and the code values to fit the sections of the colorbar.
% Create a grid of data points
data = [randi(101,1,200)-1, randi(4,1,10)+199];
dataMat = reshape(data(randperm(numel(data))),10,21);
[x,y] = meshgrid(1:size(dataMat,2), 1:size(dataMat,1));
% Define codes and their colors
uniqueCodes = [200,201,202,203]; % list unique codes
codeColors = [... % Define 1 color per code
1.0000 .75000 .79297; % pink
1.0000 .41016 .70313; % hotpink
1.0000 .00000 .00000; % red
.54297 .00000 .00000]; % darkred
% Define colormap for the range of data
cm = parula(256);
% Devote the top ~25% of the colorbar to the code-colors
nCodes = numel(uniqueCodes);
rowsPerCode = round((size(cm,1)*.25) / nCodes);
codeColorsRep = repelem(codeColors, rowsPerCode, 1);
cm(end-size(codeColorsRep,1)+1:end,:) = codeColorsRep;
% Assign colormap and colorbar to plot (still no data plotted)
fig = figure();
ax = axes(fig);
ax.Colormap = cm;
cb = colorbar(ax);
% Use caxis to scale the color range so that the continuous part spans the min-max of your data
dataLimits = [0,100]; % <----- You'll have to calculate this; it's the min,max of your data (ignoring the code values)
continuousPortion = (1-size(codeColorsRep,1)/size(cm,1));
cblim = [dataLimits(1), ceil(dataLimits(2)./continuousPortion)];
caxis(cblim)
% Compute centers of each code-section in the colorbar
discreteTicks = linspace(range(cblim)*continuousPortion+cblim(1), cblim(2), nCodes*2+1);
discreteTicks(1:2:end) = [];
% Set colorbar ticks
cb.Ticks = [0 : 10 : dataLimits(2), discreteTicks];
% Set tick lables
cbTickLab = cb.TickLabels;
cbTickLab(end-nCodes+1:end) = compose('Code %d',uniqueCodes);
cb.TickLabels = cbTickLab;
% Replace code-values with the colorbar tick values
for i = 1:nCodes
dataMat(dataMat == uniqueCodes(i)) = discreteTicks(i);
end
% Plot the data
hold(ax,'on') % important, otherwise you'll lose the colorbar etc.
sh = scatter(ax, x(:),y(:),50,dataMat(:),'filled');
Option 3: Create 2 colorbars using a 2nd invisible axes
% define code values
uniqueCodes = [200,201,202,203];
% Define code colors
codeColors = [... % Define 1 color per code
1.0000 .75000 .79297; % pink
1.0000 .41016 .70313; % hotpink
1.0000 .00000 .00000; % red
.54297 .00000 .00000]; % darkred
% Plot the data, not the code
fig = figure();
ax = axes(fig);
% plot here......
% Add 2nd invisible axes
ax2 = axes('Visible','off');
linkprop([ax,ax2],'position')
% Set colormap to ax2
ax2.Colormap = codeColors;
% add colorbars
cb1 = colorbar(ax);
cb2 = colorbar(ax2);
% Reposition axes
ax.Position(1) = ax.Position(1)*.8;
ax.Position(3) = ax.Position(3)*.8;
% Reposition colorbars
cb2.Position(1) = sum(cb1.Position([1,3]))+.1;
cb2.Ticks = linspace(0,1,numel(uniqueCodes)*2+1);
tickLabels = cell(1,numel(cb2.Ticks));
tickLabels(2:2:end) = num2cell(uniqueCodes);
cb2.TickLabels = tickLabels;

Plus de réponses (0)

Catégories

En savoir plus sur Colormaps dans Help Center et File Exchange

Produits


Version

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by