My Professor sent me a Mathematica Notebook, where he plots a 2d contour and then extracts the contour as lines (i.e. a list of lists of coordinate-tuples). The specific code segment looks like this:
xdiv = 0.05
zt = 1.
lis = Table[SomeFunction[x, y, zt], {y, -xmax, xmax, xdiv}, {x, -xmax, xmax, xdiv}];
plot = ListContourPlot[lis, PlotLegends -> Automatic, Contours -> {0}, ContourShading -> None];
lines = Cases[Normal@plot, Line[pts_, ___] :> xdiv*pts, Infinity];
I do not fully understand how exactly the code does what it does and an I'm seeking help for an explanation. I want to write a similar code in python and understand how. Also I want to know if I can extract the lines without using the ContourPlot function. I am not particularly interested in plotting the contours, I only need a list of its lines.
Edit: Rephrased the question. Also: matplotlib - extracting data from contour lines seems to explain how to achieve my goal in python. However, I don't really understand how it does what it does and judge if there is a better way, in terms of performance, to achieve it (I am dealing with very large lists, so this contour extraction seems like quite the bottleneck). I was looking for something more of an explanation to understand what exactly happens. The provided answer does really well at explaining the Mathematica code. I will read more into the matplotlib methods.
Here is some explanation of what is happening, with an example function:
SomeFunction[x_, y_, zt_] := Sin[3 x + y^2]
xmax = 4;
xdiv = 0.05;
zt = 1.;
lis = Table[SomeFunction[x, y, zt], {y, -xmax, xmax, xdiv}, {x, -xmax, xmax, xdiv}];
plot = ListContourPlot[lis, PlotLegends -> Automatic, Contours -> {0},
ContourShading -> None];
normalplot = Normal@plot
cases = Cases[normalplot, Line[pts_, ___], Infinity];
Length[cases]
First[cases]
17 Line[{{16.2216, 1.}, {17., 1.29614}, ... , {16.7818, 160.782}, {16.2216, 161.}}]
The Cases
statement extracts each line from the normalized plot. (Normal
simplifies the graphics form to one amenable to Cases
.) There are 17 separate lines of the form Line[List[{x, y}, {x, y}, ...]]
.
For each line List[{x, y}, {x, y}, ...]
is represented by pts
, so
lines = Cases[normalplot, Line[pts_, ___] :> xdiv*pts, Infinity]
multiplies each list of pts
by xdiv
.
0.05 * {{16.2216, 1.}, {17., 1.29614}, ... , {16.7818, 160.782}, {16.2216, 161.}}
= {{0.81108, 0.05}, {0.85, 0.0648069}, ... {0.839088, 8.03909}, {0.81108, 8.05}}
The lines can be plotted.
ListLinePlot[lines, AspectRatio -> 1]