Scatter plot color thresholding - matlab

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.

Related

How to get color gradient for Newton Method basin of attraction fractal

I am using MATLAB to go through a NxN grid in the complex plane, the x's are the real component and the y's are the imaginary component. For each point on this grid I am using it as a starting point for Newton's Method. Depending on which root it converges to it is assigned a number. This number is used with pcolor to plot the fractal.
It plots nicely, however, I want to also plot the color darkness depending on how long it takes to converge to the root. I am having trouble with pcolor. I was able to get the 3 colors for the 3 roots but I am not quite sure how to add more colors so that it is more descriptive.
Here is the code to get the plot after I have
xp - array of x points
yp - array of y points
col - NxN matrix that has either 1, 2, 3 (corresponds to which root)
% thresholds for color
caxis([1 3]);
% sets colors Red, Green, Blue
mycolors = [1 0 0; 0 1 0; 0 0 1];
colormap(mycolors);
% real component on x and imaginary component on y
h=pcolor(xp, yp, col');
set(h, 'LineStyle', 'none' );
So, how can I get there to be a gradient in pcolor, it seems that pcolor just kind of figures out all the colors itself. And caxis only allows boundaries for 2 colors.
Let me know if you want to see the full code of this program.
Thank you
Add the number of iterations it took to get to convergence as a color. Define the colors in HSV, and make the number of iterations map to the value S of HSV. That will give you a nice and meaningful color gradient without really changing the colors.
The pseudocode is:
For that, generate your 3 colors mycolors as you do. Change their color space as mycolorshsv=rgb2hsv(mycolors);
What you want now is to generate a bunch (your choice) of colors per color.
mycolorshsv=repelem(mycolorshsv,N,1);
Now lets generate N gradients per color.
mycolorshsv( 1: N,2)=linspace(0,1,N);
mycolorshsv( N+1:2*N,2)=linspace(0,1,N);
mycolorshsv(2*N+1:3*N,2)=linspace(0,1,N);
You want e.g. the longest iteration you obtained maxiter to be the brightest. We need to transform your col matrix from [1,2,3] to our current range now. For that, just
col=(col-1)*N+1; % make 1=>1, 2=>N, 3=>2*N;
col=col+iteration_matrix; %max(iteration_matrix) must be maxiter. You may want to normalize so min(iteration_matrix) is 0
Now simply set the colormap(mycolors);, and I would use imagesc instead of pcolor, but its less important.
Play with the range, and limits of the colro values for nicer maps. Often non-linear maps are also used, where a function f is applied to the iteration values, such as the sigmoid.
This is the technique used for the newton fractals you can find in wikipedia, such as:

Matlab legend colors don't match lines

Not sure what is going wrong here. I created a minimal example below:
clear
steps = 1:6;
labels = cell(length(steps),1);
xvals = 1:10;
fig = figure(1);
ax = axes('parent',fig);
hold on
for ii=1:length(steps)
s=steps(ii);
yvals = zeros(length(xvals)) + ii;
labels{ii} = ['gain = ' num2str(s)];
plot(ax,xvals,yvals);
end
legend(ax, labels);
hold off
And the result on my system is:
With less lines it can even put colors in the legend that aren't even on the plot. What is happening?!
Explanation of what's happening
The problem is in the line
yvals = zeros(length(xvals)) + ii;
This creates a 10x10 square matrix, not a 1x10 vector. plot then plots each column of that matrix against xvals. That causes a mixing up of colors which is probably not what you want.
It's interesting to analyze specifically what happens. Matlab plots each column of that matrix with a different color, using the default cycle of colors, which in Matlab R2014b onwards is
But all columns of that matrix are the same, so each covers (overwrites) the preceding one, and you only see the last color.
Now, the color cycle has 7 colors and the matrix has 10 columns. So in the first iteration the last plotted column (the one you see) has color mod(10,7)==3 (yellow). In the second iteration you cycle through 10 more colors starting from 3, that is, you get color mod(3+10,7)==6 (light blue). And so on. Thus the color you see in the figure depends on the loop index ii, but not in the way you expected.
legend creates its entries by picking the color (and line spec) of each plotted line, in the order in which they were plotted. There are 10*6==60 plotted lines, each corresponding to a column of a matrix. But since you only supply six strings to legend, it just picks the first six of those lines, and uses their colors to create the legend entries. Those colors follow the default order, as explained above.
None of those first six lines that make it into the legend are actually seen in the figure, because they are covered by other lines. But legend doesn't care about that. So you get six legend entries with the default color order, which of course doesn't match the lines you actually see in the graph.
Solution
From the above, the solution is clear: replaced the referred line by
yvals = zeros(1, length(xvals)) + ii;
to create yvals as a vector (not a matrix). That way you'll get the figure you expected:

How to find all the blue pixels and the location of the two boundaries in blue pixels?

I want to find per column the first and last blue pixels and them find the other boundary ( first and last blue pixel rows) inside this rows achieved before.
I made the alterations based on the previous answeers, but now I have this error when it tries to find the bif_first and last: Subscripted assignment dimension mismatch. bif_first2(2,z)=find(dx(:,z)==1,2,'first');
What is wrong? Please see my code below:
rgbImage_blue=zeros(size(movingRegistered));
lumen_first=zeros(1,size(movingRegistered,2)); lumen_last=zeros(1,size(movingRegistered,2)); bif_first=zeros(1,size(movingRegistered,2)); bif_last=zeros(1,size(movingRegistered,2)); bif_last2=zeros(2,size(movingRegistered,2)); bif_first2=zeros(2,size(movingRegistered,2));
blue=cat(3,0,0,255);
ix=all(bsxfun(#eq,movingRegistered,blue),3);% find all the blue pixels, and put them at 1 % logical array of where blue pixels are dx=[zeros(1,size(movingRegistered,2));diff(ix)]; % zeros to make the same number of columns and rows % the difference by row for all columns
nTops=sum(dx==1); % the transitions to blue
nBots=sum(dx==-1); % and from blue... % see if are consistent; if not, something's not right in image
if(nTops~=nBots), error('Mismatch in Top/Bottom'),end
for z=1:1:size(movingRegistered,2);
if nTops(1,z)==2; bifurcation=false;lumen=true; %only existis two boundaries no bifurcation
lumen_first(1,z)=find(ix(:,z)==1,1,'first');
lumen_last(1,z)=find(ix(:,z)==1,1,'last');
end
if nTops(1,z)>2;
bifurcation=true;
lumen_first(1,z)=find(ix(:,z)==1,1,'first');
lumen_last(1,z)=find(ix(:,z)==1,1,'last');
bif_first2(2,z)=find(dx(:,z)==1,2,'first');
bif_first(1,z)=bif_first2(2,z);
bif_last2(2,z)=find(dx(:,z)==1,2,'last');
bif_last(1,z)=bif_last2(2,z);
end
end
Your problem is you are comparing a n*m*3 image with a 3*1 vector. This operation is not defined.
Use this code:
blue=cat(3,0,0,250)
ix=all(bsxfun(#eq,movingRegistered,blue),3)
Images in Matlab use the third dimension for color, that's why I created blue to be a 1*1*3 vector. Now this vector is compared to the image, using bsxfun to expand the vector to match the image size. This operation compares each color channel individually, so all is used to collect the data for all three channels.

How to make a plot of a circle with dashed coloured border in MATLAB?

So i have this code to obtain radial gravity on Earth in function of the latitude:
G=6.6e-11;
M=5.976e24;
N=1000;
r=6371000;
w=2*pi/(24*3600);
for i=1:1:360
Theta=i*pi/180;
x(i)=i;
Vi(i)=-G*M/(r*r);
Phii(i)=r*w*w*sin(Theta)*sin(Theta);
gr(i)=Vi(i)+Phii(i);
end
plot(x,gr)
And it runs well. I want to make a graph of a circle made of a border of points (representing angle (i)) that change colour according to the value of gr(I want to set ranges of values of gr so that if the value obtained falls in a specific category, the point will have a specific colour).
I'm really new to MATLAB. Is there any possible way to make this?
Thanks in advance.
Here is the basic algorithm that I would do:
Determine how many colours you want to represent in your plot.
Create a colour map that has this many points for what you want to compute.
Determine a linearly increasing vector that varies from the minimum value of gr to the maximum value of gr with as many points as you have determined in Step #2
For each point in gr:
a. Determine which point yields the closest distance of this point to the vector in Step #3
b. Use this to index which colour you want.
c. Convert your angle into Cartesian co-ordinates, then plot this point with the colour found in Step 4b.
Let's tackle each point in detail.
Step #1 - Determine how many colours you want
This is pretty simple. Just determine how many colours you want. For now, let's assume that you want 20 colours, so:
num_colours = 20;
Step #2 - Create a colour map
What we can do is create a 20 x 3 matrix where each row determines a RGB tuple that denotes the amount of red, green and blue that each colour will occupy. MATLAB has built-in colour maps that will help you facilitate this. Here are all of the available colour maps that MATLAB has:
Each colour map has a special variable where you can provide it an integer number, and it'll return this 2D matrix of as many rows as the number you have provided. Each row gives you an RGB triplet which denotes the proportion of red, green and blue respectively. This matrix varies from the beginning of the colour map (top row) to the end (bottom row). All you have to do is use any name seen in the figure I've shown you above to create a colour map of that type. For example, if you wanted to get a bones colour map of 15 points, simply do:
colour_map = bones(15);
If you wanted to get a jet colour map of 25 points, simply do:
colour_map = jet(25);
.... you get the idea right? I like hsv so let's use the HSV colour map. You can use any colour map you want, but let's just stick with HSV for the sake of this example.
As such:
colour_map = hsv(num_colours);
Step #3 - Get that linearly increasing vector
You want certain colours to map into certain ranges, which is why this step is important. Given a value in gr, we want to figure out which colour we want to choose, and all you have to do is determine which value in gr is the closest to a value in this vector in Step #3. Therefore, you can use linspace to do this for you:
bin_vector = linspace(min(gr), max(gr), num_colours);
This will create a num_colours 1D array where the beginning of this array starts at the minimum value of gr and varies up to the maximum value of gr and each value is equally spaced such that we generate a num_colours array.
Step #4 - Bring it all home
Now, for each point in gr, we need to figure out which point is the closest to that vector in Step #3, we then use this to figure out the colour we want, then we need to convert our angle into Cartesian co-ordinates, then plot this point.
For illustration purposes, I'm going to assume your radius is 1. You can figure out how to get the x and y co-ordinates by simply doing cos(theta) and sin(theta), where theta is the angle you are examining. Since your gr array has 360 slots, I'm going to assume a resolution of 1 degree per slot. Therefore, you can easily do this in a for loop. Make sure you use hold on because we are going to call plot multiple times, and we don't want to overwrite the plot each time we call plot. You want all of the points to stay in the plot.
Without further ado:
figure; %// Create blank figure
hold on; %// Remember all points
%// For each point in our array...
for idx = 1 : 360
%// Find the closest slot between gr and our vector in Step #3
[~,min_idx] = min(abs(gr(idx) - bin_vector));
%// Grab this colour
clr = colour_map(min_idx,:);
%// Plot the point with this colour
plot(cosd(idx), sind(idx), '.', 'Color', clr, 'MarkerSize', 10);
end
Take notice that cosd and sind take in degrees as the input argument while cos and sin take in radians. Also, take note that I also changed the size of the point so that it's bigger. With the above logic, and your array in gr, this is what I get:
If you want the radius to get larger, all you have to do is multiply each cosd and sind term with your radius. Therefore, you can do something like this:
radius = 2;
for idx = 1 : 360
... %// Insert colour code here
...
...
%// Now plot
plot(radius*cosd(idx), radius*sind(idx), '.', 'Color', clr, 'MarkerSize', 10);
end
Just leave the code the same, but for the plot command, just multiply each x and y value by the radius.
Minor note in efficiency
The way you're calculating your gr array is using an inefficient for loop. There are some situations (like mine above) where you need to use a for loop, but for simple computations there is no need. It's better if you vectorize its creation. Therefore, you can get rid of the for loop to calculate your gr array like so:
x = 1 : 360;
Theta = x*pi/180;
Phii = r*w*w*sin(Theta).*sin(Theta);
Vi = -G*M/(r*r);
gr = Vi + Phii;
x is simply a vector going from 1 to 360, and that's done in the first line. Also, Vi is just an array which contains a single value and if you know how operations work between a scalar and an array, you can just do an addition with this single value and it'll add every value in your array by this much. As such, there's no need to create an array for Vi. Also, take a look at how I calculated Phii. I'm using element-by-element operations as Theta is now an array. You want to create an array Phii that takes corresponding values of Theta, and applies that formula to each value in Theta to produce Phii.
Hope this helps. Good luck!

Relative Markersize in Matlab plots

I am trying to plot a matrix where each element is in one out of two states. (ising model..)
Now, I would like to have one state colored and the other one white. That works using
[i,j] = find(S);
figure(gcf);
plothandle = scatter(i,j);
axis([0 nNodes+1 0 nNodes+1]);
when S holds the Spins and one state is equal to 0. (find returns a matrix of only non-zero elements)
To have a useful plot, the sizes of the markers should be 1x1 in RELATIVE coordinates. So if the whole matrix S would be in a state non-zero, everything would be colored.
However, it seems like Matlab only allows MarkerSizes in points or inches. How could I solve this?
One idea I had was, that I find out the point-size of the axes and then can easily calculate how big my markers should be. Then I would have to create a callback function if I want to zoom in and so on. Also, I have not yet found a way (without the image acq. toolbox) to find out the absolute size of my axes.
To clarify what I want: How could I plot a chessboard using a matrix with 1 for black and 0 for white fields?
For displaying data of this sort I generally prefer IMAGE or IMAGESC to PCOLOR since PCOLOR won't display the last row and column of the matrix when using faceted shading (the default). Also, IMAGE and IMAGESC flip the y axis so the image more intuitively matches what you think of when looking at a matrix (i.e. rows start from 1 at the top). You can visualize your matrix like this:
S = round(rand(20)); %# Sample 20-by-20 matrix of ones and zeroes
imagesc(S); %# Plot the image
colormap([1 1 1; 0 0 0]); %# Set the colormap to show white (zero elements) and
%# black (non-zero elements)
And here's a sample image:
Just as a suggestion, you can try using pcolor instead of `scatter' Example:
pcolor(hadamard(20))
colormap(gray(2))
axis ij
axis square