0
$\begingroup$

I have a list of data for use in ListContourPlot in the form of:

data={{x1,y1,v1},{x2,y2,v2},...};

Let's say the values of v range from -1 to 1. When plotted, it is clear there are optimal points on the contours that are produced (e.g, for contour 0.5, there is a minimal value of x).

Is there an automatic way to obtain such values from the plot (i.e. as opposed to using plot coordinates)? If so, would there dependence on the interpolation order?

UPDATE: The data would look something like this: data example

Imagine I have a ton of these plots and want to find the minimal value of x on the 0.5 contour for each of them.

$\endgroup$
  • $\begingroup$ "I have a list of data..." - then, could you maybe post it in Pastebin? $\endgroup$ – J. M. is away Nov 5 '17 at 0:02
  • $\begingroup$ Like, do you mean you want to select only those sub-lists where x falls under some condition? :s $\endgroup$ – e.doroskevic Nov 5 '17 at 0:25
  • $\begingroup$ @e.doroskevic Not really; I want to find the interpolated value of x from the contour produced in Mathematica that meets my criteria, in this case the minimal interpolated value. $\endgroup$ – Alex Nov 5 '17 at 0:56
  • $\begingroup$ The plot shows x asa single-valued function of y for each contour. May the reader assume that this always is true for the actual plots? If so, the solution is straightforward. $\endgroup$ – bbgodfrey Nov 5 '17 at 1:46
  • $\begingroup$ Welcome to Mathematica.SE! I hope you will become a regular contributor. To get started, 1) take the introductory tour now, 2) when you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge, 3) remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign, and 4) give help too, by answering questions in your areas of expertise. $\endgroup$ – bbgodfrey Nov 6 '17 at 4:47
2
$\begingroup$

The desired minimum value can be obtained from the ListContourPlot as follows. In the absence of specified data, use

data = Flatten[Table[{x, y, x - (y - 2/3)^2}, {x, 0, 1, .01}, {y, 0, 1, .01}], 1];

Next, use ListContourPlot to generate a Mesh curve corresponding to the desired contour, here 0.5. (In principle, a Contour curve could be used instead of a Mesh curve, but doing so is less convenient.)

plt = ListContourPlot[data, Mesh -> {{.5}}, MeshFunctions -> {(#3) &},
   MeshStyle -> Thick, Contours -> 0, FrameLabel -> {x, y}, 
   ImageSize -> Large, LabelStyle -> Directive[Black, Bold, Medium]]

enter image description here

along with a spurious error message that can be ignored.

Flatten::argb: Flatten called with 0 arguments; between 1 and 3 arguments are expected.Flatten::argb: Flatten called with 0 arguments; between 1 and 3 arguments are expected.

Evidently, ListContourPlot does not like Contours -> 0. Next, extract the Line corresponding to the curve,

lst = Cases[plt[[1]] // Normal, Line[z_] -> z, Infinity][[1]];

and determine the minimum point,

min = MinimalBy[lst, First] // Last
(* {0.500011, 0.67} *)

which visibly is correct. A sometimes slightly more accurate value can be obtained by

int = Interpolation[Reverse /@lst];
FindMinimum[int[y], {y, min // Last}]
(* {0.50001, {y -> 0.670422}} *)

Here, it is no better than min.

$\endgroup$
0
$\begingroup$

My solution was to first make an interpolating function f from the discrete data:

vdata=data[[1 ;;,3]];
f = Interpolation[Transpose[{data[[1;;,1;;2]], vdata}], InterpolationOrder -> 1];

Then, I made a loop to increment x and y by inc and apply in f[x,y] until the contour of interest was reached at minimal x-value ans:

contour = 0.5;
inc=0.001;
Do[
   v = f[x, y];
   If[v >= contour, {ans = x, Break[]}];
, {x, 0, 1, inc}, {y, 0, 1, inc}];

Not efficient, but it worked for my particular problem.

$\endgroup$
0
$\begingroup$

Construct an interpolation function, take its derivative (which results in a new interpolation function), then plot the zero contour of that:

data = Flatten[
   Table[{x, y, x - (x/2 + y - 2/3)^2}, {x, 0, 1, .01}, {y, 0, 
     1, .01}], 1];
int = Interpolation[data];
dy = D[int[x, y], y]
Show[{
  ContourPlot[int[x, y], {x, 0, 1}, {y, 0, 1}],
  ContourPlot[dy, {x, 0, 1}, {y, 0, 1}, Contours -> {0}, 
   ContourShading -> False]}]

enter image description here

if you need specific points on the contours, extract that line and interpolate:

c = Interpolation[{int[Sequence @@ ##], ##} & /@ (First@
      Cases[Normal@
        ContourPlot[dy, {x, 0, 1}, {y, 0, 1}, Contours -> {0},
         ContourShading -> False] , Line[pts_] :> pts , Infinity])];
Show[{
  ContourPlot[int[x, y], {x, 0, 1}, {y, 0, 1},
   Epilog -> {Red, PointSize[.025], 
     Point[Table[c[v], {v, 0, 1, .2}]]}]}]

enter image description here

note this is a little different input example than the other answer.

$\endgroup$

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.