Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plotly - different color surfaces

I'm trying to plot several surfaces, each of a different color, in Plotly for Python.

Specifically, a surface shows the predicted reward function for taking an action at different points in phase space. Since I have several possible actions at each point, each is a different surface. I'd like to color each surface uniquely, but independent of the x,y, or z coordinate.

I've tried to follow answer in R, but I can't figure out what I've done wrong. I always get the same blue color. Since I'm using PyPlot in other parts of my code, I'm choosing colors from the default matplotlib tableau.

Here's a basic example with toy data.

import matplotlib.pyplot as plt
import numpy as np
import plotly.graph_objs as go
import plotly.offline as off

off.init_notebook_mode()

make_int = np.vectorize(int)
cmap = plt.get_cmap("tab10")

saddle = np.array([[x**2-y**2 for x in np.arange(-10,11)] for y in np.arange(-10,11)])
paraboloid = np.array([[x**2 + y**2-100 for x in np.arange(-10,11)] for y in np.arange(-10,11)])

mycolors_a = make_int(256*np.array(cmap(1)[0:3])).reshape((1, 1,-1)).repeat(21, axis = 0).repeat(21, axis =1)
mycolors_b = make_int(256*np.array(cmap(2)[0:3])).reshape((1, 1,-1)).repeat(21, axis = 0).repeat(21, axis =1)
trace_a = go.Surface(z = saddle, surfacecolor = mycolors_a, opacity = .7, showscale = False, name = "Trace A")
trace_b = go.Surface(z = paraboloid, surfacecolor = mycolors_b, opacity = .7, showscale = False, name = "Trace B")

data = [trace_a, trace_b]
off.iplot(data)

Produces the following:

Output Sample

I should see a blue saddle and an orange paraboloid, but I don't. Note that even if I change the argument to cmap, I always get the same blue color. Thanks for your help!

like image 215
Jake Stevens-Haas Avatar asked Jan 01 '19 02:01

Jake Stevens-Haas


People also ask

How do you change the color of a scatter plot in Plotly?

For that you may use the color_discrete_sequence argument. This argument is to use a custom color paletter for discrete color factors, but if you are not using any factor for color it will use the first element for all the points in the plot.

What are 3D surface plots?

Introduction. Surface plots are diagrams of three-dimensional data. Rather than showing the individual data points, surface plots show a functional relationship between a designated dependent variable (Y), and two independent variables (X and Z). The plot is a companion plot to the contour plot.

How do you plot a 2D surface in Python?

Surface plots are created by using ax. plot_surface() function. where X and Y are 2D arrays of points of x and y while Z is a 2D array of heights.

How do you plot a 3D surface in Python?

We could plot 3D surfaces in Python too, the function to plot the 3D surfaces is plot_surface(X,Y,Z), where X and Y are the output arrays from meshgrid, and Z=f(X,Y) or Z(i,j)=f(X(i,j),Y(i,j)). The most common surface plotting functions are surf and contour.


1 Answers

The documentation is a bit cryptic here.

surfacecolor

(list, numpy array, or Pandas series of numbers, strings, or datetimes.)

Sets the surface color values, used for setting a color scale independent of z.

I never managed to put a list of strings, i.e. color values like 'rgb(0.3, 0.5, 0)', or RGB tuples in it.

But you can define your own color scale with the needed colors.

colorscale = [[0, 'rgb' + str(cmap(1)[0:3])], 
              [1, 'rgb' + str(cmap(2)[0:3])]]

and then provide a numeric array with the same dimensions as your plotted values.

colors_saddle = np.zeros(shape=saddle.shape)    

All values are set to 0 and will therefore map to the first color in your colorscale. The same for the next color.

In addition you need to set cmax and cmin manually.

Complete code

import numpy as np
import matplotlib.pyplot as plt
import plotly.graph_objs as go
import plotly.offline as off


off.init_notebook_mode()

make_int = np.vectorize(int)
cmap = plt.get_cmap("tab10")

saddle = np.array([[x**2-y**2 for x in np.arange(-10,11)] for y in np.arange(-10,11)])
paraboloid = np.array([[x**2 + y**2-100 for x in np.arange(-10,11)] for y in np.arange(-10,11)])

colors_saddle = np.zeros(shape=saddle.shape)    
colors_paraboloid = np.ones(shape=paraboloid.shape)    

colorscale = [[0, 'rgb' + str(cmap(1)[0:3])], 
              [1, 'rgb' + str(cmap(2)[0:3])]]

trace_a = go.Surface(z=saddle, 
                     surfacecolor=colors_saddle, 
                     opacity=.7, 
                     name="Trace A",
                     cmin=0,
                     cmax=1,
                     colorscale=colorscale)
trace_b = go.Surface(z=paraboloid, 
                     surfacecolor=colors_paraboloid, 
                     opacity=.7, 
                     name="Trace B", 
                     cmin=0,
                     cmax=1,
                     showscale=False,
                     colorscale=colorscale)

data = [trace_a, trace_b]
off.iplot(data)

enter image description here

like image 120
Maximilian Peters Avatar answered Oct 10 '22 04:10

Maximilian Peters