I am having a specific problem. Firstly I am using octave. I have a dataset where every row is of the following format:
datarow = [ x, y, z, colourIndex];
The length of the dataset is irrelevant, but suppose it is 10. I want to be able to plot the 3d plot with every point having a colour of its specific color index. Of course I know that I can use a for loop and add every point individually, but I find it hard to believe that there isn't already some way to do that using vectors.
So far I have tried:
map = cool(); #init colormap
data = initializeData(); #initialize data
plot3(data(:,1),data(:,2),data(:,3),"c" , map(data(:,4))); #doesn't work
Any ideas if it's possible to do a one-liner for my issue?
Use scatter3:
N_colors = 64;
colormap(cool(N_colors));
# point positions (your data(:, 1:3))
[x, y, z] = peaks (20);
# these are the color indexes in the colormap (your data(:, 4))
c_index = fix(rand(size(x)) * N_colors);
marker_size = 8;
scatter3(x(:), y(:), z(:), marker_size, c_index(:))
Related
I am trying to create a 3D mesh of a specific building from points that I extracted from a lidar point cloud. I then created a matrix from the x, y and z values to feed into the as.mesh3d function from the rlg package and since its from a lidar survey, I have 27,000+ points for this one building. I run into an error when I try to create the mesh. I've copied in a sample of 20 points from the point cloud:
X <- c(1566328,1566328,1566328,1566328,1566328,1566327,1566327,1566327,
1566327,1566327,1566327,1566327,1566327,1566327,1566327,1566327,
1566326,1566326,1566326,1566326)
Y <- c(5180937,5180937,5180936,5180935,5180936,5180937,5180937,5180936,
5180936,5180935,5180935,5180935,5180936,5180936,5180937,5180938,
5180938,5180937,5180936,5180936)
Z <- c(19.92300028,19.98300046,19.93700046,19.88099962,19.93500046,19.99500046,
20.00400046,20.00600046,19.97199962,19.92499962,19.95400046,
19.99099991,20.01199991,19.97600020,19.95800008,19.93200008,
19.95300008,19.94800008,19.94300020,19.98399991)
#created a matrix
xyz <- matrix(c(X, Y, Z), byrow = TRUE, ncol = 3)
The problem arises when I try to create the mesh using as.mesh3d():
mesh <- as.mesh3d(xyz, y = NULL, Z = NULL, type = "triangle", col = "red")
This is what I get: Error in as.mesh3d.default(xyz, y = NULL, Z = NULL, type = "triangle", : Wrong number of vertices
The same error happens for the original dataset of 27000+ points despite all being of the same length.
I'm really not advanced in R and was hoping I could get some advice or solutions on how to get past this.
Thankyou
The as.mesh3d function assumes the points are already organized as triangles. Since you're giving it 20 points, that's not possible: it needs a multiple of 3 points.
There's a problem with your calculation of xyz: you say byrow = TRUE, but you're specifying values by column. Using
xyz <- cbind(X, Y, Z)
would work.
If I plot all of your points using text3d(xyz, text=1:20), it looks as though there are a lot of repeats.
There are several ways to triangulate those points, but they depend on assumptions about the surface. For example, if you know there is only one Z value for each (X, Y) pair, you could use as.mesh3d.deldir (see the help page) to triangulate. Here's the code and output for your sample:
dxyz <- deldir::deldir(X - mean(X), Y - mean(Y), z = Z)
# Warning message:
# In deldir::deldir(X - mean(X), Y - mean(Y), z = Z) :
# There were different z "weights" corresponding to
# duplicated points.
persp3d(dxyz, col = "red")
I had to subtract the means from X and Y because rounding errors caused it to look very bad without that: rgl does a lot of things in single precision, which only gives 7 or 8 decimal place accuracy.
I was working with 3 vectors x , y , z , each of length N (Assume N to be some large natural number, say 20000). In order to visualize this, I was able to plot this easily using the following R code :
library("plot3D")
lines3D(x, y, z, type = "l")
Now, I was thinking if we can make a little 3D animation (i.e. a 3D GIF) from the vectors x , y , z. Is it possible in R ?
NOTE : I've previously done 2D GIFs in R, with the help of packages like ggplot2 , gganimate , magick etc. However, I'm curious whether the same thing can be done for 3D data. Thanks in advance.
It is very simple to create .gif with the animation package (note it requires ‘ImageMagick’ or ‘GraphicsMagick’ to run). After the installation, you could do something like this (I assume that you want to display your plot with different point of view):
library(plot3D)
library(animation)
x <- runif(1000)
y <- x*2+runif(1000)
z <- sample(1:10,length(x),replace = T)*x/y
ani.options(interval=0.5,nmax=35)
saveGIF(for(t in seq(0,360,10)){
lines3D(x, y, z, type = "l",theta=t)
}, movie.name = "animation.gif")
How would I put a circle around certaiin variables in the following plot?
library(dagitty)
g = dagitty('dag{
A [pos="-1,0.5"]
W [pos="0.893,-0.422"]
X [adjusted,pos="0,-0.5"]
Y [pos="1,0.5"]
A -> Y
X -> A
X -> W
X -> Y
}')
png("mp.png", width = 500, height = 500,res=300)
plot(g)
dev.off()
In the web based tool you can indicate eg latent or adjusted and it changes the color of the circle, but this is not quite what I am looking for, although if it were possible to get these in the plot from R that would be sufficient, although I don't really like the way the variable is next to the circle in the web based version. I really wanted to circle observed variables and not circle unobserved ones.
I wrote a function which takes the points you want to circle as input, extracts the position of said points and circles them.
library(dagitty)
g = dagitty('dag{
A [pos="-1,0.5"]
W [pos="0.893,-0.422"]
X [adjusted,pos="0,-0.5"]
Y [pos="1,0.5"]
A -> Y
X -> A
X -> W
X -> Y
}')
circle_points <- function(points_to_circle, g) {
#few regexs to extract the points and the positions from "g"
#can surely be optimized, made nicer and more robust but it works for now
fsplit <- strsplit(g[1], "\\]")[[1]]
fsplit <- fsplit[-length(fsplit)]
fsplit <- substr(fsplit, 1, nchar(fsplit)-1)
fsplit[1] <- substr(fsplit[1], 6, nchar(fsplit))
vars <- sapply(regmatches(fsplit,
regexec("\\\n(.*?)\\s*\\[", fsplit)), "[", 2)
pos <- sub(".*pos=\\\"", "", fsplit)
#build dataframe with extracted information
res_df <- data.frame(vars = vars,
posx = sapply(strsplit(pos, ","), "[",1),
posy = sapply(strsplit(pos, ","), "[",2))
df_to_circle <- res_df[res_df$vars %in% points_to_circle,]
#y-position seems to be inverted and has to be multiplied by -1
points(c(as.numeric(df_to_circle$posx)),
c(as.numeric(df_to_circle$posy) * -1),
cex = 4)
}
plot(g)
circle_points(c("A", "Y"), g)
This results in:
You can of course work with the cex parameter, adding colors etc. It seems that the positioning of the circles is a bit off-centered so maybe manipulate the x and y positions in circle_points by a slim margin.
I did not find any information in dagitty, but bnlearn package can add circle/or other shape easily. But I just noticed you only want to add circle to observed traits rather than latent variables (better mentioned this in your title). Then my code might not be what you are looking for. I still attached the code here for your reference. Alternatively, you can distinguish observed/latent traits in different color. This can be easily done using bnlearn (https://www.bnlearn.com/examples/graphviz-plot/)
library(bnlearn)
tree = model2network("[X][W|X][A|X][Y|A:X]")
graphviz.plot(tree, main = "DAG structure", shape = "circle",
layout = "circo")
Is there a way to create a plot in IDL with a color gradient to it? What I'm looking for is similar to this Matlab question. The best I know how to do is to plot each segment of the line in a for loop, but this seems rather cumbersome:
x = float(indgen(11) - 5)
y = x ^ 2
loadct, 2, /silent
!p.background = 255
plot, x, y
for i = 0, 9 do begin
oplot, x(i:i+1), y(i:i+1), color = i * 20, thick = 4
endfor
I'm using IDL 8.2 if that makes a difference.
I had the same issue once and there seems to be no (simple) solution. Though I surrendered, you can try using a RGB-vector and the VERT_COLORS-keywords, provided by the PLOT function:
A vector of indices into the color table for the color of each vertex
(plot data point). Alternately, a 3xN byte array containing vertex
color values. If the values supplied are not of type byte, they are
scaled to the byte range using BYTSCL. If indices are supplied but no
colors are provided with the RGB_TABLE property, a default grayscale
ramp is used. If a 3xN array of colors is provided, the colors are
used directly and the color values provided with RGB_TABLE are
ignored. If the number of indices or colors specified is less than the
number of vertices, the colors are repeated cyclically.
That would change the appearence more discrete, but maybe it will help you.
I have a routine MG_PLOTS which can do this in direct graphics:
IDL> plot, x, y, /nodata, color=0, background=255
IDL> mg_plots, x, y, color=indgen(10) * 20, thick=4
Of course, it is just a wrapper for what you where doing manually.
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()