photobiology 0.9.13
User Guide: 3 Astronomy

Pedro J. Aphalo

2016-12-18

Getting started

We load two packages, our ‘photobiology’ and ‘lubridate’, as they will be used in the examples.

library(photobiology)
library(lubridate)
## 
## Attaching package: 'lubridate'
## The following object is masked from 'package:base':
## 
##     date

Astronomy

The functions and methods described in this section return either values that represent angles or times. In the current version angles are always expressed in degrees. In the case of times, the unit of expression, can be changed through parameter unit.out which accepts the following arguments "datetime", "hour", "minute", "second". For backwards compatibility "date" is also accepted as equivalent to "datetime" but deprecated.

Position of the sun

In photobiology research we sometimes need to calculate the position on the sun at arbitrary geographic locations and times. The function sun_angles returns the azimuth in degrees eastwards, altitude in degrees above the horizon, solar disk diameter in degrees and sun to earth distance in astronomical units. The time should be a POSIXct vector, possibly of length one. The easiest way create date and time constant values is to use package lubridate.


In versions up to 0.9.11 in addition parameter geocode most functions also had the redundant formal parameters lon and lat which were removed in version 0.9.12. This change may require users’ scripts to be revised.
sun_angles(now(), geocode = data.frame(lat = 34, lon = 0))
##                  time tz solartime longitude latitude address  azimuth
## 1 2016-12-18 00:18:58     22:22:16         0       34    <NA> 289.9919
##   elevation
## 1 -66.17556
sun_angles(ymd_hms("2014-01-01 0:0:0", tz = "UTC") + hours(1:3))
##                  time  tz solartime longitude latitude   address  azimuth
## 1 2014-01-01 01:00:00 UTC  00:56:31         0     51.5 Greenwich 26.26506
## 2 2014-01-01 02:00:00 UTC  01:56:30         0     51.5 Greenwich 49.24212
## 3 2014-01-01 03:00:00 UTC  02:56:29         0     51.5 Greenwich 66.84595
##   elevation
## 1 -59.47735
## 2 -53.73359
## 3 -45.80941

When spectra contain suitable metadata, the position of the sun for the spectral irradiance data measurement can be easily obtained.

sun_angles(getWhenMeasured(sun.spct), geocode = getWhereMeasured(sun.spct))
##                  time  tz solartime longitude latitude
## 1 2010-06-22 09:51:00 UTC  11:28:50  24.96424 60.20942
##                 address azimuth elevation
## 1 Kumpula, Helsinki, FI 168.122  52.82309

The object to be supplied as argument for geocode is a data frame with variables lon and lat. This matches the return value of function ggmap::geocode(), function that can be used to find the coordinates using any address entered as a character string understood by the Google maps API.

Times of sunrise, solar noon and sunset

Functions sunrise_time, sunset_time, noon_time, day_length and night_length have all the same parameter signature. In addition, function day_night returns a data frame containing all the quantities returned by the other functions. They are all vectorized for the date and geocode parameters.

We create a vector of dates to use in the examples—default time zone of ymd is UTC.

dates <- seq(from = ymd("2015-03-01"), to = ymd("2015-07-1"), length.out = 3)

Default latitude is zero (the Equator), the default longitude is zero (Greenwich), and default time zone for the functions in the photobiology package is in most cases the time zone returned by the operating system, but values are stored in time zone "UTC". Be also aware that for summer dates the times are formatted for printing accordingly. In the examples below this can be recognized for example, by the time zone being reported as EEST instead of EET for Eastern Europe.

noon_time(dates, tz = "UTC", data.frame(lat = 34, lon = 0))
## [1] "2015-03-01 12:12:20 UTC" "2015-05-01 11:57:06 UTC"
## [3] "2015-07-01 12:03:52 UTC"
noon_time(dates, tz = "CET", data.frame(lat = 34, lon = 0))
## [1] "2015-03-01 13:12:20 CET"  "2015-05-01 13:57:06 CEST"
## [3] "2015-07-01 14:03:52 CEST"
day_night(dates, geocode = data.frame(lat = 60, lon = 0))
##          day              tz twilight.rise twilight.set longitude latitude
## 1 2015-03-01 Europe/Helsinki          none         none         0       60
## 2 2015-05-01 Europe/Helsinki          none         none         0       60
## 3 2015-07-01 Europe/Helsinki          none         none         0       60
##   address  sunrise     noon     sunset daylength nightlength
## 1    <NA> 9.082918 14.20557 19.3282169 10.245299   13.754701
## 2    <NA> 7.086868 14.95169 22.8165183 15.729651    8.270349
## 3    <NA> 5.892324 15.06447  0.2366178 -5.655707   29.655707

he default for date is the current day.

sunrise_time(geocode = data.frame(lat = 60, lon = 0))
## [1] "2016-12-18 11:00:33 EET"

Both latitude and longitude should be supplied through geocode, but be aware that if the returned value is desired in the local time coordinates of the argument passed to gocode, the time zone should match the geographic coordinates.

sunrise_time(today("UTC"), tz = "UTC", geocode = data.frame(lat = 60, lon = 0))
## [1] "2016-12-17 08:59:46 UTC"
sunrise_time(today("EET"), tz = "EET", geocode = data.frame(lat = 60, lon = 25))
## [1] "2016-12-18 09:20:33 EET"

Southern hemisphere latitudes as well as longitudes to the West of the Greenwich meridian should be supplied as negative numbers.

sunrise_time(dates, geocode = data.frame(lat = 60, lon = 0))
## [1] "2015-03-01 08:58:05 EET"  "2015-05-01 06:57:19 EEST"
## [3] "2015-07-01 05:42:30 EEST"
sunrise_time(dates, geocode = data.frame(lat = -60, lon = 0))
## [1] "2015-03-01 07:12:45 EET"  "2015-05-01 10:41:14 EEST"
## [3] "2015-07-01 12:03:42 EEST"

The angle used in the twilight calculation can be supplied, either as the name of a standard definition, or as an angle in degrees (negative for sun positions below the horizon). Positive angles can be used when the time of sun occlusion behind a building, mountain, or other obstacle needs to be calculated.

sunrise_time(today("EET"), tz = "EET", 
             geocode = data.frame(lat = 60, lon = 25),
             twilight = "civil")
## [1] "2016-12-18 08:22:49 EET"
sunrise_time(today("EET"), tz = "EET", 
             geocode = data.frame(lat = 60, lon = 25),
             twilight = -10)
## [1] "2016-12-18 07:44:09 EET"
sunrise_time(today("EET"), tz = "EET", 
             geocode = data.frame(lat = 60, lon = 25),
             twilight = +12)
## [1] NA

Parameter unit.out can be used to obtain the returned value expressed as time-of-day in hours, minutes, or seconds since midnight.

sunrise_time(today("EET"), 
             tz = "EET", 
             geocode = data.frame(lat = 60, lon = 25),
             unit.out = "hours")
## [1] 9.342699

Functions day_length and night_length return by default the length of time in hours.

day_length(dates, geocode = data.frame(lat = 60, lon = 25))
## [1] 10.47461 15.99267 18.71209
night_length(dates, geocode = data.frame(lat = 60, lon = 25))
## [1] 13.525392  8.007326  5.287909

Function day_night returns a data frame.

day_night(dates, 
          geocode = data.frame(lat = 60, lon = 25))
##          day              tz twilight.rise twilight.set longitude latitude
## 1 2015-03-01 Europe/Helsinki          none         none        25       60
## 2 2015-05-01 Europe/Helsinki          none         none        25       60
## 3 2015-07-01 Europe/Helsinki          none         none        25       60
##   address  sunrise     noon   sunset daylength nightlength
## 1    <NA> 7.416251 12.53890 17.66155  10.24530   13.754701
## 2    <NA> 5.420201 13.28503 21.14985  15.72965    8.270349
## 3    <NA> 4.225658 13.39780 22.56995  18.34429    5.655707
day_night(dates, 
          geocode = data.frame(lat = 60, lon = 25), 
          unit.out = "datetime")
##          day              tz twilight.rise twilight.set longitude latitude
## 1 2015-03-01 Europe/Helsinki          none         none        25       60
## 2 2015-05-01 Europe/Helsinki          none         none        25       60
## 3 2015-07-01 Europe/Helsinki          none         none        25       60
##   address             sunrise                noon              sunset
## 1    <NA> 2015-03-01 07:24:58 2015-03-01 12:32:20 2015-03-01 17:39:41
## 2    <NA> 2015-05-01 05:25:12 2015-05-01 13:17:06 2015-05-01 21:08:59
## 3    <NA> 2015-07-01 04:13:32 2015-07-01 13:23:52 2015-07-01 22:34:11
##   daylength nightlength
## 1  10.24530   13.754701
## 2  15.72965    8.270349
## 3  18.34429    5.655707

Solar time

In field research it is in many cases preferable to sample or measure, and present and plot data based on local solar time. Two functions are provided. They differ in the value returned, either a time of day in hours, or a date.

Paris.geo <- data.frame(lon = 2.352222, lat = 48.85661, address = "Paris")
Paris.time <- ymd_hms("2016-09-30 06:00:00", tz = "UTC")
solar_time(Paris.time, geocode = Paris.geo)
## [1] "06:19:33"
solar_time(Paris.time, geocode = Paris.geo, unit.out = "datetime")
## [1] "2016-09-30 06:19:33 solar"
my.solar.t <- solar_time(Paris.time, geocode = Paris.geo)
is.solar_time(my.solar.t)
## [1] TRUE
is.numeric(my.solar.t)
## [1] TRUE
my.solar.d <- solar_time(Paris.time, geocode = Paris.geo, unit.out = "datetime")
is.solar_date(my.solar.d)
## [1] TRUE
is.timepoint(my.solar.d)
## [1] TRUE

Time of day

Function as_tod() facilitates conversion of R’s time date objects into a numeric value representing the time of day in one of hour, minute or second as unit of expression.

times <- now() + days(0:1)
times
## [1] "2016-12-18 00:18:58 EET" "2016-12-19 00:18:58 EET"
as_tod(times)
## [1] 0.3163843 0.3163843
as_tod(times, unit.out = "minutes")
## [1] 18.98306 18.98306