Re: [Rd] as.character.POSIXt in R devel

2022-10-03 Thread Martin Maechler
> Suharto Anggono Suharto Anggono via R-devel 
> on Sun, 2 Oct 2022 08:42:50 + (UTC) writes:

> With r82904, 'as.character.POSIXt' in R devel is changed. The NEWS item:
> as.character() now behaves more in line with the
>methods for atomic vectors such as numbers, and is no longer
>influenced by options().

> Part of the code:

>s <- trunc(x$sec) fs <- x$sec - s
> r1 <- sprintf("%d-%02d-%02d", 1900 + x$year, x$mon+1L, x$mday)
>   if(any(n0 <- time != 0)) # add time if not 0
> r1[n0] <- paste(r1[n0],
> sprintf("%02d:%02d:%02d%s", x$hour[n0], 
x$min[n0], s[n0],
> substr(as.character(fs[n0]), 2L, 32L)))


> * Wrong:
> The result is wrong when as.character(fs[n0]) has scientific notation.
> Example (modified from https://bugs.r-project.org/show_bug.cgi?id=9819):
> op <- options(scipen = 0, OutDec = ".") # (default setting)
> x <- as.POSIXlt("2007-07-27 16:11:03.02")
> as.character(x) # "2007-07-27 16:11:03.983547e-06"
> as.character(x$sec - trunc(x$sec))
> # "1.983547e-06" options(op)

> 'as.character.POSIXt' could temporarily set option 'scipen' large enough 
to prevent scientific notation in as.character(fs[n0]) .


> * Too much precision:
> In some cases with fractional seconds with seconds close to 60, the 
result has many decimal places while there is an accurate representation with 
less decimal places. It is actually OK, just unpleasant.
> Example (modified from https://bugs.r-project.org/show_bug.cgi?id=14693):
> op <- options(scipen = 0, OutDec = ".") # (default setting)
> x <- as.POSIXlt("2011-10-01 12:34:56.3")
> x$sec == 56.3 # TRUE print(x$sec, 17)
> # [1] 56.297 as.character(x)
> # "2011-10-01 12:34:56.297"
> format(x, "%Y-%m-%d %H:%M:%OS1") # short and accurate
> # "2011-10-01 12:34:56.3" ct <- as.POSIXct(x, tz = "UTC")
> identical(ct,
> as.POSIXct("2011-10-01 12:34:56.3", tz = "UTC")) # TRUE
> print(as.numeric(ct), 17) # [1] 1317472496.3
> lct <- as.POSIXlt(ct) lct$sec == 56.3 # FALSE
> print(lct$sec, 17) # [1] 56.29952316284
> as.character(ct) # "2011-10-01 12:34:56.29952316284"
> options(op)

> The "POSIXct" case is a little different because some precision is 
already lost after converted to "POSIXct".

> In 'as.character.POSIXt', using 'as.character' on the seconds (not 
separating the fractional part) might be good enough, but a leading zero must 
be added as necessary.


> * Different from 'format':

> - With fractional seconds, the result is influenced by option 'OutDec'.

> - From "Printing years" in ?strptime: "For years 0 to 999 most OSes pad 
with zeros or spaces to 4 characters, and Linux outputs just the number."
> Because (1900 + x$year) is formatted with %d in 'as.character.POSIXt', 
years 0 to 999 is output without padding. It is different from 'format' in OSes 
other than Linux.


> * Behavior with "improper" "POSIXlt" object:

> - "POSIXlt" object with out-of-bounds components is not normalized.
> Example (modified from regr.tests-1d.R):
> op <- options(scipen = 0) # (default setting)
> x <- structure( list(sec = 1, min = 59L, hour = 18L,
> mday = 6L, mon = 11L, year = 116L, wday = 2L, yday = 340L,
> isdst = 0L, zone = "CET", gmtoff = 3600L),
> class = c("POSIXlt", "POSIXt"), tzone = "CET")
> as.character(x) # "2016-12-06 18:59:1" format(x)
> # "2016-12-06 21:45:40" options(op)

> - With "POSIXlt" object where sec, min, hour, mday, mon, and year 
components are not all of the same length, recycling is not handled.
> Example (modified from regr.tests-1d.R):
> op <- options(scipen = 0) # (default setting)
> x <- structure(
> list(sec = c(1,  2), min = 59L, hour = 18L,
> mday = 6L, mon = 11L, year = 116L, wday = 2L, yday = 340L,
> isdst = 0L, zone = "CET", gmtoff = 3600L),
> class = c("POSIXlt", "POSIXt"), tzone = "CET")
> as.character(x) # c("2016-12-06 18:59:01", "NA NA:NA:02")
> format(x)
> # c("2016-12-06 18:59:01", "2016-12-06 18:59:02")
> options(op)

> __
> R-devel@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] as.character.POSIXt in R devel

2022-10-03 Thread Martin Maechler


> Suharto Anggono Suharto Anggono via R-devel 
> on Sun, 2 Oct 2022 08:42:50 + (UTC) writes:

> With r82904, 'as.character.POSIXt' in R devel is changed. The NEWS item:

>   as.character() now behaves more in line with the
>   methods for atomic vectors such as numbers, and is no longer
>   influenced by options().

> Part of the code:
> 
>   s <- trunc(x$sec)
>   fs <- x$sec - s
>   r1 <- sprintf("%d-%02d-%02d", 1900 + x$year, x$mon+1L, x$mday)
>   if(any(n0 <- time != 0)) # add time if not 0
> r1[n0] <- paste(r1[n0],
>  sprintf("%02d:%02d:%02d%s", x$hour[n0], x$min[n0], s[n0],
> substr(as.character(fs[n0]), 2L, 32L)))


> * Wrong:

> The result is wrong when as.character(fs[n0]) has scientific notation.

yes, you are right.  This is a lapsus I will fix.

> Example (modified from https://bugs.r-project.org/show_bug.cgi?id=9819):
> op <- options(scipen = 0, OutDec = ".") # (default setting)
> x <- as.POSIXlt("2007-07-27 16:11:03.02")
> as.character(x)
> # "2007-07-27 16:11:03.983547e-06"
> as.character(x$sec - trunc(x$sec))
> # "1.983547e-06"
> options(op)

> 'as.character.POSIXt' could temporarily set option 'scipen' large enough 
to prevent scientific notation in as.character(fs[n0]) .

Yes, something like that.


> * Too much precision:

> In some cases with fractional seconds with seconds close to 60, the 
result has many decimal places while there is an accurate representation with 
less decimal places. It is actually OK, just unpleasant.

I agree that is unpleasant.
To someone else I had written that we also may need to improve
the number of decimals shown here.
The design has been that it should be "full precision"
as it is for  as.character()

Now, we know that POSIXct cannot be very precise (in its
fractional seconds) but that is very different for POSIXlt where
fractional seconds may have 14 digits after the decimal point.

Ideally we could *store* with the POSIXlt object if it was
produced from a POSIXct one, and hence have only around 6 valid digits
(after the dec.) or not.  As we cannot currently store/save that
info, we kept using "full" precision which may be much more than
is sensible.

> Example (modified from https://bugs.r-project.org/show_bug.cgi?id=14693):
> op <- options(scipen = 0, OutDec = ".") # (default setting)
> x <- as.POSIXlt("2011-10-01 12:34:56.3")
> x$sec == 56.3 # TRUE

[which may be typical, but may also be platform dependent]

> print(x$sec, 17)
> # [1] 56.297
> as.character(x)
> # "2011-10-01 12:34:56.297"
> format(x, "%Y-%m-%d %H:%M:%OS1") # short and accurate
> # "2011-10-01 12:34:56.3"
> ct <- as.POSIXct(x, tz = "UTC")
> identical(ct,
> as.POSIXct("2011-10-01 12:34:56.3", tz = "UTC"))
> # TRUE
> print(as.numeric(ct), 17)
> # [1] 1317472496.3
> lct <- as.POSIXlt(ct)
> lct$sec == 56.3 # FALSE
> print(lct$sec, 17)
> # [1] 56.29952316284
> as.character(ct)
> # "2011-10-01 12:34:56.29952316284"
> options(op)

> The "POSIXct" case is a little different because some precision is 
already lost after converted to "POSIXct".

yes, indeed.

> In 'as.character.POSIXt', using 'as.character' on the seconds (not 
separating the fractional part) might be good enough, but a leading zero must 
be added as necessary.

I think you are right: that may definitely better...

> * Different from 'format':

> - With fractional seconds, the result is influenced by option 'OutDec'.

Thank you.  I was not aware of that.
The reason "of course" being that  as.character()  is
*also* depending on option  OutDec.

I would say that is clearly wrong...  and I think we should
strongl consider to change that:

'OutDec' should influence print()ing and format()ing  but should
*not* influence  as.character()  at least not for basic R types/objects.


> - From "Printing years" in ?strptime: "For years 0 to 999 most OSes pad 
with zeros or spaces to 4 characters, and Linux outputs just the number."
> Because (1900 + x$year) is formatted with %d in 'as.character.POSIXt', 
years 0 to 999 is output without padding. It is different from 'format' in OSes 
other than Linux.

Good point.  This should be  amended.



> * Behavior with "improper" "POSIXlt" object:

> - "POSIXlt" object with out-of-bounds components is not normalized.

> Example (modified from regr.tests-1d.R):
> op <- options(scipen = 0) # (default setting)
> x <- structure(
> list(sec = 1, min = 59L, hour = 18L,
> mday = 6L, mon = 11L, year = 116L,
> wday = 2L, yday = 340L,
> isdst = 0L, zone = "CET", gmtoff = 3600L),
> class = c("POSIXlt", "POSIXt"), tzone = "CET")
> as.character(x)
> # "2016-12-06 18:59:1"
> format(x)
> # "2016-12-06 21:45:40"
> options(

Re: [Rd] as.character.POSIXt in R devel

2022-10-03 Thread Martin Maechler
> Martin Maechler 
> on Mon, 3 Oct 2022 14:46:08 +0200 writes:

> Suharto Anggono Suharto Anggono via R-devel 
> on Sun, 2 Oct 2022 08:42:50 + (UTC) writes:

>> With r82904, 'as.character.POSIXt' in R devel is changed. The NEWS item:

>> as.character() now behaves more in line with the
>> methods for atomic vectors such as numbers, and is no longer
>> influenced by options().

 [..]

>> * Wrong:

>> The result is wrong when as.character(fs[n0]) has scientific notation.

> yes, you are right.  This is a lapsus I will fix.

>> Example (modified from https://bugs.r-project.org/show_bug.cgi?id=9819):
>> op <- options(scipen = 0, OutDec = ".") # (default setting)
>> x <- as.POSIXlt("2007-07-27 16:11:03.02")
>> as.character(x)
>> # "2007-07-27 16:11:03.983547e-06"
>> as.character(x$sec - trunc(x$sec))
>> # "1.983547e-06"
>> options(op)

>> 'as.character.POSIXt' could temporarily set option 'scipen' large enough 
to prevent scientific notation in as.character(fs[n0]) .

> Yes, something like that.

I have committed a version now of datetime.R,  svn rev 83010 ,
which does no longer depend on  'OutDec' (but gets such argument)
and which has a new 'digits' argument which defaults
to 14 for POSIXlt and
to  6 for POSIXct  .. but the user can choose a different value.

Also, it now uses the equivalent of  as.character(round(x$sec, digits))
(in case the seconds need to be shown)  which also solves the
following  "too much precision"  problem.

>> * Too much precision:

>> In some cases with fractional seconds with seconds close to 60, the 
result has many decimal places while there is an accurate representation with 
less decimal places. It is actually OK, just unpleasant.

> I agree that is unpleasant.
> To someone else I had written that we also may need to improve
> the number of decimals shown here.
> The design has been that it should be "full precision"
> as it is for  as.character()

> Now, we know that POSIXct cannot be very precise (in its
> fractional seconds) but that is very different for POSIXlt where
> fractional seconds may have 14 digits after the decimal point.

> Ideally we could *store* with the POSIXlt object if it was
> produced from a POSIXct one, and hence have only around 6 valid digits
> (after the dec.) or not.  As we cannot currently store/save that
> info, we kept using "full" precision which may be much more than
> is sensible.

>> Example (modified from https://bugs.r-project.org/show_bug.cgi?id=14693):
>> op <- options(scipen = 0, OutDec = ".") # (default setting)
>> x <- as.POSIXlt("2011-10-01 12:34:56.3")
>> x$sec == 56.3 # TRUE

> [which may be typical, but may also be platform dependent]

>> print(x$sec, 17)
>> # [1] 56.297
>> as.character(x)
>> # "2011-10-01 12:34:56.297"
>> format(x, "%Y-%m-%d %H:%M:%OS1") # short and accurate
>> # "2011-10-01 12:34:56.3"
>> ct <- as.POSIXct(x, tz = "UTC")
>> identical(ct,
>> as.POSIXct("2011-10-01 12:34:56.3", tz = "UTC"))
>> # TRUE
>> print(as.numeric(ct), 17)
>> # [1] 1317472496.3
>> lct <- as.POSIXlt(ct)
>> lct$sec == 56.3 # FALSE
>> print(lct$sec, 17)
>> # [1] 56.29952316284
>> as.character(ct)
>> # "2011-10-01 12:34:56.29952316284"
>> options(op)

>> The "POSIXct" case is a little different because some precision is 
already lost after converted to "POSIXct".

> yes, indeed.

>> In 'as.character.POSIXt', using 'as.character' on the seconds (not 
separating the fractional part) might be good enough, but a leading zero must 
be added as necessary.

> I think you are right: that may definitely better...

indeed; part of my commit.

>> * Different from 'format':

>> - With fractional seconds, the result is influenced by option 'OutDec'.

this has been solved, too.
For the "freaks" allowing an explicit  'OutDec = *' argument
but *not* with default depending on options()!


> Thank you.  I was not aware of that.
> The reason "of course" being that  as.character()  is
> *also* depending on option  OutDec.

> I would say that is clearly wrong...  and I think we should
> strongl consider to change that:

> 'OutDec' should influence print()ing and format()ing  but should
> *not* influence  as.character()  at least not for basic R types/objects.


>> - From "Printing years" in ?strptime: "For years 0 to 999 most OSes pad 
with zeros or spaces to 4 characters, and Linux outputs just the number."
>> Because (1900 + x$year) is formatted with %d in 'as.character.POSIXt', 
years 0 to 999 is output without padding. It is different from 'format' in OSes 
other than Linux.

> Good point.  This should be  amended.

Not yet.  Actually, I'm no longer sure this needs any action.
I find it somew

Re: [Rd] Question about grid.group compositing operators in cairo

2022-10-03 Thread Paul Murrell


Interim update:  I have spoken with Thomas Lin Pedersen (cc'ed), the 
author/maintainer of 'ragg' and 'svglite', who is working on adding 
group support for those graphics devices and he has voted in support of 
the current Cairo implementation, so the needle has shifted towards 
Cairo at this stage.


I still want to do more tests on other devices to gather more evidence.

Paul

p.s.  Attached (if it makes it through the filters) is a manual 
modification of your original dsvg() example that has been changed so 
that it produces the Cairo result.  This is probably not exactly how you 
would want to implement the dsvg() solution, but it is at least a proof 
of concept that the Cairo result can be produced in SVG.


On 30/09/22 10:49, Paul Murrell wrote:

Hi

Some more thoughts ...

<1>
I said before that currently, dev->group() does this ...

[OVER] shape shape shape OP shape shape shape

... and one option would be an implicit group on 'src' and 'dst' like 
this ...


([OVER] shape shape shape) OP ([OVER] shape shape shape)

... but another approach could be just an implicit group on each shape, 
like this ...


[OVER] ([OVER] shape) ([OVER] shape) OP ([OVER] shape) ([OVER] shape)

That may be a better representation of what you are already doing with 
dsvg() ?  It may also better reflect what naturally occurs in some 
graphics systems.


<2>
Changing the Cairo implementation to work like that would I think 
produce the same result as your dsvg() for ...


grid.group(src, "in", dst)

... and it would make what constitutes more than one shape much less 
surprising ...


gList(rectGrob(), rectGrob())  ## multiple shapes (obviously)
rectGrob(width=1:2/2)  ## multiple shapes (less obvious)
rectGrob(gp=gpar(col=, fill=)) ## NOT multiple shapes (no surprise)

... and it should not break any pre-existing non-group behaviour.

<3>
One casualty from this third option would be that the following would no 
longer solve the overlapping fill and stroke problem ...


grid.group(overlapRect, "source")

... although the fact that that currently works is really a bit 
surprising AND that result could still be achieved by explicitly drawing 
separate shapes ...


grid.group(rectGrob(gp=gpar(col=rgb(1,0,0,.5), lwd=20, fill=NA)),
    "source",
    rectGrob(gp=gpar(col=NA, fill="green")))

<4>
I need to try some of this out and also check in with some other people 
who I think are working on implementing groups on different graphics 
devices.


<5>
In summary, don't go changing dsvg() too much just yet!

Paul

On 29/09/2022 1:30 pm, Paul Murrell wrote:

Hi

Would it work to explicitly record a filled-and-stroked shape as two 
separate elements (one only filled and one only stroked) ?


Then it should only be as hard to apply the active operator on both of 
those elements as it is to apply the active operator to more than one 
shape (?)


Paul

On 29/09/22 10:17, Panagiotis Skintzos wrote:

Thank you for the very thorough explanation Paul.

To answer your question on 11: The dsvg device, simply defines svg
elements with their attributes (rect with fill & stroke in my examples).
It does not do any internal image processing like cairo.

My concern is how to proceed with the implementation in dsvg.

If I leave it as it is now, they're will be cases where it will give
different results from cairo (and perhaps other devices that will
implement group compositing in similar way).

On the other hand It would be quite challenging in practice to simulate
the cairo implementation and apply first the fill and then the stroke
with the active operator, on the element itself.

Any suggestions? :-)

Panagiotis


On 28/9/22 02:56, Paul Murrell wrote:
 > Hi
 >
 > Thanks for the code (and for the previous attachments).
 >
 > Some thoughts so far (HTML version with images attached) ...
 >
 > <1>
 > As you have pointed out, the Cairo device draws a stroked-and-filled
 > shape with two separate drawing operations: the path is filled and
 > then the path is stroked.  I do not believe that there is any
 > alternative in Cairo graphics (apart from filling and stroking as an
 > isolated group and then drawing the group, which we will come back 
to).

 >
 > <2>
 > This fill-then-stroke approach is easy to demonstrate just with a 
thick

 > semitransparent border ...
 >
 > library(grid)
 > overlapRect <- rectGrob(width=.5, height=.5,
 >     gp=gpar(fill="green", lwd=20,
 >     col=rgb(1,0,0,.5)))
 > grid.newpage()
 > grid.draw(overlapRect)
 >
 > <3>
 > This fill-then-stroke approach is what happens on many (most?)
 > graphics devices, including, for example, the core windows() device,
 > the core quartz() device, the 'ragg' devices, and 'ggiraph'.  The
 > latter is true because this is actually the defined behaviour for 
SVG ...

 >
 > https://www.w3.org/TR/SVG2/render.html#Elements 

 > https://www.w3.org/TR/SVG2/render.html#Paintin