I have a 1738x6 matrix (stock2), from which I plotted the 6th column (y-axis) and the 5th column (x-axis). I divided values from the 6th column to three categories; top 100 (red dots), bottom 100 (blue dots) and the rest (green dots). I have extracted these high and low values, they are called high100 and low100 in the code below.
I understand that I have only one y-value in the plot and that it contains the three different categories. But I can't find a way to create a legend for the plot so that it would show only red dots and blue dots from inside my y-value. All attempts either fail or show a green dot and the first label of the legend. Could someone kindly show how to create the desired legend? And as an extra question: why is there a [] in the scatter plot when using a color map?
figure
% color map
c = zeros(size(stock2,1),3);
middle = stock2;
[~,j] = sort(stock2(:,6),'ascend');
remove = j([1:100 end-99:end],:);
middle(remove,:)=[];
% other points are green so blue and red can be easily distinguished
% blue didn't seem to stand out from the default black dots
d=length(middle);
for i=1:d
c(i,2)=1;
end
% red
a=length(middle)+1;
aa=a+99;
for i=a:aa
c(i,1)=1;
end
% blue
b=length(middle)+length(high100)+1;
bb=b+99;
for i=b:bb
c(i,3)=1;
end
scatter(stock2(:,5),[middle(:,6); stock2(high100,6); stock2(low100,6)],[],c,'.')
title('Stock2')
xlabel('Closing Price')
ylabel('Volume')
legend('100 highest volume days','100 lowest volume days')
I simulated your idea on random data. You could check out documentation on hold, scatter and legend.
The brackets is in the place for size parameter, likely the default value were used then.
stock2=sortrows(rand(300,6),6,'descend');
figure()
h=scatter(reshape(stock2(:,5),100,[]),reshape(stock2(:,6),100,[]),'.');
[h.MarkerEdgeColor]=deal('b','g','r');
title('Stock2')
xlabel('Closing Price')
ylabel('Volume')
legend([h(1),h(3)],{'100 highest volume days','100 lowest volume days'}, ...
'Location','northoutside','Orientation','horizontal');
Related
I'm trying to plot contour using my computed data with limited contour labels and and colors as given in the top panel of this image:
But I ended up with a slightly different plot (see the plot in the bottom of the above image).
I want to modify my plot with the following three specifications
Restrict contour labels in 2 or 3 decimal places
Remove plot labels in the area where the contours are too close to each other.
Plot with two colors as in the first image
Here is my code:
f=load('fort.15');
ngridx=180;
ngridy=180;
x=f(:,3);
y=f(:,4);
z=f(:,5);
xlin=linspace(min(x),max(x),ngridx);
ylin=linspace(min(y),max(y),ngridy);
[X,Y]=meshgrid(xlin,ylin);
Z=griddata(x,y,z,X,Y,'linear');
[c,h] = contour(X,Y,Z,20);
set(h,'LineWidth',2,'LineColor',rgb('SteelBlue'),'ShowText','on',...
'LabelSpacing',800 )
axis([0 6 -5 7])
I'm not an expert in Matlab. Please help me get the right plot.
I'm attaching my data file here.
Well, I got only 2 of 3. Deine the level in which the color has to change (here scl) and you good to go:
scl = 6.5; % switch color level;
[c1,h1] = contour(X,Y,Z,scl:max(Z(:)),'Color','r');
hold on
[c2,h2] = contour(X,Y,Z,min(Z(:)):scl,'Color','b');
clabel(c2,h2);
axis([0 6 -5 7])
The idea here is to builed your plot from two contour objects, using hold on command. the vector scl:max(Z(:)) define the levvels to show in the first contour, and the get the red color and no lables. And a similar logic works for the secound contour.
If you want to lable some red contours, or remove lables from the blue ones, you need to replace h2 in the clabel function with a vector of the levels you want to lable. If you will be mo specific in the comments I'll update my answer.
Changing the formatting of the lables, is probably possible somehow, but it's really not trivial, so I left it by now.
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.
I'm trying to reverse my legend entries order based on reverse ordering of legend colors in matlab bar plot, but it doesn't seem to work in my case.
Basicaly what I have is a GUIDE figure, that draws a lot of plots and is able to save them to a .png file. The effect looks like this:
I've managed to change the text order by flipping legend upside-down, but I can't change legend colors order.
Here's what I've got:
[a b] = legend(legenda);
map = colormap; % current colormap
n = size(b,1);
z = linspace(size(map,1),1,n/3); % there is 1 text and 2 line elements for every data series, so I divide by 3
z = round(z); %otherwise matlab gets angry that indices must be real integers or logicals
MAP = map(z(:),:); % gets elements specified by linspace from colormap
So far everything works ok.
The b vector for two series looks like this (starts with 2.0, because it's reversed):
Text (P+C 200 2.0.dpt)
Text (P+C 200 1.0.dpt)
Line (P+C 200 2.0.dpt)
Line (P+C 200 2.0.dpt)
Line (P+C 200 1.0.dpt)
Line (P+C 200 1.0.dpt)
So I figured out (based on the linked code), I have to change the color variable for every line entry.
for k = (n/3 + 1):n
a1 = get(b(k),'Children');
set(a1,'FaceColor',MAP(ceil((k - n/3)/2), :));
end
Ceil and dividing by 2 gives the same index twice.
This code, however, does nothing.
I've checked whether flipping the legend vector may be the source of my problems, but the color order stays the same. I've tried with MAP vector too - no luck.
When I remove the semicolon after the a1 = ... line in the for loop, I get:
a1 =
0x0 empty GraphicsPlaceholder array.
How can I get this to work?
Also, is there any good way to make the legend not cover the plots after it's saved (see picture linked above)?
The way I save it is by creating a temporary figure with 'visible' 'off' and doing a copyobj of axes and legend, then saving. Otherwise it saves the whole figure.
The reason for which the code provided in the answer to reverse ordering of legend colors in matlab bar plot does not work in your case is because in that case (plot of a bar chart) the object in the legend are patches while in your plot they are lines.
The FaceColor only applies to patches and not to lines.
The easiest way to solve you probles should be to reverse the order in which you plot the lines "since the beginning" and, doing that, directly using the set of colors you extract from the colormap.
Nevertheless, if you wnat to work with the legend after having plotted the graph, beside revrsing the items in the legend you have also to change the color of the lines in the plot, if you want to use the set of color extracted from the colormap (at present in your picture, some lines share the same color).
To can solve the problem in two steps:
revert the string in the legend and change the colors of the line sin the plot
update the color of the lines in the legend accordingly
The two steps are required since, when you change the color of the lines in the plot, the items in the legend are updated automatically.
With reference to the code youy've posted: you can access to the legend's string and line's color through the array b.
You can access to the handles of the lines plotted as follows:
p_h=get(gca,'children')
Since you have plotted 10 lines, the array b is build as follows:
b(1:10) contains the handles to the string
b(11:2:30) contains the handles to the lines
b(12:2:30) contains the handles to the markers
To chenge the positin of the legend you can set its location property: to put it outside the axes you can set it either to:
'NorthOutside' outside plot box near top
'SouthOutside' outside bottom
'EastOutside' outside right
'WestOutside' outside left
'NorthEastOutside' outside top right (default for 3-D plots)
'NorthWestOutside' outside top left
'SouthEastOutside' outside bottom right
'SouthWestOutside' outside bottom left
In the following you can find the code in which the above suggestions have been implemented.
figure
% Initial plot
h_p=plot(0:.1:2*pi,bsxfun(#plus,sin([0:.1:2*pi]),[3:3:30]'),'linewidth',3)
% Initial legend
[h_leg,b]=legend(cellstr(strcat(repmat('sin(x)+',10,1),num2str([3:3:30]'))))
%
% YOUR CODE TO GENERATE NTHE NEW COLORS
%
map = colormap; % current colormap
n = size(b,1);
z = linspace(size(map,1),1,n/3); % there is 1 text and 2 line elements for every data series, so I divide by 3
z = round(z); %otherwise matlab gets angry that indices must be real integers or logicals
MAP = map(z(:),:); % gets elements specified by linspace from colormap
%
% Reverse the legend strings
%
rev_str=flipud(get(b(1:10),'string'))
%
% Get the handles of the lines in the legend
%
b1=b(11:2:30)
%
% Revere the string in the legend
% and update the color of the lne in the plot using the colors defined in
% MAP
%
p_h=get(gca,'children')
for i=1:10
set(b(i),'string',rev_str{i})
set(p_h(i),'color',MAP(i,:),'linewidth',3)
end
%
% Reverse the color of the lines in the legend
for i=1:10
set(b1(i),'color',MAP(i,:),'linewidth',3)
end
%
% Move the legend outside the axes
%
set(h_leg,'location','NorthEastOutside')
Original Plot
Updated plot
Hope this helps.
My x-axis is latitudes, y-axis is longitudes, and z-axis is the hist3 of the two. It is given by: z=hist3(location(:,1:2),[180,360]), where location(:,1) is the latitude column, and location(:,2) is the longitude column.
What I now want is, instead of plotting on a self-created XY plane, I want to plot the same on a worldmap. And instead of representing the frequency of each latitude-longitude pair with the height of the bars of hist3, I want to represent the frequency of each location by a heat map on top of the world map, corresponding to each latitude-longitude pair's frequency on the dataset. I have been searching a lot for this, but have not found much help. How to do this? I could only plot the skeleton of the worldmap like this:
worldmap world
load geoid
geoshow(geoid, geoidrefvec, 'DisplayType', 'texturemap');
load coast
geoshow(lat, long)
I don't know what the colour is being produced based on.
Additionally, if possible, I would also like to know how to plot the hist3 on a 3D map of the world (or globe), where each bar of the hist3 would correspond to the frequency of each location (i.e., each latitude-longitude pair). Thank you.
The hist3 documentation, which you can find here hist3, says:
Color the bars based on the frequency of the observations, i.e. according to the height of the bars. set(get(gca,'child'),'FaceColor','interp','CDataMode','auto');
If that's not what you need, you might wanna try it with colormap. More info about it here colormap. I haven't tried using colormap on histograms directly, so If colormap doesn't help, then you can try creating a new matrix manually which will have values in colors instead of the Z values the histogram originally had.
To do that, you need to first calculate the maximum Z value with:
maxZ=max(Z);
Then, you need to calculate how much of the colors should overlap. For example, if you use RGB system and you assign Blue for the lowest values of the histogram, then Green for the middle and Red for the High, and the green starts after the Blue with no overlap, than it will look artificial. So, if you decide that you will have, for example overlapping of 10 values, than, having in mind that every R, G and B component of the RGB color images have 255 values (8 bits) and 10 of each overlap with the former, that means that you will have 255 values (from the Blue) + 245 values (From the Green, which is 255 - 10 since 10 of the Green overlap with those of the Blue) + 245 (From the Red, with the same comment as for the Green), which is total amount of 745 values that you can assign to the new colored Histogram.
If 745 > maxZ there is no logic for you to map the new Z with more than maxZ values. Then you can calculate the number of overlaping values in this manner:
if 745 > maxZ
overlap=floor(255- (maxZ-255)/2)
end
At this point you have 10 overlapping values (or more if you still think that it doesn't looks good) if the maximum value of the Z is bigger than the total amount of values you are trying to assign to the new Z, or overlap overlapping values, if the maximum of Z is smaller.
When you have this two numbers (i.e. 745 and maxZ), you can write the following code so you can create the newZ.
First you need to specify that newZ is of the same size as Z. You can achieve that by creating a zero matrix with the same size as Z, but having in mind that in order to be in color, it has to have an additional dimension, which will specify the three color components (if you are working with RGB).
This can be achieved in the following manner:
newZ=zeros(size(Z),3)
The number 3 is here, as I said, so you would be able to give color to the new histogram.
Now you need to calculate the step (this is needed only if maxZ > The number of colors you wish to assign). The step can be calculated as:
stepZ=maxZ/Total_Number_of_Colors
If maxZ is, for example 2000 and Total_Number_of_Colors is (With 10 overlaping colours) 745, then stepZ=2.6845637583892617449664429530201. You will also need a counter so you would know what color you would assign to the new matrix. You can initialize it here:
count=0;
Now, finally the assignment is as follows:
For i=1:stepZ:maxZ
count=count+1;
If count>245
NewZ(Z==stepz,3)=count;
elseif count>245 && count<256
NewZ(Z==stepz,3)=count;
NewZ(Z==stepz,2)=count-245;
elseif count>255
NewZ(Z==stepz,2)=count-245;
elseif count>500 && count<511
NewZ(Z==stepz,2)=count-245;
NewZ(Z==stepz,1)=count-500;
else
NewZ(Z==stepz,1)=count-500;
end
end
At this point you have colored your histogram. Note that you can manually color it in different colors than red, green and blue (even if you are working in RGB), but it would be a bit harder, so if you don't like the colors you can experiment with the last bit of code (the one with the for loops), or check the internet of some other automatic way to color your newZ matrix.
Now, how do you think to superimpose this matrix (histogram) over your map? Do you want only the black lines to be shown over the colored histogram? If that's the case, than it can be achieved by resampling the NewZ matrix (the colored histogram) with the same precision as the map. For example, if the map is of size MxN, then the histogram needs to be adjusted to that size. If, on the other hand, their sizes are the same, then you can directly continue to the next part.
Your job is to find all pixels that have black in the map. Since the map is not binary (blacks and whites), it will be a bit more harder, but still achievable. You need to find a satisfactory threshold for the three components. All the lines under this threshold should be the black lines that are shown on the map. You can test these values with imshow(worldmap) and checking the values of the black lines you wish to preserve (borders and land edges, for example) by pointing the cross tool on the top of the figure, in the tools bar on every pixel which is of interest.
You don't need to test all black lines that you wish to preserve. You just need to have some basic info about what values the threshold should have. Then you continue with the rest of the code and if you don't like the result so much, you just adjust the threshold in some trial and error manner. When you have figured that this threshold is, for example, (40, 30, 60) for all of the RGB values of the map that you wish to preserve (have in mind that only values that are between (0,0,0) and (40,30,60) will be kept this way, all others will be erased), then you can add the black lines with the following few commands:
for i = 1:size(worldmap,1)
for j = 1:size(worldmap,2)
if worldmap(i,j,1)<40 && worldmap(i,j,2)<30 && worldmap(i,j,3)<60
newZ(i,j,:)=worldmap(i,j,:)
end
end
I want to note that I haven't tested this code, since I don't have Matlab near me atm, so It can have few errors, but those should be easily debugable.
Hopes this is what you need,
Cheers!
I want to plot a text file with 4 columns that first column in longitude,second in latitude, third is depth and forth is amount of displacement in each point.(it's related to a fualt)
-114.903874 41.207504 1.446784 2.323745
I want a plot to show the amount of displacement in each point (like images that we plot with imagesc),unfortunately "imagesc" command doesn't work for it.
how can I plot it?
Thanks for your attention
A simple way would be to use scatter3 and assign your displacements to be the colours. Note that you have to supply a size for this to work - I'm using [] (empty matrix) which will set it to default. If your four sets of values are four vectors of the same size, then it's just something like:
scatter3(lat,lon,depth,[],displacement, 'filled')
Values in displacement will be linearly mapped to the current colormap. 'filled' gives you filled markers rather than open ones (default marker is a circle but can be changed).
You can plot each point using plot3(longitude,latitude,depth). You can color each point according to the displacement in a for loop. The easiest way to do this is create a colormap, e.g. using jet and chosing the color according to the displacement.
figure;
hold on;
cmap = jet(256);
dispRange = [min(displacement),max(displacement)];
for k=1:size(longitude,2)
c = cmap(1+round(size(cmap,1)*(displacement(k)-dispRange(1))/dispRange(2)),:);
plot3(longitude(k),latitude(k),depth(k),'o', ...
'MarkerEdgeColor',c,'MarkerFaceColor',c);
end