I am trying to create a figure like the one depicted in the third column of the following image:
Link for the image in case of backup.
Basically I have x and y positions of 200 particles and I have the MSD data for these 200 positions. I'd like MSD to be the value that should determine a color map for the particles in coordinates (x,y). So MSD should be like the height, or the z position corresponding to each particle in (x,y).
I am surprised at my incompetence, because I have been trying to solve this problem for the last couple of days but none of the Google searches gave me any result. The closest thing that I have found is the concept of "self-organizing map" in Matlab and R, but I do not know how to use R and Matlab's toolbox for SOM was utterly useful for my needs.
I tried the following code in Matlab and get the attached plot as a result:
clear all; close all; clc;
x = (dlmread('xdata.dat'))'; % x is 1x200 array
y = (dlmread('ydata.dat'))'; % y is 1x200 array
msd = (dlmread('msd_field.txt'))'; % msd is 1x200 array
[X,Y] = meshgrid(x,y);
Z = meshgrid(msd);
z = [X; Y; Z];
surf(z)
But I think this plot is not useful at all. What I want is a 2D scatter plot of (x,y) depicting particle positions and on top of that color code this scatter plot with the values stored in msd like the plot I showed in the beginning. How can I create this through Matlab, or any other visualization tool? Thank you in advance.
It is not clear whay you want to have. Here a scatter plot using ggplot2.
## some reproducible data
set.seed(1)
dat <- data.frame(
x = round(runif(200,-30,30),2),
y = round(runif(200,-2,30),2),
msd = sample(c(0,2,3),200,rep=T))
## scatter plot where the size/color of points depends in msd
library(ggplot2)
ggplot(dat) +
geom_point(aes(x,y,size=msd,color=msd)) +
theme_bw()
Related
I have three arrays of equal size: x, y, z. I want to plot z over x, y. Problems is, those x and y do not represent a rectangular region, such as what would be in case of using meshgrid function.
I know I can use something like scatter, but that would graphically only give me the points themselves. What I want is the filled, smoothed picture. So as opposed to this created by scatter:
I would like something like this:
Any suggestion how this can be done? I have a feeling the data must be smoothed out somehow via interpolation or something else prior to plotting which itself should be simple.
You can use griddata() to interpolate your x,y data on a regular grid and then you can use imagesc() to plot the result.
Here is a minimal example with a basic circle:
% INPUT
x = cos(0:0.1:2*pi);
y = sin(0:0.1:2*pi);
z = (0:0.1:2*pi);
% Create a regular grid that have the same boundary as your x,y data
[xx,yy] = meshgrid(linspace(-1,1,100),linspace(-1,1,100));
% Grid interpolation
zz = griddata (x, y, z, xx, yy);
% Plot
imagesc(zz)
colormap ([jet(); 1 1 1]); % I add a last [1 1 1] triplet to set the NaN color to white.
Noticed that this will only works if you keep the default interpolation method (which is a linear interpolation). The other method (cubic and nearest) will extend the domain of definition by analytic continuation.
I realized that the best approach would be some slight modification to what obchardon is proposing:
instead of the lines
imagesc(zz)
colormap ([jet(); 1 1 1]);
do this:
surf(xx, yy, zz);
shading interp;
colormap("jet");
This eliminates the problem with the black background. Then all it takes is just to rotate the camera with a mouse so that the 3d surface looked like 2d from above.
I'm trying to plot 3-dimensional vectors (x, y, z coordinates) onto a 3D coordinate system in R like in the picture below. Ideally, I would then like to construct 3d kernel density plots, also like in the image below.
Ideal result of vector plot and 3d kernel density plot
I have a matrix containing ~100 rows and one column for each coordinate (x, y , z). Initially, I tried arrow3D() from the plot3D package but I find the perspective to be sub-par, it's rather difficult to discern directions of the arrows from one perspective in the final plot. Next I tried the rgl package which gives me interactivity - great. Minimal working example:
library(rgl)
library(matlib)
data2 <- data.frame(replicate(6,rnorm(100))) #sample data set for minimum working example
colnames(data2) <- c("x_target", "y_target", "z_target", "x_start", "y_start", "z_start")
x1 <- data2$x_target - data2$x_start
y1 <- data2$y_target - data2$y_start
z1 <- data2$z_target - data2$z_start
vec <- (diag(6,3)) # coordinates for x, y and z axis
rownames(vec) <- c("X", "Y", "Z") # labels for x, y and z axis
z <- as.matrix((data.frame(x=x1, y=y1, z=z1)))
open3d()
vectors3d(vec, color=c(rep("black",3)), lwd=2, radius=1/25)
vectors3d(X=z, headlength=1/25)
(due to the random numbers generator the strange looking rods appear at different coordinates, not exactly like in the image i link to below)
The result of the code above is a version of the image link below. One set of coordinates produces a very strange looking more like rod object which is far longer then the coordinates would produce. If I plot the vectors individually, no such object is created. Anyone have any ideas why this happens? Also, if anyone has a tool (doesn't have to be R), that can create a 3D vector plot like in the first image, I'd be grateful. I find it to be very complicated in R, but I'm definitely a beginner.
Strange object to the right (long red rod that doesn't look like an arrow at all)
Thank you!
This is due to a bug in the matlib package, fixed in verson 0.9.2 of that package. I think you need to install it from Github instead of CRAN to get the bug fix:
devtools::install_github("friendly/matlib")
BTW, if you are using random numbers in a reproducible example, you can make it perfectly reproducible by something like
set.seed(123)
at the start (or some number other than 123). I saw reproducible problems with your example for set.seed(4).
I have a set of 3D coordinates here. The data has 52170 rows and 4 columns. Each row represent one point. The first column is point index number, increasing from 1 to 52170. The second to fourth columns are coordinates for x, y, and z axis, respectively. The first 10 lines are as follow:
seq x y z
1 7.126616 -102.927567 19.692112
2 -10.546907 -143.824966 50.77417
3 7.189214 -107.792068 18.758278
4 7.148852 -101.784027 19.905006
5 -14.65788 -146.294952 49.899158
6 -37.315742 -116.941185 12.316169
7 8.023512 -103.477882 19.081482
8 -14.641933 -145.100098 50.182739
9 -14.571636 -141.386322 50.547684
10 -15.691803 -145.66481 49.946281
I want to create a 3D scatter plot in which each point is added sequentially to this plot using R or MATLAB. The point represented by the first line is added first, then the point represented by the second line, ..., all the way to the last point.
In addition, I wish to control the speed at which points are added.
For 2D scatter plot, I could use the following code:
library(gganimate)
x <- rnorm(50, 5, 1)
y <- 7*x +rnorm(50, 4, 4)
ind <- 1:50
data <- data.frame(x, y, ind)
ggplot(data, aes(x, y)) + geom_point(aes(group = seq_along(x))) + transition_reveal(ind)
But I cannnot find information on how to do this for 3D scatter plot. Can anyone show me how this could be done? Thank you.
This is an answer for MATLAB
In a general fashion, animating a plot (or 3d plot, or scatter plot, or surface, or other graphic objects) can be done following the same approach:
Do the first plot/plot3/scatter/surf, and retrieve its handle. The first plot can incorporate the first "initial" sets of points or even be empty (use NaN value to create a plot with invisible data point).
Set axis limits and all other visualisation options which are going to be fixed (view point, camera angle, lightning...). No need to set the options which are going to evolove during the animation.
In a loop, update the minimum set of plot object properties: XData, YData ( ZData if 3D plot, CData if the plot object has some and you want to animate the color).
The code below is an implementation of the approach above adapted to your case:
%% Read data and place coordinates in named variables
csvfile = '3D scatter plot.csv' ;
data = csvread(csvfile,2) ;
% [optional], just to simplify notations further down
x = data(:,2) ;
y = data(:,3) ;
z = data(:,4) ;
%% Generate empty [plot3] objects
figure
% create an "axes" object, and retrieve the handle "hax"
hax = axes ;
% create 2 empty 3D point plots:
% [hp_new] will contains only one point (the new point added to the graph)
% [hp_trail] will contains all the points displayed so far
hp_trail = plot3(NaN,NaN,NaN,'.b','Parent',hax,'MarkerSize',2) ;
hold on
hp_new = plot3(NaN,NaN,NaN,'or','Parent',hax,'MarkerSize',6,'MarkerEdgeColor','r','MarkerFaceColor','g','LineWidth',2) ;
hold off
%% Set axes limits (to limit "wobbling" during animation)
xl = [min(x) max(x)] ;
yl = [min(y) max(y)] ;
zl = [min(z) max(z)] ;
set(hax, 'XLim',xl,'YLim',yl,'ZLim',zl)
view(145,72) % set a view perspective (optional)
%% Animate
np = size(data,1) ;
for ip=1:np
% update the "new point" graphic object
set( hp_new , 'XData',x(ip), 'YData',y(ip), 'ZData',z(ip) )
% update the "point history" graphic object
% we will display points from index 1 up to the current index ip
% (minus one) because the current index point is already displayed in
% the other plot object
indices2display = 1:ip-1 ;
set(hp_trail ,...
'XData',x(indices2display), ...
'YData',y(indices2display), ...
'ZData',z(indices2display) )
% force graphic refresh
drawnow
% Set the "speed"
% actually the max speed is given by your harware, so we'll just set a
% short pause in case you want to slow it down
pause(0.01) % <= comment this line if you want max speed
end
This will produce:
Hi I'm starting to use Octave and need help on how to plot x²+y² = 1.
I know that the figure is a cylinder.
I tried:
x= -10:0.1:10;
y = -10:0.1:10;
t = x²+y²;
but it won't work.
For this particular situation, you can just use the cylinder function.
cylinder([a,b])
will plot a cylinder whose radius at z==0 will be equal to a, and will vary continuously and smoothly until its radius at z==1 reaches b. In you case, you need to set a and b to 1, which is what happens by default when you call cylinder().
Now this will plot the cylinder with only z values in [0,1]. If you want to customize that range, you can just get the output from the function like this:
[xx yy zz]=cylinder([1,1]);
And now you can use this to obtain the plot that you want. For example,
surf(xx,yy,zz.*10);hold on; surf(xx,yy,-zz.*10);
will produce this:
I am using R to visualize some data. I am found RGL to be a great library for plotting points.
points3d(x,y,z)
where x = c(x1,x2, ...), y = c(y1,y2,...), z = c(z1,z2, ...) and x,y,z have the same length, is a great function for plotting large sets of data.
Now, I would like to plot ellipses, mixed in with the data. I have a characterization of ellipses by a center point C, a vector describing the major axis U, and a vector describing the minor axis V. I obtain points P on the boundary of the ellipse by
P = U*cos(t) + V*sin(t) (t ranges between 0 and 2*pi)
obtaining vectors, xt, yt, and zt. Then I can plot the ellipse with
polygon3d(xt,yt,zt)
It works fine, but I'm guessing everyone reading is cringing, and will tell me that this is a bad way to do this. Indeed it takes a couple seconds to render each ellipse this way.
I don't think the ellipse3d function from the RGL package works here; at the very least, I am not working a matrix of covariances, nor do I understand how to get the ellipse I want from this function. Also, it returns an ellipsoid, not an ellipse.
****** EDIT ************
For a concrete example that takes awhile:
library(rgl)
open3d()
td <- c(0:359)
t <- td*pi/180
plotEllipseFromVector <- function(c,u,v){
xt <- c[1] + u[1]*cos(t) + v[1]*sin(t)
yt <- c[2] + u[2]*cos(t) + v[2]*sin(t)
zt <- c[3] + u[3]*cos(t) + v[3]*sin(t)
polygon3d(xt,yt,zt)
}
Input center point, major, and minor axis you want. It takes just over 2 seconds for me.
On the other hand, if I change t to be 0,20,40,... 340, then it works quite fast.