Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

As was discussed in the comments of another question (MathLink Graphical Output (Plots) to File), Graphcis objects produced by commands such as Plot could be used to plot graphics independent of the presence of a connection with the Mathematica kernel which generated it; i.e., it could be displayed in a separate instance of Mathematica. This would be useful to realize the display of plots in custom front ends connected to Mathematica with MathLink. The Graphics objects would in this case serve as exchange format between the kernel and the frond end.

However, as was pointed out to me, Graphics can contain dynamic content which is evaluated by the native front end by calling the kernel. Consider the example

SetOptions["stdout", FormatType -> InputForm];
myf1[min_?NumericQ, max_?NumericQ] := Table[count, {count, min, max}];
Plot[x^2, {x, 1, 5}, Ticks -> myf1]

which generates the output

Graphics[{{{}, {}, {Hue[0.67, 0.6, 0.6], Line[{ ...}]}}}, 
  {AspectRatio -> GoldenRatio^(-1), Axes -> True, 
   AxesLabel -> {None, None}, AxesOrigin -> {1., 0}, Method -> {}, 
   PlotRange -> {{1, 5}, {0., 25.}}, PlotRangeClipping -> True, 
   PlotRangePadding -> {Scaled[0.02], Scaled[0.02]}, Ticks -> myf1}]

Note the final Ticks -> myf1. Is it possible make the kernel evaluate this output such that it is rendered static? In this case the Graphics should be made a static list of tics, however the solution would need to be generic enough to produce static output for all possible commands which generate graphics.

share|improve this question
    
The command 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? –  highsciguy Mar 7 at 16:14

1 Answer 1

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 Exporting the complete Graphics[...] as a Notebook, then Importing 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 Imported 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 Exporting. 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[].

share|improve this answer
    
Do you have an example for the crash? Does it occur when the result is displayed, or when it is build? –  highsciguy Mar 8 at 16:35
    
@highsciguy In version 8.0.4 I get the crash every time with my original "automatized" code (under Windows 7 x64). –  Alexey Popkov Mar 8 at 17:16
    
So far I did not see any crashes (I use Mathematica 9 on Linux). However I am not yet sure about the last part in your conversion. Everything seems to work if I use the native front end, but with MathLink I get A front end is not available; certain operations require a front end.. Which is not too surprising, because the linked MathKernel will a priori not even know about an X-Window to display anything. –  highsciguy Mar 8 at 18:12
    
@highsciguy This message just states that FrontEnd is not connected to the kernel (the $FrontEnd variable is undefined). –  Alexey Popkov Mar 8 at 22:54
    
Yes, I understand this. What I meant was that the FrontEnd on linux requires an X-Window (the piece of software in charge of displaying any graphical user interface). A X-Display is however not necessarily available if the login is on the command line (e.g. if I want to run Mathematica on a cluster). However I realized now that even Export[Plot[..]] requires a FrontEnd and thus a X-Display. It seems that the only way to circumvent it is to use a X-Display on a remote computer in general. This would however make it slow again. –  highsciguy Mar 14 at 19:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.