2
$\begingroup$

I want to map an electrostatic potential onto a density map.

How can I color a single contour from a ListContourPlot3D using the values from another list?

  1. Make a 3D contour plot from a list of electron density values, of which I only need one contour.

  2. Color the single contour based on the electrostatic potential density at that point. (Need help on this.)

I have this so far:

Den = Import["Density.dat", "Table"]; (* Contains, {x, y, z, Density} pointS *)

EP = Import["ElectrostaticPotential.dat", "Table"]; (* Contains, {x, y, z, EP} point *)

ListContourPlot3D[Den, 
  Contours -> {0.05}, Mesh -> None, 
  ColorFunction -> ColorData[Function[{x, y, z}, Hue[EP]]]]

I can't seem the find the right way to write the ColorFunction. Please help.

$\endgroup$
  • 2
    $\begingroup$ Can you include samples of your density and electrostatic potential data? Or perhaps put them into a pastebin for people to download? $\endgroup$ – MarcoB Feb 4 '16 at 1:01
  • $\begingroup$ Can one assume that the $(x, y, z)$ grid at which the values are calculated will be the same for the density and electrostatic potential data sets? $\endgroup$ – MarcoB Feb 4 '16 at 1:18
  • $\begingroup$ If you have Mathematica 10.2 or higher, you could also try ListSliceDensityPlot3D. $\endgroup$ – Rahul Feb 4 '16 at 6:26
  • $\begingroup$ I just don't see how "This question cannot be answered without additional information" is true in this case. The question is clear, "How can I color a single contour from a ListContourPlot3D using the values from another list", given that both lists are in the form {x,y,z, f[x,y,z]}. The actual data being plotted is irrelevant. $\endgroup$ – Jason B. Feb 4 '16 at 13:54
  • $\begingroup$ If I understand it correctly, it's a duplicate of Smooth 4D (3D + color) plot from discrete points $\endgroup$ – Jens Feb 4 '16 at 15:20
8
$\begingroup$

In the absence of your data, I'll just use some data that I make up. One of these is an example from the help on ListContourPlot3D and one is a 3D-Gaussian,

list1 = Table[{x, y, z, x^2 + y^2 - z^2}, {x, -1, 1, .05}, {y, -1, 
     1, .05}, {z, -1, 1, .05}]~Flatten~2;
list2 = Table[{x, y, z, 
     2 Exp[-3^2 ((x - .3)^2 + (y - .3)^2 + (z - .3)^2)]}, {x, -1, 
     1, .01}, {y, -1, 1, .01}, {z, -1, 1, .01}]~Flatten~2;

These are structured like your data, in the form of {x,y,z,f[x,y,z]} tuples. Here are their contour plots,

ListContourPlot3D[#, Contours -> {0.3}, 
   PlotRange -> {{-1, 1}, {-1, 1}, {-1, 1}}] & /@ {list1, list2}

enter image description here

So to do this using ColorFunction, which is my preferred way to do it, you need to have a function to use, not a list. We can make an interpolation function from the data, and we can use this opportunity to rescale it so that the values lie between 0 and 1.

 func = Module[{rescaledlist = list2},
  rescaledlist[[All, 4]] = 
   rescaledlist[[All, 4]]/Max[rescaledlist[[All, 4]]];
  rescaledlist = {{#1, #2, #3}, #4} & @@@ rescaledlist;
  Interpolation[rescaledlist]
  ]

enter image description here

And now we use this function inside the ColorFunction

ListContourPlot3D[list1, Contours -> {0.3},
 ColorFunction -> Function[{x, y, z},
   Hue[
    func[x, y, z]
    ]],
 ColorFunctionScaling -> False, Mesh -> None, MaxPlotPoints -> 40]

enter image description here

We can get basically the same thing from ListSliceDensityPlot3D but it is a bit trickier. Look at the usage information,

?ListSliceDensityPlot3D

enter image description here

So we need to define a surface object from a ListContourPlot3D. Thanks to Szabolcs for figuring out how to do this. This command gives an error, but produces the right output,

surf = DiscretizeGraphics@
  Normal@ListContourPlot3D[list1, Contours -> {0.3}, 
    MaxPlotPoints -> 40];

enter image description here

Then we take some care to get the color function scaled properly, and

ListSliceDensityPlot3D[list2, surf, 
 ColorFunction -> (Hue[#/Max[list2[[All, 4]]]] &), 
 ColorFunctionScaling -> False]

enter image description here

I prefer the output by using the scaled colorfunction on ListContourPlot3D, and I think the workflow is simpler, but this option works as well.

On a side note, I always recommend avoiding the rainbow color palette (be it the Jet or Hue variants). I'm partial to the Parula color map in Matlab, which you can define in Mathematica via <<"http://pastebin.com/raw.php?i=sqYFdrkY";. If you replace Hue[func[x, y, z]] above with ParulaCM[1.5 func[x, y, z]] then you get the nice plot below

enter image description here

$\endgroup$
  • 1
    $\begingroup$ You could also just use one of Mathematica's many nice built-in color schemes, like ColorData["StarryNightColors"][func[x, y, z]]. $\endgroup$ – Rahul Feb 4 '16 at 18:06
  • $\begingroup$ That looks like a good color scheme I haven't used before. I often like to build up my own functions and don't notice the built in stuff as much $\endgroup$ – Jason B. Feb 4 '16 at 19:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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