How to mark a point (I have x,y,z for it) in a 3D big data scatter plot with different color using matlab? - matlab

I have two 3D volume images and I want to locate one point from the first image (I have specific x, y, and z values for this point) and mark it with a different color. I mean how I can insert the values of x, y, and z and get this point in my graph inside all the points with a different color.

Here are 2 options:
Option 1
Use hold to overlay another scatter only with the points you want to color differently:
data = rand(100,3); % some data
p = randi(100); % choose some point
scatter3(data(:,1),data(:,2),data(:,3),'Fill')
hold on
% here you plot only one point (p):
scatter3(data(p,1),data(p,2),data(p,3),'r','Fill')
hold off
Option 2
If you want to color more than one point, and/or use different colors for your points, it may be better to set the color by the point when you call scatter in the first time:
data = rand(100,3); % some data
p = randi(size(data,1),5,1); % choose some points
c = ones(size(data,1),1); % default color
c(p) = 2:(numel(p)+1); % set different color for each points in p
col = lines(numel(p)+1); % set the colormap for the points
scatter3(data(:,1),data(:,2),data(:,3),[],col(c,:),'Fill')

Assuming you're using scatter3, you can just make your scatterplot, then use "hold on" and add a scatterplot with your single point in a different color that will cover the original point, e.g.:
hold on;
scatter3(x,y,z,'MarkerEdgeColor','k','MarkerFaceColor',[0 .75 .75]);

Related

How to color multiple lines based on their value?

I produced a plot that contains 50 curves and each of them corresponds to a specific value of a parameter called "Jacobi constant", so I have 50 values of jacobi constant stored in array called jacobi_cst_L1:
3.000900891023230
3.000894276927840
3.000887643313580
3.000881028967010
3.000874419173230
3.000867791975870
3.000861196034850
3.000854592397690
3.000847948043080
3.000841330136040
3.000834723697250
3.000828099771820
3.000821489088600
3.000814922863360
3.000808265737810
3.000801695858850
3.000795067776960
3.000788475204760
3.000781845363950
3.000775192199620
3.000768609354090
3.000761928862980
3.000755335851910
3.000748750854930
3.000742084743060
3.000735532899990
3.000728906460450
3.000722309400740
3.000715644446600
3.000709016645110
3.000702431180730
3.000695791284050
3.000689196186970
3.000682547292110
3.000675958537960
3.000669315388860
3.000662738391370
3.000656116141060
3.000649560630930
3.000642857256680
3.000636330415510
3.000629657944820
3.000623060310100
3.000616425935580
3.000609870077710
3.000603171772120
3.000596554947660
3.000590018845460
3.000583342259840
3.000576748353570
I want to use a colormap to color my curves and then show in a lateral bar the legend that show the numerical values corresponding to each color of orbit.
By considering my example image, I would want to add the array of constants in the lateral bar and then to color each curve according the lateral bar.
% Family of 50 planar Lyapunov orbits around L1 in dimensionless unit
fig = figure;
for k1 = 1:(numel(files_L1_L2_Ly_prop)-2)
plot([Ly_orb_filt(1).prop(k1).orbits.x],[Ly_orb_filt(1).prop(k1).orbits.y],...
"Color",my_green*1.1); hold on %"Color",my_green*1.1
colorbar()
end
axis equal
% Plot L1 point
plot(Ly_orb_filt_sys_data(1).x,Ly_orb_filt_sys_data(1).y,'.',...
'color',[0,0,0],'MarkerFaceColor',my_green,'MarkerSize',10);
text(Ly_orb_filt_sys_data(1).x-0.00015,Ly_orb_filt_sys_data(1).y-0.0008,'L_{1}');
%Primary bodies plots
plot(AstroData.mu_SEM_sys -1,0,'.',...
'color',my_blue,'MarkerFaceColor',my_blue,'MarkerSize',20);
text(AstroData.mu_SEM_sys-1,0-0.001,'$Earth + Moon$','Interpreter',"latex");
grid on;
xlabel('$x$','interpreter','latex','fontsize',12);
ylabel('$y$','interpreter','latex','FontSize',12);
How can I color each line based on its Jacobi constant value?
You can use any colour map to produce a series of RGB-triplets for the plotting routines to read (Or create an m-by-3 matrix with elements between 0 and 1 yourself):
n = 10; % Plot 10 lines
x = 1:15;
colour_map = jet(n); % Get colours. parula, hsv, hot etc.
figure;
hold on
for ii = 1:n
% Plot each line individually
plot(x, x+ii, 'Color', colour_map(ii, :))
end
colorbar % Show the colour bar.
Which on R2007b produces:
Note that indexing into a colour map will produce linearly spaced colours, thus you'll need to either interpolate or calculate a lot to get the specific ones you need. Then you can (need to?) modify the resulting colour bar's labels by hand to reflect your input values. I'd simply use parula(50), treat its indices as linspace(jacobi(1), jacobi(end), 50) and then my_colour = interp1(linspace(jacobi(1), jacobi(end), 50), parula(50), jacobi).
So in your code, rather than using "Color",my_green*1.1 for each line, use "Color",my_colour(kl,:), where my_colour is whatever series of RGB triplets you have defined.

Setting axis limit for plot

I want to set the limit for X axis in this plot from 0 to 325. When i am using xlim to set the limits (commented in the code). It doesn't work properly. When i use xlim, the entire structure of plot changes. Any help will be appreciated.
figure
imagesc(transpose(all_area_for_visual));
colormap("jet")
colorbar('Ticks',0:3,'TickLabels',{'Home ','Field','Bad house','Good house'})
xlabel('Time (min)')
tickLocs = round(linspace(1,length(final_plot_mat_missing_part(2:end,1)),8));
timeVector = final_plot_mat_missing_part(2:end,1);
timeForTicks = (timeVector(tickLocs))./60;
xticks(tickLocs);
xticklabels(timeForTicks);
%xlim([0 325]);
ylabel('Car identity')
yticks(1:length(Ucolumnnames_fpm))
yticklabels([Ucolumnnames_fpm(1,:)])
If I get you right, you want to plot only part of the data in all_area_for_visual, given by a condition on tickLocs. So you should first condition the data, and then plot it:
% generate the vector of x values:
tickLocs = round(linspace(1,length(final_plot_mat_missing_part(2:end,1)),8));
% create an index vector (of logicals) that marks the columns to plot from the data matix:
validX = tickLocs(tickLocs<=325);
% plot only the relevant part of the data:
imagesc(transpose(all_area_for_visual(:,validX)));
% generate the correct ticks for the data that was plotted:
timeVector = final_plot_mat_missing_part(2:end,1);
timeForTicks = (timeVector(tickLocs(validX)))./60;
xticks(tickLocs(validX));
% here you continue with setting the labels, colormap and so on...
imagesc puts the data in little rectangles centered around integers 1:width and 1:height by default. You can specify what the x and y locations of each data point by adding two vectors to the call:
imagesc(x,y,transpose(all_area_for_visual));
where x and y are vectors with the locations along the x and y axes you want to place the data.
Note that xlim and xticks don’t change the location of the data, only the region of the axis shown, and the location of tick marks along the axis. With xticklabels you can change what is shown at each tick mark, so you can use that to “fake” the data locations, but the xlim setting still applies to the actual locations, not to the labels assigned to the ticks.
I think it is easier to plot the data in the right locations to start with. Here is an example:
% Fake your data, I'm making a small matrix here for illustration purposes
all_area_for_visual = min(floor(cumsum(rand(20,5)/2)),3);
times = linspace(0,500,20); % These are the locations along the time axis for each matrix element
car_id_names = [4,5,8,15,18]; % These are the labels to put along the y-axis
car_ids = 1:numel(car_id_names); % These are the locations to use along the y-axis
% Replicate your plot
figure
imagesc(times,car_ids,transpose(all_area_for_visual));
% ^^^ ^^^ NOTE! specifying locations
colormap("jet")
colorbar('Ticks',0:3,'TickLabels',{'Home ','Field','Bad house','Good house'})
xlabel('Time (min)')
ylabel('Car identity')
set(gca,'YTick',car_ids,'YTickLabel',car_id_names) % Combine YTICK and YTICKLABEL calls
% Now you can specify your limit, in actual time units (min)
xlim([0 325]);

Displaying multiple figures with differents colors

I have a matlab code that generates 3D points , so I want to plot each 3D point with different colors.
My last code for generat all points are
figure(i),plot3(mx,my,mz,'r*');
and this one plot all peaks but with same color which are red.
instead of figure(i),plot3(mx,my,mz,'r*'); you can plot each datapoint separately and assign a different color using the property 'Color' of the plot3.
such an example would be:
figure(i),hold on
for j=1:length(mx)
plot3(mx(j),my(j),mz(j),'Color',rand(1,3));
end
hold off
The way each point is coloured is up to you just change the rand to something that makes sense.
What about using e.g. hsv:
M = length(mx);
cols = hsv(M); % specify M colors by hsv
figure(i);
hold on;
for pIdx = 1:M
plot3(mx(pIdx),my(pIdx),mz(pIdx),'Color',cols(pIdx,:));
end

How to mark points in a plot that are over a specified value in Matlab?

Say I have a data set with x values of longitude and Y values of 1 to 100. How can I plot the whole data set and represent all Y values over 90 with a different symbol?
Thanks for the help!
The easiest way would be to plot the sets separately, and specify a different symbol for each set i.e.
plot(x(Y<=90),Y(Y<=90),'bx',x(Y>90),Y(Y>90),'bo');
You could also do different colors. The scatter function has the ability to specify a different color for each point with the syntax scatter(x,y,s,c). For your example, you could do:
% make data
rng(0,'twister'); theta = linspace(0,2*pi,150);
x = sin(theta) + 0.75*rand(1,150); x = x*100;
y = cos(theta) + 0.75*rand(1,150); y = y*100;
mask = y>90;
% plot with custom colors for each point
c = zeros(numel(x),3); % matrix of RGB colorspecs
c(mask,:) = repmat([1 0 0],nnz(mask),1); % red
c(~mask,:) = repmat([0 0 1],nnz(~mask),1); % blue
scatter(x,y,10,c,'+');
Or instead of and RGB colorspec matrix, you can index into the current colormap. This allows you to get a nice smooth variation with some value:
scatter(x,y,10,y+x,'o') % x+y is mapped to indexes into default colormap, jet(64)
You can combine this color mapping with the approach of separating the data into two sets to also get different markers. Split the data, plot the first set with scatter as above, hold on, and plot the second set with a different marker. For example,
cv = x+y; % or just y, but this is an interesting example
scatter(x(mask),y(mask),10,cv(mask),'+');
hold on
scatter(x(~mask),y(~mask),10,cv(~mask),'o');
The result is different marker styles, where '+' is used where y>90 and '+' elsewhere, and different colors, where color is determined by mapping the values of cv=x+y onto the current colormap. The idea here is to look at 2 different modes of variations, but you could just use cv=y.

MATLAB, Filling in the area between two sets of data, lines in one figure

I have a question about using the area function; or perhaps another function is in order...
I created this plot from a large text file:
The green and the blue represent two different files. What I want to do is fill in the area between the red line and each run, respectively. I can create an area plot with a similar idea, but when I plot them on the same figure, they do not overlap correctly. Essentially, 4 plots would be on one figure.
I hope this makes sense.
Building off of #gnovice's answer, you can actually create filled plots with shading only in the area between the two curves. Just use fill in conjunction with fliplr.
Example:
x=0:0.01:2*pi; %#initialize x array
y1=sin(x); %#create first curve
y2=sin(x)+.5; %#create second curve
X=[x,fliplr(x)]; %#create continuous x value array for plotting
Y=[y1,fliplr(y2)]; %#create y values for out and then back
fill(X,Y,'b'); %#plot filled area
By flipping the x array and concatenating it with the original, you're going out, down, back, and then up to close both arrays in a complete, many-many-many-sided polygon.
Personally, I find it both elegant and convenient to wrap the fill function.
To fill between two equally sized row vectors Y1 and Y2 that share the support X (and color C):
fill_between_lines = #(X,Y1,Y2,C) fill( [X fliplr(X)], [Y1 fliplr(Y2)], C );
You can accomplish this using the function FILL to create filled polygons under the sections of your plots. You will want to plot the lines and polygons in the order you want them to be stacked on the screen, starting with the bottom-most one. Here's an example with some sample data:
x = 1:100; %# X range
y1 = rand(1,100)+1.5; %# One set of data ranging from 1.5 to 2.5
y2 = rand(1,100)+0.5; %# Another set of data ranging from 0.5 to 1.5
baseLine = 0.2; %# Baseline value for filling under the curves
index = 30:70; %# Indices of points to fill under
plot(x,y1,'b'); %# Plot the first line
hold on; %# Add to the plot
h1 = fill(x(index([1 1:end end])),... %# Plot the first filled polygon
[baseLine y1(index) baseLine],...
'b','EdgeColor','none');
plot(x,y2,'g'); %# Plot the second line
h2 = fill(x(index([1 1:end end])),... %# Plot the second filled polygon
[baseLine y2(index) baseLine],...
'g','EdgeColor','none');
plot(x(index),baseLine.*ones(size(index)),'r'); %# Plot the red line
And here's the resulting figure:
You can also change the stacking order of the objects in the figure after you've plotted them by modifying the order of handles in the 'Children' property of the axes object. For example, this code reverses the stacking order, hiding the green polygon behind the blue polygon:
kids = get(gca,'Children'); %# Get the child object handles
set(gca,'Children',flipud(kids)); %# Set them to the reverse order
Finally, if you don't know exactly what order you want to stack your polygons ahead of time (i.e. either one could be the smaller polygon, which you probably want on top), then you could adjust the 'FaceAlpha' property so that one or both polygons will appear partially transparent and show the other beneath it. For example, the following will make the green polygon partially transparent:
set(h2,'FaceAlpha',0.5);
You want to look at the patch() function, and sneak in points for the start and end of the horizontal line:
x = 0:.1:2*pi;
y = sin(x)+rand(size(x))/2;
x2 = [0 x 2*pi];
y2 = [.1 y .1];
patch(x2, y2, [.8 .8 .1]);
If you only want the filled in area for a part of the data, you'll need to truncate the x and y vectors to only include the points you need.