Plotting multiple lines in Matlab - make colors more intense on each iteration? - matlab

I am plotting graphs of a function that changes slightly on each iteration as it converges towards its limiting values...How can I make the colors of the lines get more intense on each iteration? By intense I mean the lines stay the same color but get more saturated or darker on each iteration?

If you are plotting all you lines with one call of plot then set the 'ColorOrder' property of your axes (search for ColorOrder).
If you are using a loop, then you could do something like this:
baseColour = rgb2hsv([1,0,0]); %// Get the HSV values for pure red, but choose any colour
hue = baseColour(1);
saturation = baseColour(2);
for k = 1:n
%// do stuff
lineColour = hsv2rgb([hue, saturation, 1-(k-1)/(n-1)]);
%plot(..., 'Color', lineColour)
end
This should shift your lines from having no lightness (value actually) i.e. black to being fully light, but keeping the same hue and saturation which creates a fairly natural colour grading. This makes the most sense if your data are ordinal i.e. the user should know that the value of some property of the data forming the bright lines is greater than the value of that property of the data froming the darker lines.

You should create your own colormap, and for a given color you can set the intensity by interpolating the rgb values while keeping the proportions - an example explains what I mean more clearly. So for green:
cmap = [zeros(128,1), linspace(0,1,128)', zeros(128,1)];
imagesc(1:128)
colormap(cmap)

Related

Painting all bars less lower than a threshold with a single color

I have a bivariate histogram plot created using bar3. I'm trying to change the color of the bars that have a height less than a certain threshold, but to no avail. I got this code:
h = bar3(dataSample, 0.5);
for n=1:numel(h)
cdata=get(h(n),'zdata');
set(h(n),'cdata',cdata,'facecolor','interp')
end
I can't figure out how to make the plot look like the one below, where the bars less than say 0.001 are gray:
Any ideas?
here's how:
z=peaks(20);
h=bar3(z)
for n=1:numel(h)
cdata=get(h(n),'zdata');
set(h(n),'cdata',cdata,'facecolor','interp')
end
colormap([0.5.*ones(128,3); parula(128)]);
I've arbitrarily decided to cut the colormap in the middle, first 128 intensities as gray the next 128 intensities in color. you can cut it however you want. You can find the threshold you want by setting the colormap binning (say to 256 bins) and the place in that partition below which it'll be gray.

Octave/Matlab: Colormap not based on height

When I plot several functions in a 3D figure (using surf(my_function)) the default is that it colors each little bit of the function surface in a way that the color corresponds to the height at that point.
I would like to change that a little bit. I have several functions I want to plot on the same figure, and most of them are separated a little bit in the z direction, so they have different colors (a low one has shades of blue, a high one has shades of red). I would like to keep that for the most part, except have the function surface be different shades of the same color, but have that color change on each iteration of the loop I have for plotting these functions.
In my specific case, I'm plotting the wave functions of a particle in a 2D square well (infinite potential well). However, as some energy levels (that is, the height z) are degenerate I have different wave functions occupying the same z. I want to distinguish them by their shade of color, while retaining the method that low valleys of the function are a certain shade while high valleys are a different shade of the same color.
You can set the color for surf independently: This shows a height from peaks and color from sombrero (don't rely on __osmesa_print__, it's an internal Octave function):
figure ("visible", "off")
surf (peaks(64), sombrero (64));
[az, el] = view ();
n = 1;
clear img_stack;
for nel = el:2:90
view (az, nel);
drawnow;
img_stack (:, :, :, n++) = __osmesa_print__ (gcf);
endfor
imwrite (img_stack, "out.gif", "DelayTime", 0.1, "Compression", "lzw")

Converting a RGB image to grayscale based on the intensity of one color channel [duplicate]

This question already has an answer here:
Access RGB channels in an image in MATLAB
(1 answer)
Closed 6 years ago.
I'm working with images similar to this: a cell image, and I want to extract only the red-pink sections. As of now I'm using img(:,:,1) to pull out the red values but this produces a binary image. I wanted to know if there was a way to extract the "red" values and produce a grayscale image based on their degree of "redness" or intensity. Any help would be awesome.
You are likely visualizing the result using imshow which will automatically set the color limits of the axes to be between 0 and 1. Your image is RGB and the values of the red channel are going to range from 0 to 255. Because of this, if you only specify one input to imshow, you will get an image where all values > 1 will appear as white and all zero-values will be black. So your image isn't really binary, it just appears that way.
You want to either display your image with imagesc which will automatically scale the color limits to match your data:
imagesc(img(:,:,1));
colormap gray
Or you can specify the second input to imshow to cause it to also scale to fit your data range:
imshow(img(:,:,1), [])
The reason that this isn't an issue when you are visualizing all channels is that if you specify red, green, and blue channels, this is considered a true color image and all axes color limits are ignored.
The data you capture will be correct (and is grayscale), but the visualization may be incorrect. When trying to visualize a 2D matrix (same as your result img(:,:,1)), matlab applies the default colormap and the result is:
[x,y]=meshgrid(1:200, 1:200);
z=x.^2.*sin(y/max(y(:))*pi);
figure;imagesc(z);
If you want to avoid the applied jet colormap, either change the colormap:
colormap('gray')
or change your 2D matrix into a 3D one, explicitely specifying the colors to display (must be values between 0 and 1):
z3d = z(:,:,[1 1 1]); % more efficient than repmat
z3d = (z3d - min(z(:)))./range(z(:)); % make sure values in range [0; 1]
You see banding in the colormap version, because by default a colormap contains 64 different colors; the 3d matrix version doesn't have this problem as it directly displays the colors.
If I may add to your question, it seems to me you're simply trying to isolate and visualise the red, green, and blue fluorofores separately (or in combination). I specifically think this because you mention 'pink'.
It may be nicer to just isolate the channels:
>> F_red = F; F_red(:,:,[2,3]) = 0;
>> F_green = F; F_green(:,:,[1,3]) = 0;
>> F_blue = F; F_blue(:,:,[1,2]) = 0;
>> F_pink = F; F_pink(:,:,2) = 0;
Here's a subplot of the result:
Furthermore, you should know that the 'naive' way of producing a grayscale image does not preserve the 'luminosity' of colours as perceived by the human eye, since 'green' at the same intensity as 'red' and 'blue' will actually be perceived as brighter by the human eye, and similarly 'red' is brighter than 'blue'. Matlab provides an rgb2gray function which converts an rgb image to a grayscale image that correctly preserves luminance. This is irrelevant for your pure red, green, and blue conversions, but it may be something to think about with respect to a 'pink-to-grayscale' image. For instance, compare the two images below, you will see subtle contrast differences.
>> F_pinktogray_naive = mean(F(:,:,[1,3]), 3);
>> F_pinktogray_luminance = rgb2gray(F_pink);
A subplot of the two:
In a sense, you probably care more about the left (naive) one, because you don't care about converting the pink one to a gray one "visually", but you care more about the red and blue fluorofores being "comparable" in terms of their intensity on the grayscale image instead (since they represent measurements rather than a visual scene). But it's an important distinction to keep in mind when converting rgb images to grayscale.

Matlab: How to use a suitable color bar?

I have a picture which shows the magnitude of some value in terms of color, like this one:
The higher the magnitude, the more it looks red. However there are only a few points at the edge has very high values and most of the points have much lower values. If a colorbar with equal intervals is used the picture just looks blue throughout and the values in most areas cannot be distinguished.
Is it possible to set a colorbar that has, say, exponentially increasing intervals (or others) so that the center part can also show different colors?
Here is one way, it's not quite right but it's close. The idea is to make your own log spaced colour map. I do it by using linear interpolation between log spaced break points. It could probably be improved to use logarithmic interpolation (and maybe have better end cases):
First I simulate some data (open to suggestions for simulating data that better illustrates this example):
M = exp(rand(50)*10)
Then plot it (ignore the figure(2), that's just to make this match the image later)
n = 64
figure(2)
imagesc(M)
colormap(jet(n))
colorbar
now create a log spaced colour map
linMap = jet(n);
breaks = round(0:n/5:n)';
breaks(1) = 1;
cBreaks = linMap(breaks,:);
idx = 2.^(6:-1:1)';
idx(end) = 0; %// this part is hacky
logMap = interp1(((idx)/64)*max(M(:)),flipud(cBreaks),linspace(0,max(M(:)),64)); %// based on http://stackoverflow.com/questions/17230837/how-to-create-a-custom-colormap-programatically
figure(1)
imagesc(M)
colormap(logMap)
colorbar
results in
as you can see, the data remain unchanged and the data inspector still gives you back the same values but the colour bar is pretty much on a log scale now. I'd be interested to see what this looks like on your data.

Scatter plot color thresholding

I am trying to write a script to plot florescence intensity from some microscopy data as a scatter plot and threshold this data based on cells that respond greater than a certain amount in CFPMAX and plot these in green and cells that do not in red. When I try to plot this, I am unable to really assign proper colors to points and they end up being blue and red. I need each cell in the image to be assigned 4 values, (3 values for for each florescence channel and one value to determine whether or not it responded (green or red). Thus I was wondering if it was possible to assign the proper color to the 4th column of the matrix, or if I am going about this the wrong way all together. I have attached my code below.
MCHR=csvread('data1.csv');
MYFP=csvread('data2.csv');
MCFP=csvread('data3.csv');
CFPMAX=(max(MCFP))';
MCHMAX=(max(MCHR))';
YFPMAX=(max(MYFP))';
c=zeros(length(CFPMAX));
for i=1:length(c)
if CFPMAX(i)>40
c(i)='g'; %// green responders
else
c(i)='r'; %// red non-responders
end
end
MM=horzcat(MCHMAX,YFPMAX,CFPMAX,c);
scatter(MM(:,1),MM(:,2),100,MM(:,4),'filled','MarkerEdgeColor',[0 0 0])
title('Responders vs Non-Responders ')
xlabel('[TF1]') %// x-axis label
ylabel('[TF2]') %// y-axis label
As far as I can tell from the documentation, the input parameter c (assuming scatter(x,y,a,c,...)) can be one of:
A single character specifying a colour e.g. 'g' or 'r'. But just one single scalar colouring all of you points.
A single RGB triple colouring all of your points so [1,0,0] for red or [0,1,0] for green.
A three column matrix of RGB triples. This is likely what you want. I will demonstrate this to you.
A one column matrix of numbers which will colour the points according to a colormap. This one will also work for you but less explicitly. Incidentally, I would guess that this is option that MATLAB though your vector of characters was.
So in order to create the matrix of RGB triples you can modify your code to be
c=zeros(length(CFPMAX),3);
for i = 1:length(CFPMAX)
if CFPMAX(i)>40
c(i,:)=[0,1,0]; %// green responders
else
c(i,:)=[1,0,0]; %// red non-responders
end
end
However, you could actually do away with the for-loop completely in MATLAB and construct c in a vectorized approach using logical indexing:
c=zeros(length(CFPMAX),3);
c(CFPMAX > 40, 2) = 1; %// green responders
c(CFPMAX <= 40, 1) = 1; %// red responders
This is a more idiomatic way to do this in MATLAB.