Surf color based off of greater than or less than a number

I was able to create a surf plot where values greater than 1000 are red and less than 1000 are blue. Is there a way that I could use different shades of red and blue depending how far away from 1000 it is, darker the farther. And how can I make a range of values for the greenchannel? Also is there a better way to do this as 1 side of the plot is black.
z = U_ku;
redChannel = z > 1000;
greenChannel = 0*z;
blueChannel = z < 1000;
% Make the RGB image.
colors = double(cat(3, redChannel, greenChannel, blueChannel));
% Plot the surface with those colors.
surf(z, colors);

 채택된 답변

There are a bunch of blue-red colormap generators out there, or you could create your own. Either way, this is one way to apply it. Instead of trying to directly color the surface, use the scaled colormapping functionality of the graphics system.
% some fake data
x = 0:50;
y = x.';
z = x.*y;
% plot it
hs = surf(x,y,z);
hs.EdgeColor = 'none';
% create a symmetric colormap
ncolors = 256;
CT = bluewhitered1(ncolors);
% set the colormap
colormap(CT)
% set the climits to be symmetric about the center threshold
thresh = 1000;
halfwidth = max(abs(zlim() - thresh));
clim(thresh + [-1 1]*halfwidth)
I attached a handful of similar simple map generators. There are others on the File Exchange. Otherwise, you can open up any of the attached files and edit the breakpoint locations or colors to make your own.

댓글 수: 6

Ideally, I am trying to set a colormap such that the colors respresent a certain value, so I can do many plots and if they are below 1000 they will be blue and above red. Inbetween green. Will this be possible with this set up code?
What exactly do you mean by "in between"?
You could have a discrete colormap with (e.g.) three colors representing values over three adjacent intervals, but it would make sense then that for three discrete colors, we need at least two breakpoints. Maybe the two breakpoints are equidistant from 1000, but you'd still need to specify the distance. For example:
For example, this is derived from the last example in #1891415, as adapted to the original answer's data, for a fixed window about 1000.
% some fake data
x = linspace(0,50,200);
y = x.';
Z = x.*y;
% intervals/categories in Z (or C)
% the span of this vector defines caxis/clim
thresh = 1000; % the window center
halfwidth = 200; % the window half-width
zb = [min(Z(:)) [-1 1]*halfwidth+thresh max(Z(:))]; % in data units
% interval/category colors
CT0 = [0 0 1; 0 1 0; 1 0 0]; % [blue; green; red]
% maximum table length
nmax = 256;
% generate expanded color table & info
[CT cidx] = intervalct(zb,CT0,nmax);
cidx1 = cidx(:,2); % trailing block indices
% color data as an RGB array
% this can be generated however you see fit (imquantize(), etc)
C = ones(size(Z));
nk = numel(zb)-1;
for ck = 1:nk
if ck == 1
C(Z<zb(2)) = 1;
elseif ck == nk
C(Z>=zb(nk)) = nk;
else
C(Z>=zb(ck) & Z<zb(ck+1)) = ck;
end
end
C = ind2rgb(C,CT0);
hs = surf(x,y,Z,C);
hs.CDataMapping = 'direct';
shading flat
colormap(CT) % still need full CT here though
cb = colorbar;
cb.Ticks = zb;
caxis(imrange(zb));
Alternatively, you can have a graduated colormap, but as with the discrete case, you may have to still come up with a more complete description of what it should look like. For example, how wide should the center green region be? Is it a fixed width, or is it simply proportional to the data range? Should the transition at the edge of the green region be visually distinct, or should the entire map be smoothly graduated?
There aren't many graduated blue-green-red map generators off the top of my head, so if that's what you want, you might need to make a custom one.
Here is one example, again using intervalct() to try to get favorable quantization. This is similar to the 'scaled' CDataMapping example from #1891415, but in this case, we're only using intervalct() to calculate optimal block length ratios. We're manually constructing a segmented map whose length is an integer multiple of the optimized length.
% some fake data
x = linspace(0,50,200);
y = x.';
Z = x.*y;
% intervals/categories in Z (or C)
% the span of this vector defines caxis/clim
thresh = 1000;
halfwidth = 200;
zb = [min(Z(:)) [-1 1]*halfwidth+thresh max(Z(:))];
% interval/category colors
% these are just dummy values in this case,
% but they're needed for intervalct() to work.
CT0 = rand(numel(zb)-1,3);
% maximum table length
nmax = 256;
% generate breakpoints for a new CT
% this will search for a _minimal_ length CT
% so the length will likely be shorter than nmax,
% but it will be optimized to quantize as accurately as possible.
[~,cidx] = intervalct(zb,CT0,nmax);
bw = diff(cidx,1,2) + 1; % block widths
% generate a new segmented CT
% since we don't want a short table anymore,
% new CT length is an _integer_ multiple of the optimized CT length
bw = bw*round(nmax/cidx(end)); % new block lengths
% each segment can be a unique colormap
% depending on the end colors you choose, the composite map
% may be piecewise-continuous, or it may be discontinuous for emphasis
breakos = 0.7;
CT1 = makectf([0 0 0.3],[0 0 1],bw(1),'srgb');
CT2 = makectf([0 breakos 1],[1 breakos 0],bw(2),'yiq'); % cyan-green-yellow
CT3 = makectf([1 0 0],[0.3 0 0],bw(3),'srgb');
CT = [CT1; CT2; CT3];
hs = surf(x,y,Z,Z); % here, C = Z; CDataMapping is 'scaled'
shading flat
colormap(CT)
cb = colorbar;
cb.Ticks = zb;
caxis(imrange(zb));
... or maybe you could break that center interval into two segments ...
% some fake data
x = linspace(0,50,200);
y = x.';
Z = x.*y;
% intervals/categories in Z (or C)
% the span of this vector defines caxis/clim
thresh = 1000;
halfwidth = 200;
zb = [min(Z(:)) [-1 0 1]*halfwidth+thresh max(Z(:))]; % add an extra breakpoint
% interval/category colors
% these are just dummy values in this case,
% but they're needed for intervalct() to work.
CT0 = rand(numel(zb)-1,3);
% maximum table length
nmax = 256;
% generate breakpoints for a new CT
% this will search for a _minimal_ length CT
% so the length will likely be shorter than nmax,
% but it will be optimized to quantize as accurately as possible.
[~,cidx] = intervalct(zb,CT0,nmax);
bw = diff(cidx,1,2) + 1; % block widths
% generate a new segmented CT
% since we don't want a short table anymore,
% new CT length is an _integer_ multiple of the optimized CT length
bw = bw*round(nmax/cidx(end)); % new block lengths
% each segment can be a unique colormap
% depending on the end colors you choose, the composite map
% may be piecewise-continuous, or it may be discontinuous for emphasis
breakos = 0.6;
CT1 = makectf([0 0 0.2],[0 0 1],bw(1),'srgb');
CT2 = makectf([0 breakos 1],[0 0.8 0],bw(2),'linear'); % uses IPT
CT3 = makectf([0 0.8 0],[1 breakos 0],bw(3),'linear'); % uses IPT
CT4 = makectf([1 0 0],[0.2 0 0],bw(4),'srgb');
CT = [CT1; CT2; CT3; CT4];
hs = surf(x,y,Z,Z); % here, C = Z; CDataMapping is 'scaled'
shading flat
colormap(CT)
cb = colorbar;
cb.Ticks = zb;
caxis(imrange(zb));
... or just make the center interval solid green
% some fake data
x = linspace(0,50,200);
y = x.';
Z = x.*y;
% intervals/categories in Z (or C)
% the span of this vector defines caxis/clim
thresh = 1000;
halfwidth = 200;
zb = [min(Z(:)) [-1 1]*halfwidth+thresh max(Z(:))];
% interval/category colors
% these are just dummy values in this case,
% but they're needed for intervalct() to work.
CT0 = rand(numel(zb)-1,3);
% maximum table length
nmax = 256;
% generate breakpoints for a new CT
% this will search for a _minimal_ length CT
% so the length will likely be shorter than nmax,
% but it will be optimized to quantize as accurately as possible.
[~,cidx] = intervalct(zb,CT0,nmax);
bw = diff(cidx,1,2) + 1; % block widths
% generate a new segmented CT
% since we don't want a short table anymore,
% new CT length is an _integer_ multiple of the optimized CT length
bw = bw*round(nmax/cidx(end)); % new block lengths
% each segment can be a unique colormap
% depending on the end colors you choose, the composite map
% may be piecewise-continuous, or it may be discontinuous for emphasis
CT1 = makectf([0 0 0.3],[0 0 1],bw(1),'srgb');
CT2 = repmat([0 0.8 0],[bw(2) 1]); % all green
CT3 = makectf([1 0 0],[0.3 0 0],bw(3),'srgb');
CT = [CT1; CT2; CT3];
hs = surf(x,y,Z,Z); % here, C = Z; CDataMapping is 'scaled'
shading flat
colormap(CT)
cb = colorbar;
cb.Ticks = zb;
caxis(imrange(zb));
Thank you!! This is exactly what i want!
I am trying to recreate the last figure with making the code a function. As of now I have this and it is not plotting like above. How should I make the code to a function to fix?
function [CT,zb]=colorscheme(Z,thresh)
% intervals/categories in Z (or C)
% the span of this vector defines caxis/clim
%thresh = 1000;
halfwidth = 200;
zb = [min(Z(:)) [-1 1]*halfwidth+thresh max(Z(:))];
% interval/category colors
% these are just dummy values in this case,
% but they're needed for intervalct() to work.
CT0 = rand(numel(zb)-1,3);
% maximum table length
nmax = 256;
% generate breakpoints for a new CT
% this will search for a _minimal_ length CT
% so the length will likely be shorter than nmax,
% but it will be optimized to quantize as accurately as possible.
[~,cidx] = intervalct(zb,CT0,nmax);
bw = diff(cidx,1,2) + 1; % block widths
% generate a new segmented CT
% since we don't want a short table anymore,
% new CT length is an _integer_ multiple of the optimized CT length
bw = bw*round(nmax/cidx(end)); % new block lengths
% each segment can be a unique colormap
% depending on the end colors you choose, the composite map
% may be piecewise-continuous, or it may be discontinuous for emphasis
CT1 = makectf([0 0 0.3],[0 0 1],bw(1),'srgb');
CT2 = repmat([0 0.8 0],[bw(2) 1]); % all green
CT3 = makectf([1 0 0],[0.3 0 0],bw(3),'srgb');
CT = [CT1; CT2; CT3];
end
How would you go about changing the colors to 3 different colors for the last figure code. And I was able to figure out my function problem.
Sorry about being late. My garbage computer is in its death throes.
If you want to adjust the colors a bit easier, you could do something like this.
% you can define these as input arguments to your function if you want
basecolors = [0 0 1; 0 0.8 0; 1 0 0]; % the colors near the center band
darkenamt = 0.7; % the amount by which the top and bottom colors get darkened
% then make the color table segments based on those parameters
CT1 = makectf(max(basecolors(1,:)-darkenamt,0),basecolors(1,:),bw(1),'srgb');
CT2 = repmat(basecolors(2,:),[bw(2) 1]); % all green
CT3 = makectf(basecolors(3,:),max(basecolors(2,:)-darkenamt,0),bw(3),'srgb');
CT = [CT1; CT2; CT3];

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

도움말 센터File Exchange에서 Contour Plots에 대해 자세히 알아보기

제품

릴리스

R2024b

질문:

2025년 3월 14일

댓글:

DGM
2025년 3월 17일

Community Treasure Hunt

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

Start Hunting!

Translated by