1
$\begingroup$

I am trying to find the Mathematica equivalent for Python Matplotlib's cmap option, to be used with ListPlot3D[].

Here is the situation. I want to supply (N,1)-sized arrays for the position x,y,z, and then an extra (N,1)-sized array clr that gets mapped onto some colour map that colours the different points. In Python, such data can be simply plotted using a scatter plot, and then coloured using the existing cmap option. For example, here is such a scatter plot coloured using a cmap acting on the array clr:

plotly plot

To get an interpolated, smooth version of the data, I prefer to plot it in Mathematica using ListPlot3D[]. For example, the following, created using a default z-based colour map: Mathematica plot

But I cannot figure out the equivalent of a custom cmap based on the array clr. Of course, I would like the colours to be interpolated smoothly as well. Is this possible?

$\endgroup$
5
  • $\begingroup$ There's an extensive list here of the colormaps supported by matplotlib, but I can't seem to find the colormap you used in there. Can you check your code and see what colormap (maybe the default?) was used? $\endgroup$ Aug 1, 2017 at 2:17
  • $\begingroup$ @J.M. Indeed, it is the default BlueGreenYellow colormap. $\endgroup$
    – ap21
    Aug 16, 2017 at 16:34
  • $\begingroup$ The second plot uses that, yes. I was asking about the one you generated in matplotlib. $\endgroup$ Aug 16, 2017 at 16:51
  • $\begingroup$ Ah, this is a Plotly 3d scatter plot. Not matplotlib. It uses the default Plotly colormap. See here: community.plot.ly/t/… $\endgroup$
    – ap21
    Aug 17, 2017 at 4:20
  • $\begingroup$ Well, the way you phrased it in your post was confusing. :) So, you'd like a surface produced with ListPlot3D[], but colored with (apparently) the "Portland" colormap? (Also, can you maybe post (a small sample of) your data to Pastebin?) $\endgroup$ Aug 17, 2017 at 4:36

2 Answers 2

1
$\begingroup$

Since the OP was unable/unwilling to provide data, I'm coming up with my own:

states = Entity["AdministrativeDivision", {#, "UnitedStates"}] & /@
         CountryData["UnitedStates", "Regions"];

pos = Reverse[First[EntityValue[#, "Position"]]] & /@ states;

logPop = Log10[N[QuantityMagnitude[EntityValue[#, "Population"]]]] & /@ states;

logGSP = Log10[QuantityMagnitude[EntityValue[#, "GrossStateProduct"]]] & /@ states;

For the purposes of this answer, I'll use the triplet of pos with logPop as the $x$-$y$-$z$ data, and use logGSPas the color map. Let's plot the data first as is:

dat = MapThread[Append, {pos, logPop}];
ListPlot3D[dat, ViewPoint -> {-2.4, -1.3, 2.}]

data plot

Now, here is how to color with respect to logGSP: we create an interpolating function by feeding the values of logGSP rescaled to $[0,1]$ along with the associated $x$ and $y$ to Interpolation[]:

ifun = Interpolation[MapThread[Append, {pos, Rescale[logGSP]}]];

(There is a warning thrown, but it is mostly harmless here.)

From here, we can use ifun along with an appropriate color function. Let's borrow the one in plotly used in the OP's picture:

portland = Blend[{RGBColor[4/85, 1/5, 131/255], RGBColor[2/51, 8/15, 62/85], 
                  RGBColor[242/255, 211/255, 56/255], RGBColor[242/255, 143/255, 56/255], 
                  RGBColor[217/255, 2/17, 2/17]}, #] &;

Now let's put it all together, along with Legended[] to provide a sense of what the colors map to:

rng = MinMax[logGSP];
Legended[ListPlot3D[dat, ColorFunction -> Function[{x, y, z}, portland[ifun[x, y]]], 
                    ColorFunctionScaling -> False, Lighting -> "Neutral", 
                    PlotStyle -> Specularity[0.9, 50], PlotTheme -> None, 
                    ViewPoint -> {-2.4, -1.3, 2.}], 
         BarLegend[{portland[Rescale[#, rng]] &, rng}]]

colorized data plot

For comparison purposes, here is the result if one uses Nearest[Thread[pos -> Rescale[logGSP]]] as the coloring function:

colorized data plot, take two

$\endgroup$
1
$\begingroup$

OK, I found an answer to this in a separate post: Smooth 4D (3D + color) plot from discrete points

The trick is to define a custom ColorFunction (not easy) as done in the link above:

data = Import["~/Downloads/furan-ks.sdat", "Table"];

nf = Nearest[data[[All, {1, 2, 3}]] -> Rescale[data[[All, 4]]]]

colfun = ColorData["Rainbow"]@First@nf[{#1,#2,#3}]&

data is a 4-column data array, and the definitions of nf and colfun are sufficient to paint the surface plot according to the value of the 4th column. How this works is explained in the link above.

As opposed to what is written in the above link, this custom ColorFunction works with both ListSurfacePlot3D and ListPlot3D (and other similar 3D functions, I presume). You just need to add the options ColorFunction -> colfun, ColorFunctionScaling -> False.

In the end, my plot looks as follows:

colored plot

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.