Why doesn't the Inset item show in Prolog in a plot?

让人想犯罪 __ 提交于 2019-12-13 18:12:34

问题


I apologise for the length of this question. My current Mathematica programming project involves replicating the very specific business rules my employing institution has for publication-quality plots of time series. One of these rules is that multipanel graphs have panel titles and subtitles centered near the top of the plot area. This worked fine using Prolog and Inset until I redid that bit of the function to allow explicit Prolog elements to be included as well. Then only the item passed in the Prolog option shows, not the panel titles and subtitles. If there is no explicit Prolog option, the panel titles and subtitles show up fine.

To explicate a bit further, imagine the function body is all in a big Module, including the local variable pl=OptionValue[Prolog] and mp=OptionValue[MultiPanel].

A bit further down is this definition (ppl, title and subtitle were also defined as local variables, and Rfont and framecol are constants defined elsewhere in the package, namely to be "Arial" and "Black"):

ppl=If[mp===False,pl,If[Length[pl]>0,Join[{ 
If[ToString[subtitle] == "None",  Inset[
DisplayForm[GridBox[{{Style[title, 20, FontFamily -> Rfont, framecol]}}]],
    Scaled[{0.5,0.96}],{Center,Top} ], 
Inset[DisplayForm[
GridBox[{{Style[title, 20, FontFamily -> Rfont, framecol]}, 
     {Style[subtitle, 16, FontFamily -> Rfont, framecol]}}, 
     RowSpacings -> 0]],Scaled[{0.5,0.98}],{Center,Top}] ]},pl],
  {If[ToString[subtitle] == "None",  
     Inset[ DisplayForm[
       GridBox[{{Style[title, 20, FontFamily -> Rfont, framecol]}}]],
      Scaled[{0.5,0.96}],{Center,Top} ], 
      Inset[DisplayForm[
        GridBox[{{Style[title, 20, FontFamily -> Rfont, framecol]}, 
                  {Style[subtitle, 16, FontFamily -> Rfont, framecol]}},
        RowSpacings -> 0]],Scaled[{0.5,0.98}],{Center,Top}]] }] ]

All fine as far as it goes. The Inset is used if the option MultiPanel (and thus mp) is not False and there is no Prolog explicitly set. But if a prolog is set, e.g., Prolog -> {Text["test", Scaled[{0.6, 0.5}]]}, then the Inset doesn't show, only the Text element.

It isn't a problem with the way I am joining them together. Capturing and printing the value of ppl gives:

{Inset[{{Style["This is a test", LineColor -> GrayLevel[0], 
FrontFaceColor -> GrayLevel[0],   BackFaceColor -> GrayLevel[0], 
GraphicsColor -> GrayLevel[0], FontFamily -> "Arial", FontSize -> 20, 
FontColor -> GrayLevel[0]]}, 
{Style["Year-ended percentage change", LineColor -> GrayLevel[0], 
FrontFaceColor -> GrayLevel[0], BackFaceColor -> GrayLevel[0], 
GraphicsColor -> GrayLevel[0], FontFamily -> "Arial", FontSize -> 16, 
FontColor -> GrayLevel[0]]}}, 
Scaled[{0.5, 0.98}], {Center, Top}], Text["test", Scaled[{0.6, 0.5}]]}

(And yes, those are a bunch of undocumented options which I shall ask about in another question.)

Does anyone know if there is anything preventing Prolog (or Epilog for that matter) combining Inset elements and other things in the one set of graphics options?


回答1:


As you have not given a working fragment of code, I'm not sure what's going wrong in it.

How does my simple example not replicate what you're trying?

plot = Plot[x^2, {x, -5, 5}, Prolog -> Inset[Style[Text[":) = \[HappySmiley]"], Large]]]

pl = Flatten@{Prolog /. AbsoluteOptions[plot, Prolog]}

join = Show[{Plot[x^2 + 1, {x, -5, 5}, PlotStyle -> Red], 
             Plot[x^2, {x, -5, 5}, PlotStyle -> Blue]}, 
            Prolog -> Join[{Inset[Graphics@Circle[]]}, If[Length[pl] > 0, pl, {}]]]




回答2:


I feel a bit stupid now. I worked out the issue. Let me see if I can explain clearly enough.

Suppose you have a custom function (say, XYZPlot) that is built on a built-in one (say, DateListPlot). Suppose you want to pass some options to DateListPlot, as well as handling some options that are specific to XYZPlot. Then you probably want to pass any options the user includes explicitly before you pass the default options that apply to your custom function. This is a toy example: normally you'd set default PlotRange as an option to your custom function with SetOptions etc.

defaultplotrange = {1,5};
XYZPlot[args___,opts:OptionsPattern[{XYZPlot,DateListPlot}]]:=
  DateListPlot[args,Sequence @@ FilterRules[{opts}, Options[DateListPlot]],
    PlotRange->defaultplotrange]

So far so good. But if you want to catch the value of an option and modify it even if the user provides an explicit value for it when they call the function, for example to add [ahem] panel titles if some other option is set to True, then you can't put that option after the FilterRules bit. It has to come before. Otherwise the value of Prolog that the user gave will be used, not the one with the bit added. So the right way is to do something like this.

defaultplotrange = {1,5};
XYZPlot[args___,opts:OptionsPattern[{XYZPlot,DateListPlot}]]:=
  With[{pl=OptionValue[Prolog],mp=OptionValue[MultiPanel]},
  DateListPlot[args,
  Prolog -> If[mp===False,pl,Join[pl,{Inset[(* something else *)]}]],
  Sequence @@ FilterRules[{opts}, Options[DateListPlot]],
    PlotRange->defaultplotrange]]

Sorry to bother you all.



来源:https://stackoverflow.com/questions/6894196/why-doesnt-the-inset-item-show-in-prolog-in-a-plot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!