[R] Lattice, ggplot, and pointsize
deepayan.sarkar at r-project.org
Wed Jun 5 16:07:04 CEST 2013
On Sun, May 26, 2013 at 12:47 AM, Milan Bouchet-Valat <nalimilan at club.fr> wrote:
> Le mardi 21 mai 2013 à 21:39 +0100, Prof Brian Ripley a écrit :
>> On 21/05/2013 21:24, Bert Gunter wrote:
>> > At the risk of misunderstanding... (inline)
>> > On Tue, May 21, 2013 at 12:17 PM, Milan Bouchet-Valat <nalimilan at club.fr> wrote:
>> >> Le mardi 21 mai 2013 à 08:17 -0700, Jeff Newmiller a écrit :
>> >>> That is like complaining that your hammer does not fit these
>> >>> newfangled Philips screws.
>> >>> These are different tools. Do not expect them to interoperate.
>> >> I understand that Lattice and ggplot2 do not use settings from par().
>> >> I'm fine with this, as these packages are different from base graphics
>> >> and have they own equivalent to tweak settings.
>> >> What I do not understand is that one argument passed to output devices,
>> >> which are _not_ provided by package graphics, is ignored by these two
>> >> packages. Lattice and ggplot2 do not provide an alternative output
>> >> system,
>> > False, I believe, depending on what you mean by "output system". They
>> > both use grid graphics, not base graphics and with lattice, anyway,
>> Indeed. The issue is a design difference between the base and grid
>> graphics subsystems. See the 'R Internals' manual for more details.
> Thanks for the pointers. Indeed there is some interesting documentation
> there. I've also had a deeper look at the code, and I've traced
> pointsize (called ps) back to the R_GE_gcontext struct in
> If I understand correctly, base graphics draw text using GText() in
> src/library/graphics/src/graphics.c, which in turn calls GEText() in
> src/main/engine.c. GEText() does take into account the pointsize.
> On the other hand, grid graphics draw text using gridText() from
> src/library/grid/src/grid.c. This function uses gcontextFromgpar() to
> get its R_GE_gcontext object. gcontextFromgpar() (defined in gpar.c)
> computes the pointsize from the fontsize gpar setting and a general
> scaling of the output:
> * Scale by GSS_SCALE (a "zoom" factor)
> gc->ps = gpFontSize(gp, i) * REAL(gridStateElement(dd, GSS_SCALE));
> What is interesting is that when a new device gets initialized by grid
> (initGPar() atin gpar.c), the fontsize gpar settings is set to the
> device starting pointsize:
> REAL(gpfs) = dev->startps;
> And indeed this works with svg():
>> svg("test.svg", pointsize=5)
>  5
> ...but not with Lattice:
>  12
>  8
> So the problem does not appear to be a base vs. grid graphics issue, but
> rather something specific to Lattice and ggplot2. And indeed, when
> looking at Lattice's sources, canonical.theme() in settings.R does:
> fontsize = list(text = 12, points = 8),
> As simple as that! I didn't need to look so deep into the code... :-/
> ?trellis.par.set says:
> The initial settings for each device defaults to values
> appropriate for that device. In practice, this boils down to three
> distinct settings, one for screen devices like ‘x11’ and
> ‘windows’, one for black and white plots (mostly useful for
> ‘postscript’) and one for color printers (color ‘postcript’,
> ‘pdf’). [This may not be up-to-date, though...]
> So it does not appear completely absurd to try to adjust to the device
> settings where appropriate. Pointsize seems such a case to me.
> canonical.theme() could set the text font size to get.gpar("fontsize").
> Since the default value is 12 for most devices, this would not change
> anything by default. (ggplot2 could probably benefit from a similar
If I remember correctly (it was a long time ago), I had nothing in
particular against the default text fontsize. The default symbol size
in grid was larger than I liked, and so fontsize$points was set to
something more reasonable, and fontsize$text just seemed natural to
add. It is only ever used in a single call to gpar() inside
print.trellis. So it seems perfectly reasonable to take the default of
fontsize$text from grid instead.
I don't like the idea of making the default
'get.gpar("fontsize")$fontsize' though, because that requires a device
to be active, which canonical.theme() doesn't by design. Instead I
have changed the default to NULL, and the fontsize is now set from (in
order of priority)
1. trellis.par.get("fontsize")$text # NULL by default
2. trellis.par.get("grid.pars")$fontsize # NULL by default
3. get.gpars()$fontsize # approximately device pointsize by default
Hopefully this works for you. You can test using the r-forge version.
> I realize this is no longer a discussion relevant for R as a whole, but
> I am posting it here nevertheless in case somebody was interested. Maybe
> we should discuss this offlist with Deepayan.
More information about the R-help