Let f
be some numeric function with two arguments
f[x_?NumericQ, y_?NumericQ] := x y
For the purposes of this question f
has a very simple form, but the function I am actually working with takes several seconds to evaluate. Therefore, I want to store every evaluation of f
. This could be done with a memory function (memf[x_,y_]:=memf[x,y]=f[x,y]
), but here I use Sow
instead, i.e.
sowf[x_?NumericQ, y_?NumericQ] := (Sow[{x, y, f[x, y]}, "f"]; f[x, y])
Now create a ContourPlot
of sowf
with
{plot, {{fPts}, {monitorPts}}} = Reap[
ContourPlot[
sowf[x, y], {x, 0, 1}, {y, 0, 1},
EvaluationMonitor :> Sow[{x, y, f[x, y]}, "monitor"],
PlotTheme -> "Monochrome",
PlotPoints -> 3,
MaxRecursion -> 0
],
{"f", "monitor"}
];
The plot is now stored in plot
, while fPts
contains all results of evaluations of sowf
and monitorPts
contains all points that where sent to EvaluationMonitor
.
Remark: I thought those two sets of points should be the same, but in fact sowf
was evaluated one more time than EvaluationMonitor
suggests:
Length /@ {fPts, monitorPts}
(* {10, 9} *)
Complement[fPts, monitorPts]
(* {{0.0005, 0.0005, 2.5*10^-7}} *)
The computation above will be done with the expensive f
on a computer cluster, and I want to make some adjustments to the plot style and other options later on, without having to re-evaluate f
.
My question is, how can I use either set of points to reconstruct the ContourPlot
, using a ListContourPlot
? Simply providing ListContourPlot
with one of those sets results in a different plot:
contours = Sort@Cases[plot, Tooltip[__, n_] :> n, \[Infinity]]
(* {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9} *)
Show[{
plot,
ListContourPlot[monitorPts,
ContourStyle -> Directive[Thick, Cyan, Dashed],
ColorFunction -> (Transparent &), Contours -> contours]
}]
Show[{
plot,
ListContourPlot[fPts,
ContourStyle -> Directive[Thick, Cyan, Dashed],
ColorFunction -> (Transparent &), Contours -> contours]
}]
Note, that ListContourPlot
does not show all the contours I specified! The contours for 0.9, 0.8, and 0.7 are missing.
Tally@Cases[%, Tooltip[__, n_] :> n, \[Infinity]]
(* {{0.9, 1}, {0.8, 1}, {0.7, 1}, {0.6, 2}, {0.5, 2}, {0.4, 2}, {0.3, 2},
{0.2, 2}, {0.1, 2}} *)
What additional information does ContourPlot
use?
When the number of points is large enough it works fine
{plot, {{fPts}, {monitorPts}}} = Reap[
ContourPlot[
sowf[x, y], {x, 0, 1}, {y, 0, 1},
EvaluationMonitor :> Sow[{x, y, f[x, y]}, "monitor"],
PlotTheme -> "Monochrome"
],
{"f", "monitor"}
];
Show[{
plot,
ListContourPlot[fPts,
ContourStyle -> Directive[Thick, Cyan, Dashed],
ColorFunction -> (Transparent &)]
}]
but the actual f
is, as I mentioned before, very expensive to evaluate, so I want to keep the number of plot points relatively low.
0.9
,0.8
, and0.7
. $\endgroup$