Unfortunately FullGraphics
is extremely out-of-date: it seems that it has not changed much since version 5. Currently correct solution may be only FrontEnd-based.
FrontEnd has a command Convert Dynamic to Literal
under Evaluation
menu which helps with Dynamic
but not with Ticks
.
A workaround for Ticks
is Export
ing the complete Graphics[...]
as a Notebook, then Import
ing it backward:
myf1[min_?NumericQ, max_?NumericQ] := Table[count, {count, min, max}];
plot = Plot[x^2, {x, 1, 5}, Ticks -> myf1];
Shallow[ImportString[ExportString[plot, "NB"], "NB"][[1, 1, 1, 1, -1]], 7]
Ticks->FrontEndValueCache[$CellContext`myf1,{{{0.916667,FormBox[<<2>>]},{1.91667,FormBox[<<2>>]},{2.91667,FormBox[<<2>>]},{3.91667,FormBox[<<2>>]},{4.91667,FormBox[<<2>>]}},{{-0.520833,FormBox[<<2>>]},{0.479167,FormBox[<<2>>]},{1.47917,FormBox[<<2>>]},{2.47917,FormBox[<<2>>]},{3.47917,FormBox[<<2>>]},{4.47917,FormBox[<<2>>]},{5.47917,FormBox[<<2>>]},{6.47917,FormBox[<<2>>]},{7.47917,FormBox[<<2>>]},{8.47917,FormBox[<<2>>]},{9.47917,FormBox[<<2>>]},{10.4792,FormBox[<<2>>]},{11.4792,FormBox[<<2>>]},{12.4792,FormBox[<<2>>]},{13.4792,FormBox[<<2>>]},{14.4792,FormBox[<<2>>]},{15.4792,FormBox[<<2>>]},{16.4792,FormBox[<<2>>]},{17.4792,FormBox[<<2>>]},{18.4792,FormBox[<<2>>]},{19.4792,FormBox[<<2>>]},{20.4792,FormBox[<<2>>]},{21.4792,FormBox[<<2>>]},{22.4792,FormBox[<<2>>]},{23.4792,FormBox[<<2>>]},{24.4792,FormBox[<<2>>]},{25.4792,FormBox[<<2>>]}}}]
As you can see the Import
ed expression contains explicit Ticks
specification as a cache for the value of $CellContext`myf1
variable wrapped by FrontEndValueCache
. To get standalone Ticks
specification you should replace FrontEndValueCache
with its second argument:
Shallow[ImportString[ExportString[plot, "NB"], "NB"][[1, 1, 1]] /.
FrontEndValueCache[var_, val_] :> val // ToExpression // InputForm, 7]
Graphics[{{}, {}, {Hue[0.67, 0.6, 0.6], Line[{<<77>>}]}}, AspectRatio -> GoldenRatio^(-1),
Axes -> True, AxesOrigin -> {1., 0}, PlotRange -> {{1, 5}, {0., 24.99999918367348}},
PlotRangeClipping -> True, PlotRangePadding -> {Scaled[0.02], Scaled[0.02]},
Ticks -> {{{<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}}, {{<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, > > {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}, {<<2>>}}}]
Now you have got the complete standalone Graphics
expression. Note that this workaround is for Ticks
only and works only in the absence of Dynamic
constructs. So before applying this you need to get rid of Dynamic
using the Convert Dynamic to Literal
command. This can be automatized:
myf1[min_?NumericQ, max_?NumericQ] := Table[count, {count, min, max}];
a = 8;
dynamicPlot = Dynamic[Plot[x^2, {x, 1, a}, Ticks -> myf1]];
nb = CreateDocument[dynamicPlot];
SelectionMove[nb, All, Notebook];
FrontEndExecute[{FrontEnd`NotebookDynamicToLiteral[
FrontEnd`NotebookSelection[FrontEnd`InputNotebook[]]]}];
Shallow[NotebookGet[nb], 8]
Notebook[{Cell[
BoxData[GraphicsBox[{{}, {}, {<<2>>}},
AspectRatio -> NCache[<<2>>], Axes -> True,
AxesOrigin -> {<<2>>}, PlotRange -> {<<2>>},
PlotRangeClipping -> True, PlotRangePadding -> {<<2>>},
Ticks -> FrontEndValueCache[<<2>>]]],
CellChangeTimes -> {3.60323*10^9}]}, WindowSize -> {701, 766},
WindowMargins -> {{480, Automatic}, {Automatic, 57}},
FrontEndVersion ->
"8.0 for Microsoft Windows (64-bit) (October 6, 2011)",
StyleDefinitions -> "Default.nb"]
Note that in this case we able to kill two birds with one stone! We both have got rid of Dynamic
and got complete Ticks
specification without Export
ing. What we need now is just to apply the replacement rule
FrontEndValueCache[var_, val_] :> val
and extract the BoxData
expression from the Notebook
expression, then convert box data into ordinary Mathematica graphics by applying ToExpression
. Done!
P.S. In principle it is not necessary to convert BoxData
to ordinary Mathematica graphics for transferring standalone Graphics
to another computer. You can transfer the complete Notebook
expression which can be stored in a textual file with .nb
extension and opened by FrontEnd as ordinary Notebook. Even more, this way is more safe and gives much lesser possibility to corrupt anything.
UPDATE
I just have found that the automatized way with the above method of calling Convert Dynamic to Literal
command can lead to FrontEnd crash. More safe solution would be to get values of Dynamic
variables directly from the kernel, so just stripping out Dynamic
in the kernel. Here is the complete code which accounts only for simplest literal Dynamic
and Ticks
but not to other Dynamic
constructs like DynamicModule
etc.:
makeStandalone[expr_] := Module[{nb, nbExpr},
nb = CreateDocument[dynamicPlot /. Dynamic[x___] :> x];
FinishDynamic[]; Pause[.1];
nbExpr = NotebookGet[nb] /. FrontEndValueCache[var_, val_] :> val;
NotebookClose[nb]; nbExpr];
I have added FinishDynamic[]
and Pause[.1]
because in some cases Ticks
were not resolved even with FinishDynamic[]
.
FullGraphics
seems to be the right direction. But is it complete? And, if yes, how can I influence properties such as the aspect ration of the plot? $\endgroup$