Skip to main content

plotting - Improve Plot3D resolution near max/mins


I have the following function


$$V(r) = \sum_{i=1}^N 4 \epsilon_i \left(\frac{\sigma_i^{12}}{\|r-r_{0i}\|^{12}}-\frac{\sigma_i^6}{\|r-r_{0i}\|^6}\right)$$


which -for those interested- corresponds to a sum of Lennard-Jones potentials, with the following real life set of parameters


sig = {0.329633, 0.0400014, 0.405359, 0.235197, 0.387541, 0.235197,
0.235197, 0.387541, 0.235197, 0.235197, 0.387541, 0.235197,
0.235197, 0.387541, 0.235197, 0.235197, 0.329633, 0.0400014,
0.0400014, 0.0400014, 0.356359, 0.302906, 0.329633, 0.0400014,
0.387541, 0.235197, 0.235197, 0.356359, 0.302906, 0.329633,

0.0400014, 0.405359, 0.235197, 0.387541, 0.235197, 0.235197,
0.405359, 0.235197, 0.36705, 0.235197, 0.235197, 0.235197, 0.36705,
0.235197, 0.235197, 0.235197, 0.356359, 0.302906, 0.329633,
0.0400014, 0.405359, 0.235197, 0.387541, 0.235197, 0.235197,
0.387541, 0.235197, 0.235197, 0.356359, 0.302906, 0.329633,
0.0400014, 0.0400014, 0.356359, 0.302906, 0.329633, 0.0400014,
0.405359, 0.235197, 0.405359, 0.235197, 0.36705, 0.235197, 0.235197,
0.235197, 0.387541, 0.235197, 0.235197, 0.36705, 0.235197, 0.235197,
0.235197, 0.356359, 0.302906}


eps = {0.8368, 0.192464, 0.08368, 0.092048, 0.23012, 0.092048, 0.092048,
0.23012, 0.092048, 0.092048, 0.23012, 0.092048, 0.092048, 0.23012,
0.092048, 0.092048, 0.8368, 0.192464, 0.192464, 0.192464, 0.46024,
0.50208, 0.8368, 0.192464, 0.23012, 0.092048, 0.092048, 0.46024,
0.50208, 0.8368, 0.192464, 0.08368, 0.092048, 0.23012, 0.092048,
0.092048, 0.08368, 0.092048, 0.33472, 0.092048, 0.092048, 0.092048,
0.33472, 0.092048, 0.092048, 0.092048, 0.46024, 0.50208, 0.8368,
0.192464, 0.08368, 0.092048, 0.23012, 0.092048, 0.092048, 0.23012,
0.092048, 0.092048, 0.29288, 0.50208, 0.8368, 0.192464, 0.192464,
0.46024, 0.50208, 0.8368, 0.192464, 0.08368, 0.092048, 0.08368,

0.092048, 0.33472, 0.092048, 0.092048, 0.092048, 0.23012, 0.092048,
0.092048, 0.33472, 0.092048, 0.092048, 0.092048, 0.46024, 0.50208}

r0 = {{0.681, -2.673}, {0.605, -2.736}, {0.715, -2.578}, {0.812, -2.583},
{0.628, -2.607}, {0.654, -2.698}, {0.533, -2.609}, {0.63, -2.515},
{0.559, -2.545}, {0.609, -2.423}, {0.763, -2.509}, {0.825, -2.446},
{0.804, -2.6}, {0.742, -2.461}, {0.709, -2.367}, {0.829, -2.465},
{0.642, -2.547}, {0.629, -2.515}, {0.675, -2.642}, {0.555, -2.543},
{0.693, -2.445}, {0.778, -2.359}, {0.585, -2.422}, {0.526, -2.499},
{0.55, -2.291}, {0.543, -2.236}, {0.459, -2.299}, {0.638, -2.219},

{0.661, -2.105}, {0.715, -2.293}, {0.688, -2.387}, {0.829, -2.244},
{0.791, -2.156}, {0.867, -2.346}, {0.893, -2.431}, {0.946, -2.309},
{0.754, -2.38}, {0.674, -2.422}, {0.697, -2.255}, {0.627, -2.281},
{0.77, -2.205}, {0.657, -2.197}, {0.802, -2.482}, {0.729, -2.503},
{0.825, -2.566}, {0.883, -2.448}, {0.956, -2.216}, {1.034, -2.126},
{0.986, -2.287}, {0.921, -2.356}, {1.104, -2.268}, {1.178, -2.271},
{1.13, -2.381}, {1.056, -2.379}, {1.217, -2.362}, {1.135, -2.523},
{1.218, -2.53}, {1.055, -2.534}, {1.137, -2.64}, {1.171, -2.628},
{1.083, -2.751}, {1.043, -2.753}, {1.08, -2.832}, {1.099, -2.133},
{1.196, -2.059}, {0.987, -2.095}, {0.911, -2.161}, {0.964, -1.963},

{1.042, -1.957}, {0.833, -1.955}, {0.818, -1.859}, {0.844, -2.053},
{0.759, -2.051}, {0.92, -2.024}, {0.861, -2.146}, {0.714, -1.996},
{0.729, -2.089}, {0.708, -1.934}, {0.581, -1.991}, {0.505, -2.018},
{0.565, -1.898}, {0.586, -2.053}, {0.98, -1.845}, {1.047, -1.739}}

which -again, for those interested- correspond to a 2D projection of the first five residues of a S4S5 alpha helix for the Kv1.2 Ion Channel.


Defining $V(r)$ as


v[r_, r0_, s_, ep_] := 4 ep (s^12/EuclideanDistance[r, r0]^12 -
s^6/EuclideanDistance[r, r0]^6);


I can plot the potential with


Plot3D[Sum[v[{x, y}, r0[[i]], sig[[i]], eps[[i]]], {i, 1, 84}], 
{x, -0.5, 2}, {y, -3.5, -1},
PlotStyle -> Directive[Opacity[0.35], Blue],
AxesLabel -> {x, y}, PlotRange -> {-5, 1}
]

obtaining the following output


plot of sum of potentials


or, using PlotPoints -> 50



refined plot of sum of potentials


where the minima/maxima can be seen really well.


The thing is, I have a lot of these objects, with a lot more elements, and a lot of minima/maxima, in a way that is very expensive for my (old) computer to simply increase PlotPoints for smoother graphics, and I was wondering, due the fact that $V(r)$ rapidly decreases, if there is a way to ask MMA to increase resolution near the minima/maxima, and reduce it far from the data set r0.


Hope my question is clear and interesting.


--FINAL EDIT--


First of all, I want to thank you all for your comments and answers. If I could, I'd accept all of them, since each one gave me the insight needed to solve my problem. For obvious reasons, Silvia's answer deserves maximum recognition, but readers should also check PlatoManiac and Sjoerd C. de Vries responses, as they will provide a full picture.


Now, to honour the work of all the people involved, I'll show you the beautiful application of the code they've worked out.


Here is a caricaturization of the S4S5 linker helix, believed to play a major role in the opening and closing of voltage gated potassium channels.


S4S5 linker helix


This helix generates all sort of van der Waals interactions, that can be modelled by the Lennard-Jones potential.



For specific reasons, I need to see how this potential looks on a given plane, namely the XY plane, and it is very important to capture all the maxima and minima of it, as it will provide a full picture of the dynamics in that plane.


Thanks to Silvia's code, one can see:


a view from below of the potential generated by the helix, View from below


a sideways view, where the peaks are actually minima, Sideways veiw, the peaks are actually minima


and a view form above,


View from above


What you are seeing is the van der Waals interactions generated by the helix over that plane, and if you're wondering what does that sharp barrier around the helix is, it's the macroscopic consequence of Pauli's Exclusion Principle!


Thank you all for your help, you've put a big smile on my face!



Answer



In order to emphasize the wanted features, my idea is to manually generate a grid which is fine near the ridge line and sketchy far away:



Mathematica graphics



First we define our functions following Simon's suggestion:


v[r_, r0_, s_, ep_] := 4*ep*(s^12/(#.#&)[r-r0]^(12/2)-s^6/(#.#&)[r-r0]^(6/2))

expr = Sum[v[{x, y}, r0[[i]], sig[[i]], eps[[i]]], {i, 1, 84}];

func = Compile[{x, y}, Evaluate[expr // Expand]];

funcWrap[x_?NumericQ, y_?NumericQ] := func[x, y]



The shape of the plot makes me feel that it's more convenient to work in a polar coordinate system in the $x$-$y$ plane, with rC (center of r0) as the origin. In order to generate a grid fit for expr, two key lines need to be known first: one is the boundary innerBoundLine where expr==2 (because we want to cut the PlotRange below $1<2$), and the other is the ridge line minPointsPolar, highlighted blue in the plot above:


rC = Mean[r0];

innerBoundLine = ContourPlot[funcWrap[x, y] == 2,
{x, -0.5, 2}, {y, -3.5, -1}, PlotPoints -> 50];

innerBoundPoints = Cases[
Normal[innerBoundLine[[1]] /.Tooltip[expr_, _] :> expr],

Line[pts_] :> pts, ∞][[1]] // Most;

innerBoundPointsPolar =
{Arg[{1, I}.#], Norm@#} &[# - rC] & /@ innerBoundPoints // SortBy[#, First] &;

innerBoundFunc = Interpolation[
ReplacePart[#,{{1, 2}, {-1, 2}} -> Mean[#[[{1, -1}, 2]]]] &[innerBoundPointsPolar],
PeriodicInterpolation -> True, InterpolationOrder -> 1];

minPointsPolar = Module[

{ρmin, linefunc, ρinit},
Table[ρinit = innerBoundFunc[φ];
ρmin = ρ /. FindMinimum[ funcWrap @@ (ρ {Cos[φ], Sin[φ]} + rC),
{ρ, ρinit}, Method -> "PrincipalAxis"][[2]];
{φ, ρmin},
{φ, 0, 2 π, 1. Degree}]];

minFunc = Interpolation[
ReplacePart[#, {{1, 2}, {-1, 2}} -> Mean[#[[{1, -1}, 2]]]] &[minPointsPolar],
PeriodicInterpolation -> True, InterpolationOrder -> 1];



Now we can proceed to the grid generation step. Here, four grids with different fineness are generated. minLineGrid is near the ridge line and is the finest. From fineGrid to transitionalGrid to outlineGrid, the grids are farther and farther from the ridge, and sketchier and sketchier.


minLineGrid = Module[{ρmin, linefunc},
Table[
ρmin = minFunc[φ];
linefunc = Append[#,
funcWrap @@ #] &[
ρ {Cos[φ], Sin[φ]} + rC];
Table[linefunc, {ρ,

Range[.98, 1.02, .01] ρmin
}],
{φ, 0, 2 π, 1. Degree}] // Flatten[#, 1] &
];

fineGrid = Module[{ρmin, linefunc, ρinit},
Table[
ρinit = innerBoundFunc[φ];
ρmin = minFunc[φ];
linefunc = Append[#,

funcWrap @@ #] &[
ρ {Cos[φ], Sin[φ]} + rC];
Table[linefunc, {ρ, Join[
Rescale[Range[0, 1, .5], {0, 1}, {ρinit, ρmin}],
Rescale[Range[0, 1, .3], {0, 1}, {ρmin, 1.1 ρmin}]
]}],
{φ, 0, 2 π, 2. Degree}] // Flatten[#, 1] &
];

transitionalGrid = Module[{ρmin, linefunc},

Table[
ρmin = minFunc[φ];
linefunc = Append[#,
funcWrap @@ #] &[
ρ {Cos[φ], Sin[φ]} + rC];
Table[linefunc, {ρ,
Rescale[Range[0, 1, .2], {0, 1}, {1.1 ρmin, 1.5 ρmin}]
}],
{φ, 0, 2 π, 5. Degree}] // Flatten[#, 1] &
];


outlineGrid = Module[{ρmin, linefunc},
Table[
ρmin = minFunc[φ];
linefunc = Append[#,
funcWrap @@ #] &[
ρ {Cos[φ], Sin[φ]} + rC];
Table[linefunc, {ρ,
Rescale[Range[0, 1, .5], {0, 1}, {1.5 ρmin, 2}]
}],

{φ, 0, 2 π, 20. Degree}] // Flatten[#, 1] &
];

dataGrid = Join[outlineGrid, transitionalGrid, fineGrid, minLineGrid];

The grid points would look like this in the $x$-$y$ plane:


Graphics[{PointSize[.001], Black, Point[minLineGrid[[All, 1 ;; 2]]],
PointSize[.002], Red, Point[fineGrid[[All, 1 ;; 2]]],
PointSize[.005], Darker@Green, Point[transitionalGrid[[All, 1 ;; 2]]],
PointSize[.008], Blue, Point[outlineGrid[[All, 1 ;; 2]]]},

Frame -> True, FrameLabel -> (Style[#, Bold, 20] & /@ {x, y})]

Mathematica graphics



Plot the dataGrid by ListPlot3D:


ListPlot3D[dataGrid,
PlotRange -> {{-.5, 2}, {-3.5, -1}, {-5, 1}},
ClippingStyle -> Gray, BoundaryStyle -> Blue,
AxesLabel -> (Style[#, Bold, 20] & /@ {x, y})]


Mathematica graphics


($x$,$y$) grid of the plot:


ListPlot3D[dataGrid,
PlotRange -> {{-.5, 2}, {-3.5, -1}, {-5, 1}},
Mesh -> All, PlotStyle -> None,
AxesLabel -> (Style[#, Bold, 20] & /@ {x, y}),
ViewPoint -> {0, 0, ∞}]

Mathematica graphics


Remarks: I believe it can be made more adaptive by finding an appropriate coordinate transformation which converts the ridge-line and the outside borders (-0.5 <= x <= 2 && -3.5 <= y <= -1) to centered concentric circles, and then generate polar grids in this new coordinate system.



Edit: The typical time spent for generating above grids on my computer:


Timing[
rC = Mean[r0];

...

outlineGrid = ...;
]



{1.482, Null}



Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

equation solving - Invert and fit implicitly defined curve

I need to fit an implicitly defined curve. I thought I could get some data out of Solve , and then using FindFit . Therefore, I would like to find the relation the parametric curve defined by $F(x,y)=0$: Solve[-(1/2) + 1/2 (0.41202 BesselK[0, 0.1 Sqrt[x^2 + y^2]] + (0.101483 x BesselK[1, 0.1 Sqrt[x^2 + y^2]])/Sqrt[x^2 + y^2]) == 0, y] But I can't get an output: Solve was unable to solve the system with inexact coefficients or the system obtained by direct rationalization of inexact numbers present in the system. Since many of the methods used by Solve require exact input, providing Solve with an exact version of the system may help. >> Edit: In particular, I would like to fit the data coming from the curve with the expression of another curve, and not with a function $f(x)$. In particular, since this clearly looks like a cardioid , I would like it to fit to something like it. What other strategies could I try?

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...