Accessing the Quick TUV calculator
Package ‘photobiologyInOut’ 0.4.28.1.9000
Pedro J. Aphalo
2024-10-04
Source:vignettes/articles/tuv-examples.Rmd
tuv-examples.Rmd
Introduction
Package ‘photobiologyInOut’ since 2018, versions (>= 0.4.15), has supported the import of the output files from interactively run spectral simulations done in the Quick TUV calculator, as exemplified in the User Guide.
In versions (>= 0.4.29) it is also possible to call the Quick TUV
calculator server directly from within R, to get the spectral data
returned in a source_spct
object or in a
source_mspct
ready to be used with functions from the R for
Photobiology suite, or used as data frames with other R code. Examples
demostrating this new feature need to access the UCAR server, and
because of this, they included in this article, that is part of the
on-line documentation, but not distributed as part of the package.
The implementation of the interaction with the server is inspired on
that used in package ‘foqat’. This is actually very simple: to construct
URLs identical to those generated by the [Quick TUV calculator web
interface] and use them to download the computed spectral data into a
file. This file is already in a format supported by function
read_qtuv_txt()
avaialble in package ‘photobiologyInOut’
(>= 0.4.15).
## Loading required package: photobiology
## News at https://www.r4photobiology.info/
## Loading required package: ggplot2
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
theme_set(theme_bw() + theme(legend.position = "top"))
force_qtuv_call <- FALSE # set to TRUE to recalculate cached QTUV-generated data
In this file, we call the Quick TUV calculator server only once and save the returned value in a local file. Please, consider using this same approach in your scripts to avoid unnecessarily overloading the public server.
Simulation of a single spectrum
In the first example, using default arguments for all parameters
except time
, the text returned by the sever is saved into a
temporary file, the data read into a source_spct()
and the
file deleted. The default for sun.elevation
is
NULL
and the sun elevation is compute from the geographic
coordinates and time coordinates.
# avoid repeated calls to Quick TUV server
sun_greenwich.spct.filepath <- "./sun-greenwich.spct.rda"
if (!force_qtuv_call && file.exists(sun_greenwich.spct.filepath)) {
load(sun_greenwich.spct.filepath)
} else {
sun_greenwich.spct <-
qtuv_s.e.irrad(time = ymd_hm("2024-06-23 12:00", tz = "UTC"))
save(sun_greenwich.spct, file = sun_greenwich.spct.filepath)
}
colnames(sun_greenwich.spct)
## [1] "w.length" "s.e.irrad" "s.e.irrad.dir"
## [4] "s.e.irrad.diff.down" "s.e.irrad.diff.up"
Variable s.e.irrad
corresponds to the total down-welling
spectral irradiance. Variable s.e.irrad.dir
is direct,
s.e.irrad.diff.down
is down-welling diffuse radiation and
s.e.irrad.diff.up
is up-welling diffuse radiation.
The summary shows in addition to a summary of the data, some impotant metadata.
summary(sun_greenwich.spct)
## Summary of source_spct [140 x 5] object: sun_greenwich.spct
## Wavelength range 280.5-419.5 nm, step 1 nm
## Label: Solar spectrum (model simulation). File: file30e01a984eed
## Measured on 2024-06-23 12:00:00 UTC
## Measured at 51.5 N, 0 E; Greenwich
## Variables:
## w.length: Wavelength [nm]
## s.e.irrad: Spectral energy irradiance [W m-2 nm-1]
## --
## w.length s.e.irrad s.e.irrad.dir s.e.irrad.diff.down
## Min. :280.5 Min. :0.0000 Min. :0.00000 Min. :0.0000
## 1st Qu.:315.2 1st Qu.:0.2241 1st Qu.:0.08329 1st Qu.:0.1368
## Median :350.0 Median :0.5804 Median :0.27660 Median :0.2916
## Mean :350.0 Mean :0.5620 Mean :0.30947 Mean :0.2525
## 3rd Qu.:384.8 3rd Qu.:0.7776 3rd Qu.:0.43155 3rd Qu.:0.3544
## Max. :419.5 Max. :1.3310 Max. :0.86390 Max. :0.4865
## s.e.irrad.diff.up
## Min. :0.00000
## 1st Qu.:0.02241
## Median :0.05804
## Mean :0.05620
## 3rd Qu.:0.07777
## Max. :0.13310
## SPECTRAL IRRADIANCE (W m-2 nm-1):
## computed by UCAR's Quick TUV calculator
## read from file: file30e01a984eed
## with modification date: 2024-10-04 15:48:11
## ozone column: 300 DU
## sun elevation: 61.9078712 degrees
## ground altitude: 0 km a.s.l.
## observer altitude: 0 km a.s.l.
what_measured(sun_greenwich.spct)
## [1] "Solar spectrum (model simulation). File: file30e01a984eed"
when_measured(sun_greenwich.spct)
## [1] "2024-06-23 12:00:00 UTC"
how_measured(sun_greenwich.spct)
## [1] "Computer simulation with the TUV model version 5.3 Using -2 streams."
where_measured(sun_greenwich.spct)
## # A tibble: 1 × 3
## lon lat address
## <dbl> <dbl> <chr>
## 1 0 51.5 Greenwich
attr(sun_greenwich.spct, "qtuv.url")
## [1] "https://www.acom.ucar.edu/cgi-bin/acom/TUV/V5.3/tuv?wStart=280&wStop=420&wIntervals=140&inputMode=0&latitude=51.5&longitude=0&date=20240623&timeStamp=12:00:00&zenith=0&ozone=300&albedo=0.1&gAltitude=0&mAltitude=0&taucld=0&zbase=4&ztop=5&tauaer=0.235&ssaaer=0.99&alpha=1&time=12&outputMode=5&nStreams=-2&dirsun=1&difdn=1&difup=0"
autoplot(sun_greenwich.spct)
To save the raw output from TUV into a persistent file, we have to provide a file name. We also extend the wavelength range, and provide the coordinates of a different location.
my.geocode <- data.frame(lon = 24.96474, lat = 60.20911)
# avoid repeated calls to Quick TUV server
sun_viikki.spctfile.path <- "./sun-viikki.spct.rda"
if (!force_qtuv_call && file.exists(sun_viikki.spctfile.path)) {
load(sun_viikki.spctfile.path)
} else {
sun_viikki.spct <-
qtuv_s.e.irrad(time = ymd_hm("2024-06-23 12:20", tz = "EET"),
w.length = 290:800,
geocode = my.geocode,
file = "qtuv-viikki-test.txt")
save(sun_viikki.spct, file = sun_viikki.spctfile.path)
}
summary(sun_viikki.spct)
## Summary of source_spct [510 x 5] object: sun_viikki.spct
## Wavelength range 290-800 nm, step 1-1.005 nm
## Label: Solar spectrum (model simulation). File: qtuv-viikki-test.txt
## Measured on 2024-06-23 09:20:00 UTC
## Variables:
## w.length: Wavelength [nm]
## s.e.irrad: Spectral energy irradiance [W m-2 nm-1]
## --
## w.length s.e.irrad s.e.irrad.dir s.e.irrad.diff.down
## Min. :290.0 Min. :0.0000001 Min. :0.0000001 Min. :0.0000001
## 1st Qu.:417.5 1st Qu.:0.8552000 1st Qu.:0.6554250 1st Qu.:0.1426250
## Median :545.0 Median :1.0635000 Median :0.8748000 Median :0.2267500
## Mean :545.0 Mean :0.9653408 Mean :0.7315923 Mean :0.2337341
## 3rd Qu.:672.5 3rd Qu.:1.2085000 3rd Qu.:0.9469750 3rd Qu.:0.3135750
## Max. :800.0 Max. :1.4020000 Max. :1.0090000 Max. :0.4465000
## s.e.irrad.diff.up
## Min. :1.000e-08
## 1st Qu.:8.552e-02
## Median :1.064e-01
## Mean :9.653e-02
## 3rd Qu.:1.208e-01
## Max. :1.402e-01
The file was not deleted because a file name was passed as aargument in the call above.
file.exists("qtuv-viikki-test.txt")
## [1] TRUE
The spectrum was also imported into R as a source_spct
object for which an autoplot()
method is defined in package
‘ggspectra’.
autoplot(sun_viikki.spct)
autoplot(sun_viikki.spct, unit.out = "photon")
Simulation of a collection of spectra
Not to abuse the use of the UCAR server, the examples in this section create collections of very few spectra. The functions do not impose any strict limit but keep in mind that the recommended maximum is 100 spectra per user and day.
Four different ozone column thicknesses.
# avoid repeated calls to Quick TUV server
sun_viikki_ozone.mspct.filepath <- "./sun_viikki_ozone.mspct.rda"
if (!force_qtuv_call && file.exists(sun_viikki_ozone.mspct.filepath)) {
load(sun_viikki_ozone.mspct.filepath)
} else {
sun_viikki_ozone.mspct <-
qtuv_m_s.e.irrad(
time = ymd_hm("2024-06-23 12:20", tz = "EET"),
ozone.du = c(200, 250, 300, 350),
w.length = 290:450,
geocode = my.geocode
)
save(sun_viikki_ozone.mspct, file = sun_viikki_ozone.mspct.filepath)
}
summary(sun_viikki_ozone.mspct)
## Summary of source_mspct [4 x 1] object: sun_viikki_ozone.mspct
## # A tibble: 4 × 8
## spct.idx class dim w.length.min w.length.max colnames multiple.wl time.unit
## <chr> <chr> <chr> <dbl> <dbl> <list> <dbl> <chr>
## 1 ozone.200 sour… [160… 290. 450. <chr> 1 second
## 2 ozone.250 sour… [160… 290. 450. <chr> 1 second
## 3 ozone.300 sour… [160… 290. 450. <chr> 1 second
## 4 ozone.350 sour… [160… 290. 450. <chr> 1 second
Three sun elevation angles above the horizon in degrees. Geographic and time coordinates are used to compute the sun elevation angle when the angle is not supplied as in other examples, but if the angle is passed as an argument, they are ignored.
# avoid repeated calls to Quick TUV server
sun_viikki_elevation.mspct.filepath <- "./sun_viikki_elevation.mspct.rda"
if (!force_qtuv_call && file.exists(sun_viikki_elevation.mspct.filepath)) {
load(sun_viikki_elevation.mspct.filepath)
} else {
sun_viikki_elevation.mspct <-
qtuv_m_s.e.irrad(
sun.elevation = c(60, 40, 20),
w.length = 290:450,
geocode = my.geocode
)
save(sun_viikki_elevation.mspct, file = sun_viikki_elevation.mspct.filepath)
}
summary(sun_viikki_elevation.mspct)
## Summary of source_mspct [3 x 1] object: sun_viikki_elevation.mspct
## # A tibble: 3 × 8
## spct.idx class dim w.length.min w.length.max colnames multiple.wl time.unit
## <chr> <chr> <chr> <dbl> <dbl> <list> <dbl> <chr>
## 1 sun.elev… sour… [160… 290. 450. <chr> 1 second
## 2 sun.elev… sour… [160… 290. 450. <chr> 1 second
## 3 sun.elev… sour… [160… 290. 450. <chr> 1 second
autoplot(sun_viikki_elevation.mspct)
Three different times of the day.
# avoid repeated calls to Quick TUV server
sun_viikki_time.mspct.filepath <- "./sun_viikki_time.mspct.rda"
if (!force_qtuv_call && file.exists(sun_viikki_time.mspct.filepath)) {
load(sun_viikki_time.mspct.filepath)
} else {
sun_viikki_time.mspct <-
qtuv_m_s.e.irrad(
time = ymd_hm("2024-06-23 12:20", tz = "EET") +
hours(c(0, 3, 6)),
w.length = 290:750,
geocode = my.geocode
)
save(sun_viikki_time.mspct, file = sun_viikki_time.mspct.filepath)
}
summary(sun_viikki_time.mspct)
## Summary of source_mspct [3 x 1] object: sun_viikki_time.mspct
## # A tibble: 3 × 8
## spct.idx class dim w.length.min w.length.max colnames multiple.wl time.unit
## <chr> <chr> <chr> <dbl> <dbl> <list> <dbl> <chr>
## 1 time.202… sour… [460… 290 750 <chr> 1 second
## 2 time.202… sour… [460… 290 750 <chr> 1 second
## 3 time.202… sour… [460… 290 750 <chr> 1 second
autoplot(sun_viikki_time.mspct, facets = 1)
Three different latitudes.
my.geocodes <- data.frame(lat = c(30, 50, 70),
lon = rep(25, 3))
my.geocodes[["address"]] <-
paste("lat", my.geocodes[["lat"]], sep = ".")
# avoid repeated calls to Quick TUV server
sun_latitudes.mspct.filepath <- "./sun_latitudes.mspct.rda"
if (!force_qtuv_call && file.exists(sun_latitudes.mspct.filepath)) {
load(sun_latitudes.mspct.filepath)
} else {
sun_latitudes.mspct <-
qtuv_m_s.e.irrad(
time = ymd_hm("2024-06-23 12:20", tz = "EET"),
w.length = 290:750,
geocode = my.geocodes
)
save(sun_latitudes.mspct, file = sun_latitudes.mspct.filepath)
}
summary(sun_latitudes.mspct)
## Summary of source_mspct [3 x 1] object: sun_latitudes.mspct
## # A tibble: 3 × 8
## spct.idx class dim w.length.min w.length.max colnames multiple.wl time.unit
## <chr> <chr> <chr> <dbl> <dbl> <list> <dbl> <chr>
## 1 geocode.… sour… [460… 290 750 <chr> 1 second
## 2 geocode.… sour… [460… 290 750 <chr> 1 second
## 3 geocode.… sour… [460… 290 750 <chr> 1 second
autoplot(sun_latitudes.mspct, facets = 1)
Six different ground altitudes, with measurements at ground level.
# avoid repeated calls to Quick TUV server
ground_altitudes.mspct.filepath <- "./ground_altitudes.mspct.rda"
if (!force_qtuv_call && file.exists(ground_altitudes.mspct.filepath)) {
load(ground_altitudes.mspct.filepath)
} else {
ground_altitudes.mspct <-
qtuv_m_s.e.irrad(
ground.altitude = 0:5,
w.length = 290:450,
sun.elevation = 45
)
save(ground_altitudes.mspct, file = ground_altitudes.mspct.filepath)
}
summary(ground_altitudes.mspct)
## Summary of source_mspct [6 x 1] object: ground_altitudes.mspct
## # A tibble: 6 × 8
## spct.idx class dim w.length.min w.length.max colnames multiple.wl time.unit
## <chr> <chr> <chr> <dbl> <dbl> <list> <dbl> <chr>
## 1 altitude… sour… [160… 290. 450. <chr> 1 second
## 2 altitude… sour… [160… 290. 450. <chr> 1 second
## 3 altitude… sour… [160… 290. 450. <chr> 1 second
## 4 altitude… sour… [160… 290. 450. <chr> 1 second
## 5 altitude… sour… [160… 290. 450. <chr> 1 second
## 6 altitude… sour… [160… 290. 450. <chr> 1 second
Two different cloud conditions.
my.clouds <- qtuv_clouds(c("clear.sky", "cirrus"))
# avoid repeated calls to Quick TUV server
sun_viikki_clouds.mspct.filepath <- "./sun_viikki_clouds.mspct.rda"
if (!force_qtuv_call && file.exists(sun_viikki_clouds.mspct.filepath)) {
load(sun_viikki_clouds.mspct.filepath)
} else {
sun_viikki_clouds.mspct <-
qtuv_m_s.e.irrad(
time = ymd_hm("2024-06-23 12:20", tz = "EET"),
w.length = 290:750,
geocode = my.geocode,
clouds = my.clouds
)
save(sun_viikki_clouds.mspct, file = sun_viikki_clouds.mspct.filepath)
}
summary(sun_viikki_clouds.mspct)
## Summary of source_mspct [2 x 1] object: sun_viikki_clouds.mspct
## # A tibble: 2 × 8
## spct.idx class dim w.length.min w.length.max colnames multiple.wl time.unit
## <chr> <chr> <chr> <dbl> <dbl> <list> <dbl> <chr>
## 1 clouds.c… sour… [460… 290 750 <chr> 1 second
## 2 clouds.c… sour… [460… 290 750 <chr> 1 second
autoplot(sun_viikki_clouds.mspct, facets = 1)
For three times, as above, but keeping the downloaded files, by passing a file name “root”.
# avoid repeated calls to Quick TUV server
sun_viikki_time.mspct.filepath <- "./sun_viikki_time.mspct.rda"
if (!force_qtuv_call && file.exists(sun_viikki_time.mspct.filepath)) {
load(sun_viikki_time.mspct.filepath)
} else {
sun_viikki_time.mspct <-
qtuv_m_s.e.irrad(
time = ymd_hm("2024-06-23 12:20", tz = "EET") +
hours(c(0, 3, 6)),
w.length = 290:750,
geocode = my.geocode,
file = "qtuv-viikki"
)
save(sun_viikki_time.mspct, file = sun_viikki_time.mspct.filepath)
}
summary(sun_viikki_time.mspct)
## Summary of source_mspct [3 x 1] object: sun_viikki_time.mspct
## # A tibble: 3 × 8
## spct.idx class dim w.length.min w.length.max colnames multiple.wl time.unit
## <chr> <chr> <chr> <dbl> <dbl> <list> <dbl> <chr>
## 1 time.202… sour… [460… 290 750 <chr> 1 second
## 2 time.202… sour… [460… 290 750 <chr> 1 second
## 3 time.202… sour… [460… 290 750 <chr> 1 second
autoplot(sun_viikki_time.mspct, facets = 1)
list.files(pattern = "^qtuv-viikki-time.*")
## [1] "qtuv-viikki-time.2024.06.23.12.20.00.txt"
## [2] "qtuv-viikki-time.2024.06.23.15.20.00.txt"
## [3] "qtuv-viikki-time.2024.06.23.18.20.00.txt"