swmmr icon indicating copy to clipboard operation
swmmr copied to clipboard

read_out() as.POSIXct "GMT" stamp

Open joelnc opened this issue 4 years ago • 2 comments

Hi,

I'm having trouble with the referenced line in read_out:

time <- as.POSIXct(GetSwmmTimes(), tz = "GMT", origin = "1899-12-30")

In my use case, I am in eastern USA, and use the "America/Panama" time zone for my data (i.e., eastern time with no daylight savings). So the rainfall and climate data that is fed to my SWMM models is in year round Eastern Standard, -5 offset, as is my flow data that I use for calibration.

But then the line referenced above seems to reads my model output and stamp it as GMT, which it is not. Then if I convert that GMT time series to "America/Panama" via standard conversion tools, I will have subtracted 5 hours off of my data creating a lag between simulated and observed.

My current workaround is to read the output with read_out, then convert those data to a data.frame (as I'm more comfortable manipulating date/times there as opposed to with xts objects), and then I do a super kludgey substring/paste to rip off the "GMT" and stick on "-0500" as tz, basically to undo what read_out() does. Relevant code section from my obj_fun() function is below. Per all my testing thus far this works, but I'm wondering if I'm missing something or if this could actually be a problem for others as well.


    ## Read sim result
    ## iType: 0 subs; 1 nodes; 2 links; 3 sys vars
    simAll <- read_out(file=swmm_files$out, iType=2,
                       object_name="l3883", vIndex=0) # see docs for vIndex vals
    sim <- simAll[["l3883"]]$flow_rate # directly access to xts object

    ## SWMMR xts to plain data frame
    simDf <- data.frame(dt=index(sim),
                        sim=coredata(sim))

    ## Ok rough fix of mis-stamped GMT to EST... here we go
    simDf$dt <- as.POSIXct(paste(substr(simDf$dt,1,16), "-0500"),
                           format="%Y-%m-%d %H:%M %z", tz="America/Panama")
  
    ## Merge simulated and observed into single df
    combDf <- merge(obs, simDf, all=FALSE)

    ## Pass merged DF to objective fun
    return(nseFun(combDf)*-1)

As a fix, I could imagine adding another input arg to the read_out function that would take the user's preferred time stamp and pass that to the as.POSIXct call. I've gone through some of the source files, but the approach/tooling with Rcpp is a bit beyond my current capabilities.

Any feedback appreciated.

joelnc avatar Jan 25 '21 19:01 joelnc

Thanks for reporting this!

If you need a quick solution, I would suggest to check out the fantastic lubridate package and simply override the time zone.

The next option would be to change the line

https://github.com/dleutnant/swmmr/blob/3e373e6399a6b25f1644d86a36f2c11b9a73510b/R/read_out.R#L116

and insert either (1) the user’s current timezone, i.e. the one which R found at startup or (2) add a new argument to the function tz = Sys.timezone() and use this as a parameter in the line shown above (of course, a fallback tz could be set if R fails to detect the time zone.

dleutnant avatar Jan 26 '21 20:01 dleutnant

Thanks Dominik.

What I have above works for me as a workaround, but I just looked and it does appear lubridate has a force_tz function that many would probably find cleaner than my as.POSIX(paste(substr(..))) construct. Or modifying the function itself as you suggest.

Flagging this for @mrament and @CChaoE17 as I know they may need a heads up on it.

joelnc avatar Jan 27 '21 18:01 joelnc