Eric
Eric

Reputation: 39

Plotting a 3D volume plot in R using discrete 3D points

I'm trying to create a volume plot in R that will show the smoothed density of points in 3D space. I'm using plotly to plot with scatter3D at the moment.

  df = data.frame(a = sample(seq(.5,.8,.001),100), 
              b = sample(seq(0,.5,.001),100), 
              c = sample(seq(0,.3,.001),100), 
              value = sample(seq(0,1,.01),100))


plot_ly(df, x = ~a, y = ~b, z = ~c, type = 'scatter3d')

enter image description here

Setting type to 'mesh3d' works to connect these points as a surface in 3d space.

  plot_ly(df, x = ~a, y = ~b, z = ~c, type = 'mesh3d')

enter image description here

However, trying to set the type to 'volume' gives me a blank plot each time.

  plot_ly(df, x = ~a, y = ~b, z = ~c, value = ~value, type = 'volume', 
          isomin = 0, isomax = 1, opacity = 1)

enter image description here

The documentation is here: https://plotly.com/r/reference/volume/ and specifies:

Draws volume trace between iso-min and iso-max values with coordinates given by four 1-dimensional arrays containing the value, x, y and z of every vertex of a uniform or non-uniform 3-D grid. Horizontal or vertical slices, caps as well as spaceframe between iso-min and iso-max values could also be drawn using this trace.

The python version of plotly provides an example: https://plotly.com/python/3d-volume-plots/ but I don't know where I'm missing the conversion to R. I've included the extra value dimension for volume plots, but it doesn't seem to do anything.

Upvotes: 2

Views: 1157

Answers (1)

Hugo Kerstens
Hugo Kerstens

Reputation: 96

Unlike the documentation of plotly where it states you can use non-uniform grids with a volume, plotting 3d volumes with isomin and isomax is actually not possible. Having a single coordinate which is non-uniform invalidates the whole plot. I struggled with the same issue for ages, wondering why my plots keep ending up blank.

To demonstrate, first create a plot with a uniform grid. For example, use the Python example from the resource you linked: https://plotly.com/python/3d-volume-plots/. (It doesn't matter that it's the Python API, rendering the plots is language independent).

import plotly.graph_objects as go
import numpy as np
X, Y, Z = np.mgrid[-8:8:40j, -8:8:40j, -8:8:40j]
values = np.sin(X*Y*Z) / (X*Y*Z)

fig = go.Figure(data=go.Volume(
    x=X.flatten(),
    y=Y.flatten(),
    z=Z.flatten(),
    value=values.flatten(),
    isomin=0.1,
    isomax=0.8,
    opacity=0.1, # needs to be small to see through all surfaces
    surface_count=17, # needs to be a large number for good volume rendering
    ))
fig.show()

This should show a plot. Next, change the coordinate of one point:

X[0, 0, 0] += 1

And tada: it no longer works and shows an empty plot.

Upvotes: 1

Related Questions