diff --git a/.Rbuildignore b/.Rbuildignore index 170e38a..b60119f 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -14,3 +14,5 @@ ^app\.R$ ^vignettes/articles$ ^\.gitlab-ci\.yml$ +^cran-comments\.md$ +^LightLogR-manual\.tex$ \ No newline at end of file diff --git a/DESCRIPTION b/DESCRIPTION index 7ca4a6c..2204498 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: LightLogR -Title: Work With Data from Wearable Light Loggers and Optical Radiation Dosimeters -Version: 0.3.7 +Title: Process Data from Wearable Light Loggers and Optical Radiation Dosimeters +Version: 0.3.8 Authors@R: c( person("Johannes", "Zauner", email = "johannes.zauner@tum.de", role = c("aut", "cre"), @@ -15,17 +15,11 @@ Authors@R: c( person("EURAMET", role = "fnd", comment = "European Association of National Metrology Institutes. Website: www.euramet.org. Grant Number: 22NRM05 MeLiDos. Grant Statement: The project (22NRM05 MeLiDos) has received funding from the European Partnership on Metrology, co-financed from the European Union’s Horizon Europe Research and Innovation Programme and by the Participating States."), person("European Union", role = "fnd", comment = "Co-funded by the European Union. Views and opinions expressed are however those of the author(s) only and do not necessarily reflect those of the European Union or EURAMET. Neither the European Union nor the granting authority can be held responsible for them."), person("TSCN-Lab", comment = c(URL = "www.tscnlab.org"), role = "cph")) -Description: LightLogR is a package under development as part of the MeLiDos - project aimed at developing a standard workflow for wearable light logger - data and optical radiation dosimeters. MeLiDos is a joint, EURAMET-funded - project involving sixteen partners across Europe. Its primary contributions - towards fostering FAIR data include the development of a common file format, - robust metadata descriptors, and an accompanying open-source software - ecosystem. +Description: Import, processing, validation, and visualization of personal light exposure measurement data from wearable devices. The package implements features such as the import of data and metadata files, conversion of common file formats, validation of light logging data, verification of crucial metadata, calculation of common parameters, and semi-automated analysis and visualization. License: GPL (>= 3) Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.1 +RoxygenNote: 7.3.2 URL: https://github.com/tscnlab/LightLogR, https://tscnlab.github.io/LightLogR/, https://zenodo.org/doi/10.5281/zenodo.11562600 @@ -67,4 +61,3 @@ Suggests: testthat (>= 3.0.0), tidyverse Config/testthat/edition: 3 -VignetteBuilder: knitr diff --git a/NEWS.md b/NEWS.md index 89d8165..1bebb9d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# LightLogR 0.3.8 + +* Submission to CRAN + # LightLogR 0.3.7 "Astronomical dawn" * Changes to the tutorial articles on the website diff --git a/R/import_LL.R b/R/import_LL.R index a0b0d21..cd7eff6 100644 --- a/R/import_LL.R +++ b/R/import_LL.R @@ -66,28 +66,56 @@ #' ``` #' #' ## ActLumus +#' Manufacturer: Condor Instruments +#' Model: ActLumus +#' Implemented: 2023 #' A sample file is provided with the package, it can be accessed through #' `system.file("extdata/205_actlumus_Log_1020_20230904101707532.txt.zip", #' package = "LightLogR")`. It does not need to be unzipped to be imported. #' This sample file is a good example for a regular dataset without gaps -#' ## LYS +#' ## LYS +#' Manufacturer: LYS Technologies +#' Model: LYS Button +#' Implemented: 2023 #' A sample file is provided with the package, it can be accessed #' through `system.file("extdata/sample_data_LYS.csv", package = #' "LightLogR")`. This sample file is a good example for an irregular dataset. #' ## Actiwatch_Spectrum +#' Manufacturer: Philips Respironics +#' Model: Actiwatch Spectrum +#' Implemented: 2023 #' **Required Argument: `column_names`** A character vector containing column #' names in the order in which they appear in the file. This is necessary to #' find the starting point of actual data. #' ## ActTrust +#' Manufacturer: Condor Instruments +#' Model: ActTrust1, ActTrust2 +#' Implemented: 2024 #' This function works for both ActTrust 1 and 2 devices #' ## Speccy -#' . +#' Manufacturer: Monash University +#' Model: Speccy +#' Implemented: 2024 #' ## DeLux -#' . +#' Manufacturer: Intelligent Automation Inc +#' Model: DeLux +#' Implemented: 2023 #' ## LiDo -#' . +#' Manufacturer: University of Lucerne +#' Model: LiDo +#' Implemented: 2023 #' ## SpectraWear -#' . +#' Manufacturer: +#' Model: SpectraWear +#' Implemented: 2024 +#' ## NanoLambda +#' Manufacturer: NanoLambda +#' Model: XL-500 BLE +#' Implemented: 2024 +#' ## LightWatcher +#' Manufacturer: Object-Tracker +#' Model: LightWatcher +#' Implemented: 2024 #' #' @section Examples: #' diff --git a/R/metric_EMA.R b/R/metric_EMA.R index 5889c47..ea1935f 100644 --- a/R/metric_EMA.R +++ b/R/metric_EMA.R @@ -30,11 +30,11 @@ #' @references #' Price, L. L. A. (2014). On the Role of Exponential Smoothing in Circadian #' Dosimetry. \emph{Photochemistry and Photobiology}, 90(5), 1184-1192. -#' \url{https://doi.org/10.1111/php.12282} +#' \doi{10.1111/php.12282} #' #' Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: #' Quantification metrics. \emph{Lighting Research & Technology}. -#' \url{https://doi.org/10.1177/14771535231170500} +#' \doi{10.1177/14771535231170500} #' #' @examples #' sample.data.environment.EMA = sample.data.environment %>% diff --git a/R/metric_barroso.R b/R/metric_barroso.R index 12e7743..e625a1b 100644 --- a/R/metric_barroso.R +++ b/R/metric_barroso.R @@ -48,11 +48,11 @@ #' @references #' Barroso, A., Simons, K., & Jager, P. de. (2014). Metrics of circadian #' lighting for clinical investigations. \emph{Lighting Research & Technology}, -#' 46(6), 637–649. \url{https://doi.org/10.1177/1477153513502664} +#' 46(6), 637–649. \doi{10.1177/1477153513502664} #' #' Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: #' Quantification metrics. \emph{Lighting Research & Technology}. -#' \url{https://doi.org/10.1177/14771535231170500} +#' \doi{10.1177/14771535231170500} #' #' @examples #' diff --git a/R/metric_bright_dark_period.R b/R/metric_bright_dark_period.R index ffb481d..2544924 100755 --- a/R/metric_bright_dark_period.R +++ b/R/metric_bright_dark_period.R @@ -38,7 +38,7 @@ #' @references #' Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: #' Quantification metrics. \emph{Lighting Research & Technology}. -#' \url{https://doi.org/10.1177/14771535231170500} +#' \doi{10.1177/14771535231170500} #' #' @export #' diff --git a/R/metric_centroidLE.R b/R/metric_centroidLE.R index 3212e39..523f443 100755 --- a/R/metric_centroidLE.R +++ b/R/metric_centroidLE.R @@ -25,11 +25,11 @@ #' L. K., Picard, R. W., Lockley, S. W., Klerman, E. B., & Czeisler, C. A. (2017). #' Irregular sleep/wake patterns are associated with poorer academic performance #' and delayed circadian and sleep/wake timing. \emph{Scientific Reports}, -#' 7(1), 3216. \url{https://doi.org/10.1038/s41598-017-03171-4} +#' 7(1), 3216. \doi{10.1038/s41598-017-03171-4} #' #' Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: #' Quantification metrics. \emph{Lighting Research & Technology}. -#' \url{https://doi.org/10.1177/14771535231170500} +#' \doi{10.1177/14771535231170500} #' #' @examples #' # Dataset with POSIXct time vector diff --git a/R/metric_disparity_index.R b/R/metric_disparity_index.R index 79d06f3..9b5e60d 100644 --- a/R/metric_disparity_index.R +++ b/R/metric_disparity_index.R @@ -20,11 +20,11 @@ #' Martín-Vide, J., & Peñuelas, J. (2018). #' The consecutive disparity index, D: A measure of temporal variability in #' ecological studies. \emph{Ecosphere}, 9(12), e02527. -#' \url{https://doi.org/10.1002/ecs2.2527} +#' \doi{10.1002/ecs2.2527} #' #' Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: #' Quantification metrics. \emph{Lighting Research & Technology}. -#' \url{https://doi.org/10.1177/14771535231170500} +#' \doi{10.1177/14771535231170500} #' #' @examples #' dataset1 <- diff --git a/R/metric_duration_above_threshold.R b/R/metric_duration_above_threshold.R index 63fba2f..64b1bf6 100755 --- a/R/metric_duration_above_threshold.R +++ b/R/metric_duration_above_threshold.R @@ -27,7 +27,7 @@ #' @references #' Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: #' Quantification metrics. \emph{Lighting Research & Technology}. -#' \url{https://doi.org/10.1177/14771535231170500} +#' \doi{10.1177/14771535231170500} #' #' @export #' diff --git a/R/metric_frequency_crossing_threshold.R b/R/metric_frequency_crossing_threshold.R index 14f1d03..a2879e1 100644 --- a/R/metric_frequency_crossing_threshold.R +++ b/R/metric_frequency_crossing_threshold.R @@ -19,11 +19,11 @@ #' @references #' Alvarez, A. A., & Wildsoet, C. F. (2013). Quantifying light #' exposure patterns in young adult students. \emph{Journal of Modern Optics}, -#' 60(14), 1200–1208. \url{https://doi.org/10.1080/09500340.2013.845700} +#' 60(14), 1200–1208. \doi{10.1080/09500340.2013.845700} #' #' Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: #' Quantification metrics. \emph{Lighting Research & Technology}. -#' \url{https://doi.org/10.1177/14771535231170500} +#' \doi{10.1177/14771535231170500} #' #' @examples # diff --git a/R/metric_interdaily_stability.R b/R/metric_interdaily_stability.R index 8076256..38a18fa 100755 --- a/R/metric_interdaily_stability.R +++ b/R/metric_interdaily_stability.R @@ -24,11 +24,11 @@ #' McCall, W. V., & Rosenquist, P. B. (1999). Bright Light Therapy: Improved #' Sensitivity to Its Effects on Rest-Activity Rhythms in Alzheimer Patients #' by Application of Nonparametric Methods. \emph{Chronobiology International}, -#' 16(4), 505–518. \url{https://doi.org/10.3109/07420529908998724} +#' 16(4), 505–518. \doi{10.3109/07420529908998724} #' #' Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: #' Quantification metrics. \emph{Lighting Research & Technology}. -#' \url{https://doi.org/10.1177/14771535231170500} +#' \doi{10.1177/14771535231170500} #' #' @examples #' diff --git a/R/metric_intradaily_variability.R b/R/metric_intradaily_variability.R index 7aab154..5b8d9b3 100755 --- a/R/metric_intradaily_variability.R +++ b/R/metric_intradaily_variability.R @@ -22,11 +22,11 @@ #' McCall, W. V., & Rosenquist, P. B. (1999). Bright Light Therapy: Improved #' Sensitivity to Its Effects on Rest-Activity Rhythms in Alzheimer Patients #' by Application of Nonparametric Methods. \emph{Chronobiology International}, -#' 16(4), 505–518. \url{https://doi.org/10.3109/07420529908998724} +#' 16(4), 505–518. \doi{10.3109/07420529908998724} #' #' Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: #' Quantification metrics. \emph{Lighting Research & Technology}. -#' \url{https://doi.org/10.1177/14771535231170500} +#' \doi{10.1177/14771535231170500} #' #' @examples #' diff --git a/R/metric_midpointCE.R b/R/metric_midpointCE.R index 03a1904..5037ce1 100644 --- a/R/metric_midpointCE.R +++ b/R/metric_midpointCE.R @@ -22,11 +22,11 @@ #' Shochat, T., Santhi, N., Herer, P., Flavell, S. A., Skeldon, A. C., #' & Dijk, D.-J. (2019). Sleep Timing in Late Autumn and Late Spring Associates #' With Light Exposure Rather Than Sun Time in College Students. -#' \emph{Frontiers in Neuroscience}, 13. \url{https://doi.org/10.3389/fnins.2019.00882} +#' \emph{Frontiers in Neuroscience}, 13. \doi{10.3389/fnins.2019.00882} #' #' Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: #' Quantification metrics. \emph{Lighting Research & Technology}. -#' \url{https://doi.org/10.1177/14771535231170500} +#' \doi{10.1177/14771535231170500} #' #' @examples # Dataset with POSIXct time vector diff --git a/R/metric_nvR.R b/R/metric_nvR.R index 0796fb8..94da0e6 100644 --- a/R/metric_nvR.R +++ b/R/metric_nvR.R @@ -10,12 +10,12 @@ #' #' @param MEDI.vector Numeric vector containing the melanopic EDI data. #' @param Illuminance.vector Numeric vector containing the Illuminance data. -#' @param Time.vector Vector containing the time data. Can be \link[base]{POSIXct}, \link[hms]{hms}, -#' \link[lubridate]{duration}, or \link[base]{difftime}. +#' @param Time.vector Vector containing the time data. Can be [POSIXct()],[hms::hms()], +#' [lubridate::duration()], [difftime()]. #' @param epoch The epoch at which the data was sampled. Can be either a -#' \link[lubridate]{duration} or a string. If it is a string, it needs to be +#' [lubridate::duration()] or a string. If it is a string, it needs to be #' either `"dominant.epoch"` (the default) for a guess based on the data, or a valid -#' \link[lubridate]{duration} string, e.g., `"1 day"` or `"10 sec"`. +#' [lubridate::duration()] string, e.g., `"1 day"` or `"10 sec"`. #' #' @return A numeric vector containing the nvRD data. The output has the same #' length as `Time.vector`. @@ -25,62 +25,11 @@ #' #' @details The timeseries is assumed to be regular. Missing values in the #' light data will be replaced by 0. -#' -#' The inputs to the model are discrete time samples of melanopic equivalent -#' daylight (D65) illuminance (mEDI) \eqn{E_{v,mel}^{D65}(t)}, transformed into -#' the effective light stimulus \eqn{I(t)}. -#' -#' \deqn{I(t) = E_{v,mel}^{D65} * K_{mel,v}^{D65}/A_{mel},} -#' -#' where \eqn{K_{mel,v}^{D65} = 1.3262 / 1000} is the melanopic normalization factor -#' to convert melanopic EDI to melanopic Irradiance and \eqn{A_{mel} = 97.07} is the -#' area of the melanopic sensitivity curve. -#' -#' The light stimulus \eqn{I(t)} is then passed through a linear filter \eqn{L1}, -#' which is associated with the temporal integration of the retina, to determine the -#' output \eqn{u(t)}. -#' -#' \deqn{u(t) = \frac{1}{d_{1}}\sum_{i=0}^{d_{1}/\Delta t} I(t-1)\Delta t,} -#' -#' where \eqn{d_{1}} is the length of filter \eqn{L1}. The time step size -#' \eqn{\Delta t} is the epoch at which the data was sampled. -#' Then \eqn{u(t)} is transformed by a nonlinear function \eqn{N(u)}, describing the -#' intensity-response relationship to the light stimulus, to determine the -#' output \eqn{v(t)}. -#' -#' \deqn{v(t) = N(u(t)) = \frac{1}{1+(\sigma(t)/u(t))^n}.} -#' -#' The half-maximum constant \eqn{\sigma} adapts to prior light history -#' \deqn{ -#' \begin{array}{ll} -#' \sigma(t)=\sigma_{0}/2, & \qquad & \forall u_{H}(t)<0,\\ -#' \sigma(t)=\sigma_{0}\times2^{u_{H}(t)-1}, & \qquad & \forall u_{H}(t)\geq 0. -#' \end{array} -#' } -#' -#' The prior history of light exposure is calculated using a moving window, -#' filter \eqn{LH}, to average the input -#' -#' \deqn{u_{H}(t) = \frac{1}{d_{H}}\sum_{i=0}^{d_{H}/\Delta t} -#' \log_{10}(E_{v}(t-i))\Delta t,} -#' -#' where \eqn{dH} is the width of the filter \eqn{LH} in hours and \eqn{E_{v}} -#' is the photopic illuminance. -#' -#' The signal \eqn{v(t)} is finally passed through a second filter \eqn{L2}, -#' which reflects the adaptation of the non-visual system to continuous light -#' exposure, to determine the final output \eqn{r_{D}(t)}. -#' -#' \deqn{r_{D}(t)=\alpha \times v(t−1)+(1−\alpha) \times r_{D}(t−1),} -#' -#' where \eqn{\alpha=2/(d2/\Delta t+1)} and \eqn{d2} is the length of filter -#' \eqn{L2} in hours. The model outputs are time-sampled relative non-visual -#' responses. #' #' @references Amundadottir, M.L. (2016). Light-driven model for identifying #' indicators of non-visual health potential in the built environment #' \[Doctoral dissertation, EPFL\]. EPFL infoscience. -#' \url{http://dx.doi.org/10.5075/epfl-thesis-7146} +#' \doi{10.5075/epfl-thesis-7146} #' #' @examples #' @@ -201,7 +150,7 @@ nvRD <- function(MEDI.vector, #' @references Amundadottir, M.L. (2016). Light-driven model for identifying #' indicators of non-visual health potential in the built environment #' \[Doctoral dissertation, EPFL\]. EPFL infoscience. -#' \url{http://dx.doi.org/10.5075/epfl-thesis-7146} +#' \doi{10.5075/epfl-thesis-7146} #' #' @examples #' dataset1 <- @@ -288,78 +237,11 @@ nvRD_cumulative_response <- function(nvRD, #' @details The timeseries is assumed to be regular. Missing values in the #' light data will be replaced by 0. #' -#' The inputs to the model are discrete time samples of melanopic equivalent -#' daylight (D65) illuminance (mEDI) \eqn{E_{v,mel}^{D65}(t)}, transformed into -#' the effective light stimulus \eqn{I(t)}. -#' -#' \deqn{I(t) = E_{v,mel}^{D65} * K_{mel,v}^{D65}/A_{mel},} -#' -#' where \eqn{K_{mel,v}^{D65} = 1.3262 / 1000} is the melanopic normalization factor -#' to convert melanopic EDI to melanopic Irradiance and \eqn{A_{mel} = 97.07} is the -#' area of the melanopic sensitivity curve. -#' -#' The light stimulus \eqn{I(t)} is then passed through a linear filter \eqn{L1}, -#' which is associated with the temporal integration of the retina, to determine the -#' output \eqn{u(t)}. -#' -#' \deqn{u(t) = \frac{1}{d_{1}} \sum_{i=0}^{d_{1}/\Delta t} I(t-1)\Delta t,} -#' -#' where \eqn{d_{1}} is the length of filter \eqn{L1}. The time step size -#' \eqn{\Delta t} is the epoch at which the data was sampled. -#' Then \eqn{u(t)} is transformed by a nonlinear function \eqn{N(u)}, describing the -#' intensity-response relationship to the light stimulus, to determine the -#' output \eqn{v(t)}. -#' -#' \deqn{v(t) = N(u(t)) \times N_{C}(t) = \frac{N_{C}(t)}{1+(\sigma(t)/u(t))^n}.} -#' -#' The saturation intensity is controlled by the circadian sensitivity modulator -#' -#' \deqn{N_{C}(t)=(1−0.4C_{1}(t))(1−0.4C_{2}(t)),} -#' -#' acting as a simple harmonic oscillator -#' -#' \deqn{ -#' \begin{array}{l} -#' C_{1} = \cos(\pi(t/12+1)+\phi_{xcx}/2),\\ -#' C_{2} = -\sin(\pi(t/12+1)+\phi_{xcx}/2), -#' \end{array} -#' } -#' -#' where the phase angle to CBT min \eqn{\phi_{xcx}} is equal to \eqn{-2.98} rad, -#' assuming that sleep onset is at \eqn{t_{0}}. -#' -#' The half-maximum constant \eqn{\sigma} adapts to prior light history -#' -#' \deqn{ -#' \begin{array}{ll} -#' \sigma(t)=\sigma_{0}/2, & \qquad & \forall u_{H}(t)<0,\\ -#' \sigma(t)=\sigma_{0}\times2^{u_{H}(t)-1}, & \qquad & \forall u_{H}(t)\geq 0. -#' \end{array} -#' } -#' -#' The prior history of light exposure is calculated using a moving window, -#' filter \eqn{LH}, to average the input -#' -#' \deqn{u_{H}(t) = \frac{1}{d_{H}}\sum_{i=0}^{d_{H}/\Delta t} -#' \log_{10}(E_{v}(t-i))\Delta t,} -#' -#' where \eqn{dH} is the width of the filter \eqn{LH} in hours and \eqn{E_{v}} -#' is the photopic illuminance. -#' -#' The signal \eqn{v(t)} is finally passed through a second filter \eqn{L2}, -#' which reflects the adaptation of the non-visual system to continuous light -#' exposure, to determine the final output \eqn{r_{C}(t)}. -#' -#' \deqn{r_{C}(t)=\alpha \times v(t−1)+(1−\alpha) \times r_{C}(t−1),} -#' -#' where \eqn{\alpha=2/(d2/\Delta t+1)} and \eqn{d2} is the length of filter -#' \eqn{L2} in hours. The model outputs are time-sampled relative non-visual -#' responses. #' #' @references Amundadottir, M.L. (2016). Light-driven model for identifying #' indicators of non-visual health potential in the built environment #' \[Doctoral dissertation, EPFL\]. EPFL infoscience. -#' \url{http://dx.doi.org/10.5075/epfl-thesis-7146} +#' \doi{10.5075/epfl-thesis-7146} #' #' @examples #' @@ -504,7 +386,7 @@ nvRC <- function(MEDI.vector, #' @references Amundadottir, M.L. (2016). Light-driven model for identifying #' indicators of non-visual health potential in the built environment #' \[Doctoral dissertation, EPFL\]. EPFL infoscience. -#' \url{http://dx.doi.org/10.5075/epfl-thesis-7146} +#' \doi{10.5075/epfl-thesis-7146} #' #' @name nvRC_metrics #' @examples @@ -540,7 +422,7 @@ nvRC <- function(MEDI.vector, #' # Relative amplitude error #' nvRC_relativeAmplitudeError(dataset1$nvRC, dataset.reference$nvRC) -NULL + #' @rdname nvRC_metrics #' @@ -623,7 +505,7 @@ nvRC_circadianBias <- function(nvRC, #' `nvRC_relativeAmplitudeError()` calculates the relative amplitude error (RAE). #' It is expressed as #' -#' \deqn{RAE(i,T)=r_{C,max}−r_{C,max}^{ref},} +#' \deqn{RAE(i,T)=r_{C,max}-r_{C,max}^{ref},} #' #' and quantifies the difference between the maximum response achieved in a period #' to the reference signal. diff --git a/R/metric_pulses_above_threshold.R b/R/metric_pulses_above_threshold.R index 6cb8dca..b2142d5 100644 --- a/R/metric_pulses_above_threshold.R +++ b/R/metric_pulses_above_threshold.R @@ -54,7 +54,7 @@ #' @references Wilson, J., Reid, K. J., Braun, R. I., Abbott, S. M., & Zee, P. C. #' (2018). Habitual light exposure relative to circadian timing in delayed #' sleep-wake phase disorder. \emph{Sleep}, 41(11). -#' \url{https://doi.org/10.1093/sleep/zsy166} +#' \doi{10.1093/sleep/zsy166} #' #' @examples #' # Sample data diff --git a/R/metric_timing_above_threshold.R b/R/metric_timing_above_threshold.R index 9d1b72e..b309b7e 100755 --- a/R/metric_timing_above_threshold.R +++ b/R/metric_timing_above_threshold.R @@ -33,11 +33,11 @@ #' Reid, K. J., Santostasi, G., Baron, K. G., Wilson, J., Kang, J., #' & Zee, P. C. (2014). Timing and Intensity of Light Correlate with Body Weight #' in Adults. \emph{PLOS ONE}, 9(4), e92251. -#' \url{https://doi.org/10.1371/journal.pone.0092251} +#' \doi{10.1371/journal.pone.0092251} #' #' Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: #' Quantification metrics. \emph{Lighting Research & Technology}. -#' \url{https://doi.org/10.1177/14771535231170500} +#' \doi{10.1177/14771535231170500} #' #' @examples #' # Dataset with light > 250lx between 06:00 and 18:00 diff --git a/R/symlog_trans.R b/R/symlog_trans.R index 507de77..7b2439e 100644 --- a/R/symlog_trans.R +++ b/R/symlog_trans.R @@ -11,8 +11,8 @@ #' @return a transformation function that can be used in [ggplot] or [plotly] to scale positive and negative values on a log scale. #' @export #' -#' @references This function`s code is a straight copy from a post on stack overflow. -#' https://stackoverflow.com/a/14674703 +#' @references This function`s code is a straight copy from a post on [stack overflow](https://stackoverflow.com/a/14674703). +#' The author of the answer is [Julius Vainora](https://stackoverflow.com/users/1320535/julius-vainora), and the author of the question [Brian B](https://stackoverflow.com/users/1212562/brian-b) #' #' @examples #' dataset <- diff --git a/README.Rmd b/README.Rmd index 235ea4c..04095ab 100644 --- a/README.Rmd +++ b/README.Rmd @@ -60,7 +60,13 @@ The project (22NRM05 MeLiDos) has received funding from the European Partnership ## Installation -You can install the development version of LightLogR from [GitHub](https://github.com/) with: +You can install LightLogR from [CRAN](https://CRAN.R-project.org) with: + +``` r +install.packages("LightLogR") +``` + +You can install the latest development version of LightLogR from [GitHub](https://github.com/) with: ``` r # install.packages("devtools") @@ -73,7 +79,7 @@ Here is a quick starter on how do use **LightLogR**. ```{r, message = FALSE} library(LightLogR) -#these packages are just needed for the examples as shown. +#these packages are needed for the examples as shown below. library(flextable) library(dplyr) library(ggplot2) diff --git a/README.md b/README.md index e2bf46a..63fe729 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,13 @@ held responsible for them. ## Installation -You can install the development version of LightLogR from +You can install LightLogR from [CRAN](https://CRAN.R-project.org) with: + +``` r +install.packages("LightLogR") +``` + +You can install the latest development version of LightLogR from [GitHub](https://github.com/) with: ``` r @@ -108,7 +114,7 @@ Here is a quick starter on how do use **LightLogR**. ``` r library(LightLogR) -#these packages are just needed for the examples as shown. +#these packages are needed for the examples as shown below. library(flextable) library(dplyr) library(ggplot2) diff --git a/cran-comments.md b/cran-comments.md new file mode 100644 index 0000000..0510326 --- /dev/null +++ b/cran-comments.md @@ -0,0 +1,19 @@ +## R CMD check results + +0 errors | 0 warnings | 1 note + +* This is a new release. + +## Windevel results + +Maintainer: 'Johannes Zauner ' + +* New submission + +* Found the following (possibly) invalid URLs: + URL: https://lists.lrz.de/mailman/listinfo/lightlogr-users + From: README.md + Status: 403 + Message: Forbidden + +This URL is valid, but the server does not allow the Windevel server to access it. The URL leads to the mailing list for the package. \ No newline at end of file diff --git a/man/LightLogR-package.Rd b/man/LightLogR-package.Rd index 9b6836d..c897403 100644 --- a/man/LightLogR-package.Rd +++ b/man/LightLogR-package.Rd @@ -4,11 +4,11 @@ \name{LightLogR-package} \alias{LightLogR} \alias{LightLogR-package} -\title{LightLogR: Work With Data from Wearable Light Loggers and Optical Radiation Dosimeters} +\title{LightLogR: Process Data from Wearable Light Loggers and Optical Radiation Dosimeters} \description{ \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} -LightLogR is a package under development as part of the MeLiDos project aimed at developing a standard workflow for wearable light logger data and optical radiation dosimeters. MeLiDos is a joint, EURAMET-funded project involving sixteen partners across Europe. Its primary contributions towards fostering FAIR data include the development of a common file format, robust metadata descriptors, and an accompanying open-source software ecosystem. +Import, processing, validation, and visualization of personal light exposure measurement data from wearable devices. The package implements features such as the import of data and metadata files, conversion of common file formats, validation of light logging data, verification of crucial metadata, calculation of common parameters, and semi-automated analysis and visualization. } \seealso{ Useful links: diff --git a/man/barroso_lighting_metrics.Rd b/man/barroso_lighting_metrics.Rd index e5beb58..4fb9009 100644 --- a/man/barroso_lighting_metrics.Rd +++ b/man/barroso_lighting_metrics.Rd @@ -80,9 +80,9 @@ dataset1 \%>\% \references{ Barroso, A., Simons, K., & Jager, P. de. (2014). Metrics of circadian lighting for clinical investigations. \emph{Lighting Research & Technology}, -46(6), 637–649. \url{https://doi.org/10.1177/1477153513502664} +46(6), 637–649. \doi{10.1177/1477153513502664} Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: Quantification metrics. \emph{Lighting Research & Technology}. -\url{https://doi.org/10.1177/14771535231170500} +\doi{10.1177/14771535231170500} } diff --git a/man/bright_dark_period.Rd b/man/bright_dark_period.Rd old mode 100755 new mode 100644 index 17808cf..b90df5f --- a/man/bright_dark_period.Rd +++ b/man/bright_dark_period.Rd @@ -96,7 +96,7 @@ dataset2 \%>\% \references{ Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: Quantification metrics. \emph{Lighting Research & Technology}. -\url{https://doi.org/10.1177/14771535231170500} +\doi{10.1177/14771535231170500} } \seealso{ Other metrics: diff --git a/man/centroidLE.Rd b/man/centroidLE.Rd index d4e15e2..e93ba71 100644 --- a/man/centroidLE.Rd +++ b/man/centroidLE.Rd @@ -79,11 +79,11 @@ Phillips, A. J. K., Clerx, W. M., O’Brien, C. S., Sano, A., Barger, L. K., Picard, R. W., Lockley, S. W., Klerman, E. B., & Czeisler, C. A. (2017). Irregular sleep/wake patterns are associated with poorer academic performance and delayed circadian and sleep/wake timing. \emph{Scientific Reports}, -7(1), 3216. \url{https://doi.org/10.1038/s41598-017-03171-4} +7(1), 3216. \doi{10.1038/s41598-017-03171-4} Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: Quantification metrics. \emph{Lighting Research & Technology}. -\url{https://doi.org/10.1177/14771535231170500} +\doi{10.1177/14771535231170500} } \seealso{ Other metrics: diff --git a/man/disparity_index.Rd b/man/disparity_index.Rd index 70297e5..40d1e88 100644 --- a/man/disparity_index.Rd +++ b/man/disparity_index.Rd @@ -40,11 +40,11 @@ Fernández-Martínez, M., Vicca, S., Janssens, I. A., Carnicer, J., Martín-Vide, J., & Peñuelas, J. (2018). The consecutive disparity index, D: A measure of temporal variability in ecological studies. \emph{Ecosphere}, 9(12), e02527. -\url{https://doi.org/10.1002/ecs2.2527} +\doi{10.1002/ecs2.2527} Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: Quantification metrics. \emph{Lighting Research & Technology}. -\url{https://doi.org/10.1177/14771535231170500} +\doi{10.1177/14771535231170500} } \seealso{ Other metrics: diff --git a/man/duration_above_threshold.Rd b/man/duration_above_threshold.Rd index 66a9315..b22a1b9 100644 --- a/man/duration_above_threshold.Rd +++ b/man/duration_above_threshold.Rd @@ -80,7 +80,7 @@ dataset.combined \%>\% \references{ Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: Quantification metrics. \emph{Lighting Research & Technology}. -\url{https://doi.org/10.1177/14771535231170500} +\doi{10.1177/14771535231170500} } \seealso{ Other metrics: diff --git a/man/exponential_moving_average.Rd b/man/exponential_moving_average.Rd index f15e305..9ca8b97 100644 --- a/man/exponential_moving_average.Rd +++ b/man/exponential_moving_average.Rd @@ -57,11 +57,11 @@ sample.data.environment.EMA \%>\% \references{ Price, L. L. A. (2014). On the Role of Exponential Smoothing in Circadian Dosimetry. \emph{Photochemistry and Photobiology}, 90(5), 1184-1192. -\url{https://doi.org/10.1111/php.12282} +\doi{10.1111/php.12282} Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: Quantification metrics. \emph{Lighting Research & Technology}. -\url{https://doi.org/10.1177/14771535231170500} +\doi{10.1177/14771535231170500} } \seealso{ Other metrics: diff --git a/man/frequency_crossing_threshold.Rd b/man/frequency_crossing_threshold.Rd index 44c927f..cf0559f 100644 --- a/man/frequency_crossing_threshold.Rd +++ b/man/frequency_crossing_threshold.Rd @@ -48,11 +48,11 @@ dataset1 \%>\% \references{ Alvarez, A. A., & Wildsoet, C. F. (2013). Quantifying light exposure patterns in young adult students. \emph{Journal of Modern Optics}, -60(14), 1200–1208. \url{https://doi.org/10.1080/09500340.2013.845700} +60(14), 1200–1208. \doi{10.1080/09500340.2013.845700} Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: Quantification metrics. \emph{Lighting Research & Technology}. -\url{https://doi.org/10.1177/14771535231170500} +\doi{10.1177/14771535231170500} } \seealso{ Other metrics: diff --git a/man/import_Dataset.Rd b/man/import_Dataset.Rd index f3d4c5e..741ce1e 100644 --- a/man/import_Dataset.Rd +++ b/man/import_Dataset.Rd @@ -84,6 +84,9 @@ is maintained. }\if{html}{\out{}} \subsection{ActLumus}{ +Manufacturer: Condor Instruments +Model: ActLumus +Implemented: 2023 A sample file is provided with the package, it can be accessed through \code{system.file("extdata/205_actlumus_Log_1020_20230904101707532.txt.zip", package = "LightLogR")}. It does not need to be unzipped to be imported. This sample file is a good example for a regular dataset without gaps @@ -91,12 +94,18 @@ This sample file is a good example for a regular dataset without gaps \subsection{LYS}{ +Manufacturer: LYS Technologies +Model: LYS Button +Implemented: 2023 A sample file is provided with the package, it can be accessed through \code{system.file("extdata/sample_data_LYS.csv", package = "LightLogR")}. This sample file is a good example for an irregular dataset. } \subsection{Actiwatch_Spectrum}{ +Manufacturer: Philips Respironics +Model: Actiwatch Spectrum +Implemented: 2023 \strong{Required Argument: \code{column_names}} A character vector containing column names in the order in which they appear in the file. This is necessary to find the starting point of actual data. @@ -104,27 +113,52 @@ find the starting point of actual data. \subsection{ActTrust}{ +Manufacturer: Condor Instruments +Model: ActTrust1, ActTrust2 +Implemented: 2024 This function works for both ActTrust 1 and 2 devices } \subsection{Speccy}{ -. +Manufacturer: Monash University +Model: Speccy +Implemented: 2024 } \subsection{DeLux}{ -. +Manufacturer: Intelligent Automation Inc +Model: DeLux +Implemented: 2023 } \subsection{LiDo}{ -. +Manufacturer: University of Lucerne +Model: LiDo +Implemented: 2023 } \subsection{SpectraWear}{ -. +Manufacturer: +Model: SpectraWear +Implemented: 2024 +} + +\subsection{NanoLambda}{ + +Manufacturer: NanoLambda +Model: XL-500 BLE +Implemented: 2024 +} + +\subsection{LightWatcher}{ + +Manufacturer: Object-Tracker +Model: LightWatcher +Implemented: 2024 } } diff --git a/man/interdaily_stability.Rd b/man/interdaily_stability.Rd old mode 100755 new mode 100644 index 8c50fd3..a75d623 --- a/man/interdaily_stability.Rd +++ b/man/interdaily_stability.Rd @@ -56,11 +56,11 @@ Van Someren, E. J. W., Swaab, D. F., Colenda, C. C., Cohen, W., McCall, W. V., & Rosenquist, P. B. (1999). Bright Light Therapy: Improved Sensitivity to Its Effects on Rest-Activity Rhythms in Alzheimer Patients by Application of Nonparametric Methods. \emph{Chronobiology International}, -16(4), 505–518. \url{https://doi.org/10.3109/07420529908998724} +16(4), 505–518. \doi{10.3109/07420529908998724} Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: Quantification metrics. \emph{Lighting Research & Technology}. -\url{https://doi.org/10.1177/14771535231170500} +\doi{10.1177/14771535231170500} } \seealso{ Other metrics: diff --git a/man/intradaily_variability.Rd b/man/intradaily_variability.Rd old mode 100755 new mode 100644 index 87dbb43..0dca74a --- a/man/intradaily_variability.Rd +++ b/man/intradaily_variability.Rd @@ -53,11 +53,11 @@ Van Someren, E. J. W., Swaab, D. F., Colenda, C. C., Cohen, W., McCall, W. V., & Rosenquist, P. B. (1999). Bright Light Therapy: Improved Sensitivity to Its Effects on Rest-Activity Rhythms in Alzheimer Patients by Application of Nonparametric Methods. \emph{Chronobiology International}, -16(4), 505–518. \url{https://doi.org/10.3109/07420529908998724} +16(4), 505–518. \doi{10.3109/07420529908998724} Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: Quantification metrics. \emph{Lighting Research & Technology}. -\url{https://doi.org/10.1177/14771535231170500} +\doi{10.1177/14771535231170500} } \seealso{ Other metrics: diff --git a/man/midpointCE.Rd b/man/midpointCE.Rd index 7344af1..abd236c 100644 --- a/man/midpointCE.Rd +++ b/man/midpointCE.Rd @@ -67,11 +67,11 @@ dataset3 \%>\% Shochat, T., Santhi, N., Herer, P., Flavell, S. A., Skeldon, A. C., & Dijk, D.-J. (2019). Sleep Timing in Late Autumn and Late Spring Associates With Light Exposure Rather Than Sun Time in College Students. -\emph{Frontiers in Neuroscience}, 13. \url{https://doi.org/10.3389/fnins.2019.00882} +\emph{Frontiers in Neuroscience}, 13. \doi{10.3389/fnins.2019.00882} Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: Quantification metrics. \emph{Lighting Research & Technology}. -\url{https://doi.org/10.1177/14771535231170500} +\doi{10.1177/14771535231170500} } \seealso{ Other metrics: diff --git a/man/nvRC.Rd b/man/nvRC.Rd index d1db526..97ed48a 100644 --- a/man/nvRC.Rd +++ b/man/nvRC.Rd @@ -43,74 +43,6 @@ input to the non-visual system (see Details). \details{ The timeseries is assumed to be regular. Missing values in the light data will be replaced by 0. - -The inputs to the model are discrete time samples of melanopic equivalent -daylight (D65) illuminance (mEDI) \eqn{E_{v,mel}^{D65}(t)}, transformed into -the effective light stimulus \eqn{I(t)}. - -\deqn{I(t) = E_{v,mel}^{D65} * K_{mel,v}^{D65}/A_{mel},} - -where \eqn{K_{mel,v}^{D65} = 1.3262 / 1000} is the melanopic normalization factor -to convert melanopic EDI to melanopic Irradiance and \eqn{A_{mel} = 97.07} is the -area of the melanopic sensitivity curve. - -The light stimulus \eqn{I(t)} is then passed through a linear filter \eqn{L1}, -which is associated with the temporal integration of the retina, to determine the -output \eqn{u(t)}. - -\deqn{u(t) = \frac{1}{d_{1}} \sum_{i=0}^{d_{1}/\Delta t} I(t-1)\Delta t,} - -where \eqn{d_{1}} is the length of filter \eqn{L1}. The time step size -\eqn{\Delta t} is the epoch at which the data was sampled. -Then \eqn{u(t)} is transformed by a nonlinear function \eqn{N(u)}, describing the -intensity-response relationship to the light stimulus, to determine the -output \eqn{v(t)}. - -\deqn{v(t) = N(u(t)) \times N_{C}(t) = \frac{N_{C}(t)}{1+(\sigma(t)/u(t))^n}.} - -The saturation intensity is controlled by the circadian sensitivity modulator - -\deqn{N_{C}(t)=(1−0.4C_{1}(t))(1−0.4C_{2}(t)),} - -acting as a simple harmonic oscillator - -\deqn{ - \begin{array}{l} - C_{1} = \cos(\pi(t/12+1)+\phi_{xcx}/2),\\ - C_{2} = -\sin(\pi(t/12+1)+\phi_{xcx}/2), - \end{array} - } - -where the phase angle to CBT min \eqn{\phi_{xcx}} is equal to \eqn{-2.98} rad, -assuming that sleep onset is at \eqn{t_{0}}. - -The half-maximum constant \eqn{\sigma} adapts to prior light history - -\deqn{ - \begin{array}{ll} - \sigma(t)=\sigma_{0}/2, & \qquad & \forall u_{H}(t)<0,\\ - \sigma(t)=\sigma_{0}\times2^{u_{H}(t)-1}, & \qquad & \forall u_{H}(t)\geq 0. - \end{array} - } - -The prior history of light exposure is calculated using a moving window, -filter \eqn{LH}, to average the input - -\deqn{u_{H}(t) = \frac{1}{d_{H}}\sum_{i=0}^{d_{H}/\Delta t} - \log_{10}(E_{v}(t-i))\Delta t,} - -where \eqn{dH} is the width of the filter \eqn{LH} in hours and \eqn{E_{v}} -is the photopic illuminance. - -The signal \eqn{v(t)} is finally passed through a second filter \eqn{L2}, -which reflects the adaptation of the non-visual system to continuous light -exposure, to determine the final output \eqn{r_{C}(t)}. - -\deqn{r_{C}(t)=\alpha \times v(t−1)+(1−\alpha) \times r_{C}(t−1),} - - where \eqn{\alpha=2/(d2/\Delta t+1)} and \eqn{d2} is the length of filter -\eqn{L2} in hours. The model outputs are time-sampled relative non-visual -responses. } \examples{ @@ -141,7 +73,7 @@ dataset2.nvRC <- dataset2 \%>\% Amundadottir, M.L. (2016). Light-driven model for identifying indicators of non-visual health potential in the built environment [Doctoral dissertation, EPFL]. EPFL infoscience. -\url{http://dx.doi.org/10.5075/epfl-thesis-7146} +\doi{10.5075/epfl-thesis-7146} } \seealso{ Other metrics: diff --git a/man/nvRC_metrics.Rd b/man/nvRC_metrics.Rd index 1198239..8d0d528 100644 --- a/man/nvRC_metrics.Rd +++ b/man/nvRC_metrics.Rd @@ -56,8 +56,8 @@ and the circadian response to a reference profile. \code{nvRC_relativeAmplitudeError()} calculates the relative amplitude error (RAE). It is expressed as -\deqn{RAE(i,T)=r_{C,max}−r_{C,max}^{ref},} - +\deqn{RAE(i,T)=r_{C,max}-r_{C,max}^{ref},} + and quantifies the difference between the maximum response achieved in a period to the reference signal. } @@ -98,5 +98,5 @@ nvRC_relativeAmplitudeError(dataset1$nvRC, dataset.reference$nvRC) Amundadottir, M.L. (2016). Light-driven model for identifying indicators of non-visual health potential in the built environment [Doctoral dissertation, EPFL]. EPFL infoscience. -\url{http://dx.doi.org/10.5075/epfl-thesis-7146} +\doi{10.5075/epfl-thesis-7146} } diff --git a/man/nvRD.Rd b/man/nvRD.Rd index af27031..cb6dc74 100644 --- a/man/nvRD.Rd +++ b/man/nvRD.Rd @@ -11,13 +11,13 @@ nvRD(MEDI.vector, Illuminance.vector, Time.vector, epoch = "dominant.epoch") \item{Illuminance.vector}{Numeric vector containing the Illuminance data.} -\item{Time.vector}{Vector containing the time data. Can be \link[base]{POSIXct}, \link[hms]{hms}, -\link[lubridate]{duration}, or \link[base]{difftime}.} +\item{Time.vector}{Vector containing the time data. Can be \code{\link[=POSIXct]{POSIXct()}},\code{\link[hms:hms]{hms::hms()}}, +\code{\link[lubridate:duration]{lubridate::duration()}}, \code{\link[=difftime]{difftime()}}.} \item{epoch}{The epoch at which the data was sampled. Can be either a -\link[lubridate]{duration} or a string. If it is a string, it needs to be +\code{\link[lubridate:duration]{lubridate::duration()}} or a string. If it is a string, it needs to be either \code{"dominant.epoch"} (the default) for a guess based on the data, or a valid -\link[lubridate]{duration} string, e.g., \code{"1 day"} or \code{"10 sec"}.} +\code{\link[lubridate:duration]{lubridate::duration()}} string, e.g., \code{"1 day"} or \code{"10 sec"}.} } \value{ A numeric vector containing the nvRD data. The output has the same @@ -32,57 +32,6 @@ exposure signal to quantify the effective direct input to the non-visual system \details{ The timeseries is assumed to be regular. Missing values in the light data will be replaced by 0. - -The inputs to the model are discrete time samples of melanopic equivalent -daylight (D65) illuminance (mEDI) \eqn{E_{v,mel}^{D65}(t)}, transformed into -the effective light stimulus \eqn{I(t)}. - -\deqn{I(t) = E_{v,mel}^{D65} * K_{mel,v}^{D65}/A_{mel},} - -where \eqn{K_{mel,v}^{D65} = 1.3262 / 1000} is the melanopic normalization factor -to convert melanopic EDI to melanopic Irradiance and \eqn{A_{mel} = 97.07} is the -area of the melanopic sensitivity curve. - -The light stimulus \eqn{I(t)} is then passed through a linear filter \eqn{L1}, -which is associated with the temporal integration of the retina, to determine the -output \eqn{u(t)}. - -\deqn{u(t) = \frac{1}{d_{1}}\sum_{i=0}^{d_{1}/\Delta t} I(t-1)\Delta t,} - -where \eqn{d_{1}} is the length of filter \eqn{L1}. The time step size -\eqn{\Delta t} is the epoch at which the data was sampled. -Then \eqn{u(t)} is transformed by a nonlinear function \eqn{N(u)}, describing the -intensity-response relationship to the light stimulus, to determine the -output \eqn{v(t)}. - -\deqn{v(t) = N(u(t)) = \frac{1}{1+(\sigma(t)/u(t))^n}.} - -The half-maximum constant \eqn{\sigma} adapts to prior light history -\deqn{ - \begin{array}{ll} - \sigma(t)=\sigma_{0}/2, & \qquad & \forall u_{H}(t)<0,\\ - \sigma(t)=\sigma_{0}\times2^{u_{H}(t)-1}, & \qquad & \forall u_{H}(t)\geq 0. - \end{array} - } - -The prior history of light exposure is calculated using a moving window, -filter \eqn{LH}, to average the input - -\deqn{u_{H}(t) = \frac{1}{d_{H}}\sum_{i=0}^{d_{H}/\Delta t} - \log_{10}(E_{v}(t-i))\Delta t,} - -where \eqn{dH} is the width of the filter \eqn{LH} in hours and \eqn{E_{v}} -is the photopic illuminance. - -The signal \eqn{v(t)} is finally passed through a second filter \eqn{L2}, -which reflects the adaptation of the non-visual system to continuous light -exposure, to determine the final output \eqn{r_{D}(t)}. - -\deqn{r_{D}(t)=\alpha \times v(t−1)+(1−\alpha) \times r_{D}(t−1),} - - where \eqn{\alpha=2/(d2/\Delta t+1)} and \eqn{d2} is the length of filter -\eqn{L2} in hours. The model outputs are time-sampled relative non-visual -responses. } \examples{ @@ -118,7 +67,7 @@ dataset.combined.nvRD <- dataset.combined \%>\% Amundadottir, M.L. (2016). Light-driven model for identifying indicators of non-visual health potential in the built environment [Doctoral dissertation, EPFL]. EPFL infoscience. -\url{http://dx.doi.org/10.5075/epfl-thesis-7146} +\doi{10.5075/epfl-thesis-7146} } \seealso{ Other metrics: diff --git a/man/nvRD_cumulative_response.Rd b/man/nvRD_cumulative_response.Rd index 37a9451..095ac20 100644 --- a/man/nvRD_cumulative_response.Rd +++ b/man/nvRD_cumulative_response.Rd @@ -56,7 +56,7 @@ dataset1 \%>\% Amundadottir, M.L. (2016). Light-driven model for identifying indicators of non-visual health potential in the built environment [Doctoral dissertation, EPFL]. EPFL infoscience. -\url{http://dx.doi.org/10.5075/epfl-thesis-7146} +\doi{10.5075/epfl-thesis-7146} } \seealso{ Other metrics: diff --git a/man/pulses_above_threshold.Rd b/man/pulses_above_threshold.Rd index 2991193..04afe3f 100644 --- a/man/pulses_above_threshold.Rd +++ b/man/pulses_above_threshold.Rd @@ -109,7 +109,7 @@ data \%>\% Wilson, J., Reid, K. J., Braun, R. I., Abbott, S. M., & Zee, P. C. (2018). Habitual light exposure relative to circadian timing in delayed sleep-wake phase disorder. \emph{Sleep}, 41(11). -\url{https://doi.org/10.1093/sleep/zsy166} +\doi{10.1093/sleep/zsy166} } \seealso{ Other metrics: diff --git a/man/symlog_trans.Rd b/man/symlog_trans.Rd index c461f8e..0f154aa 100644 --- a/man/symlog_trans.Rd +++ b/man/symlog_trans.Rd @@ -54,6 +54,6 @@ labels = function(x) format(x, scientific = FALSE, big.mark = " ")) } \references{ -This function`s code is a straight copy from a post on stack overflow. -https://stackoverflow.com/a/14674703 +This function`s code is a straight copy from a post on \href{https://stackoverflow.com/a/14674703}{stack overflow}. +The author of the answer is \href{https://stackoverflow.com/users/1320535/julius-vainora}{Julius Vainora}, and the author of the question \href{https://stackoverflow.com/users/1212562/brian-b}{Brian B} } diff --git a/man/timing_above_threshold.Rd b/man/timing_above_threshold.Rd old mode 100755 new mode 100644 index 1ea388d..48c1f7f --- a/man/timing_above_threshold.Rd +++ b/man/timing_above_threshold.Rd @@ -72,11 +72,11 @@ dataset1 \%>\% Reid, K. J., Santostasi, G., Baron, K. G., Wilson, J., Kang, J., & Zee, P. C. (2014). Timing and Intensity of Light Correlate with Body Weight in Adults. \emph{PLOS ONE}, 9(4), e92251. -\url{https://doi.org/10.1371/journal.pone.0092251} +\doi{10.1371/journal.pone.0092251} Hartmeyer, S.L., Andersen, M. (2023). Towards a framework for light-dosimetry studies: Quantification metrics. \emph{Lighting Research & Technology}. -\url{https://doi.org/10.1177/14771535231170500} +\doi{10.1177/14771535231170500} } \seealso{ Other metrics: diff --git a/tests/testthat/Rplots.pdf b/tests/testthat/Rplots.pdf index 728f55a..5b96a60 100644 Binary files a/tests/testthat/Rplots.pdf and b/tests/testthat/Rplots.pdf differ diff --git a/tests/testthat/test-aggregate_Date.R b/tests/testthat/test-aggregate_Date.R new file mode 100644 index 0000000..4c32a60 --- /dev/null +++ b/tests/testthat/test-aggregate_Date.R @@ -0,0 +1,29 @@ +test_that("aggregate_Date works", { + dates <- sample.data.environment + #aggregate_Date works + expect_no_error(aggregate_Date(dates)) + + #only one day left + dates_agg <- aggregate_Date(dates) + expect_equal(lubridate::date(dates_agg$Datetime) %>% unique() %>% length(), 1) + #leaving unit = "none" (default) yields different results depending on Id + expect_equal(dates_agg %>% dominant_epoch() %>% + dplyr::pull(dominant.epoch) %>% + as.numeric, + c(30, 10) + ) + #changing the date.handler to max works + dates_agg2 <- aggregate_Date(dates, date.handler = max) + expect_equal(lubridate::date(dates_agg2$Datetime) %>% + unique() %>% + as.character(), + "2023-08-20") + #changing the numeric unit works + dates_agg3 <- aggregate_Date(dates, unit = "15 mins") + expect_equal(dates_agg3 %>% + count_difftime() %>% + dplyr::pull(difftime) %>% + as.numeric, + c(15*60, 15*60) + ) + }) \ No newline at end of file diff --git a/tests/testthat/test-double_date.R b/tests/testthat/test-double_date.R new file mode 100644 index 0000000..d3083d2 --- /dev/null +++ b/tests/testthat/test-double_date.R @@ -0,0 +1,58 @@ +test_that("repeat_date and next date works", { + #some example datetimes + dates <- tibble::tibble( + Datetime = as.POSIXct( + c("2023-08-20 10:00:00", + "2023-08-20 10:15:00", + "2023-08-20 10:30:00", + "2023-08-20 10:45:00" + ) + ) + ) + + #repeat_date works + expect_equal(nrow(repeat_date(dates)), 2*nrow(dates)) + expect_equal(repeat_date(dates) %>% + dplyr::pull(Datetime) %>% + lubridate::date() %>% + unique() %>% as.character(), + c("2023-08-20", "2023-08-21")) + expect_equal(repeat_date(dates) %>% length(), 2) + expect_equal(repeat_date(dates) %>% dplyr::group_vars(), "Date.data") + expect_true(repeat_date(dates) %>% + create_Timedata() %>% + dplyr::pull(Time.data) %>% {all(.[1:4] == .[5:8])}) + + #next_date works + next_dates <- next_date(repeat_date(dates) %>% dplyr::ungroup()) + expect_equal(nrow(next_dates), 3*nrow(dates)) + expect_equal(next_dates %>% + dplyr::pull(Datetime) %>% + lubridate::date() %>% unique() %>% as.character(), + c("2023-08-20", "2023-08-21")) + expect_equal(next_dates %>% + dplyr::pull(Datetime) %>% + lubridate::date() %>% table() %>% unname() %>% as.numeric(), + c(4, 8)) + expect_equal(next_dates %>% length(), 2) + expect_equal(next_dates %>% dplyr::group_vars(), "Date.data") +}) + +test_that("double_date works", { + #some example datetimes + dates <- tibble::tibble( + Datetime = as.POSIXct( + c("2023-08-20 10:00:00", + "2023-08-20 10:15:00", + "2023-08-20 10:30:00", + "2023-08-20 10:45:00" + ) + ) + ) + next_dates <- next_date(repeat_date(dates) %>% dplyr::ungroup()) + + #double_date correctly identifies the correct type of date + expect_equal(double_date(dates), repeat_date(dates)) + expect_equal(double_date(repeat_date(dates) %>% dplyr::ungroup()), + next_dates) +}) \ No newline at end of file diff --git a/vignettes/articles/Import.Rmd b/vignettes/articles/Import.Rmd index 94aad6e..6d010f3 100644 --- a/vignettes/articles/Import.Rmd +++ b/vignettes/articles/Import.Rmd @@ -9,7 +9,7 @@ knitr::opts_chunk$set( ) ``` -This article focuses on the import from multiple files and participants, as well as the cleaning of the data. We need these packages +This article focuses on the import from multiple files and participants, as well as the cleaning of the data. We need these packages: ```{r setup, message = FALSE} library(LightLogR) @@ -17,7 +17,33 @@ library(tidyverse) library(gghighlight) ``` -# Importing Data +# From which devices can I import data? + +LightLogR aims to provide standard import routines for all devices used in research on personal light exposure. Currently, the following devices are supported: + +```{r} +supported.devices +``` +More Information on these devices can be found in the reference for +`import_Dataset()`. + +## What if my device is not listed? + +If you are using a device that is currently not supported, please contact the developers. We are always looking to expand the range of supported devices. The easiest and most trackable way to get in contact is by opening a new issue on our [Github repository](https://github.com/tscnlab/LightLogR/issues). Please also provide a sample file of your data, so we can test the import function. + +## What if my device is listed but the import does not work as expected? + +We regularly find that files exported from the same device model can differ in structure. This may be due to different settings, software or hardware updates. If you encounter problems with the import, please get in contact with us, e.g. by opening an issue on our [Github repository](https://github.com/tscnlab/LightLogR/issues). Please provide a sample file of your data. + +## Are there other ways to import data? + +Yes. `LightLogR` simply requires a `data.frame` with a column containing `datetime` formatted data. Even a `light` data column is not strictly necessary, as `LightLogR` is optimized for, but not restricted to, light data. Further, an `Id` column is used in some functions to distinguish between different participants. + +To make life easier when using functions in `LightLogR`, the datetime column should be named `Datetime`, the id column `Id`, and, if present, the melanopic EDI light information `MEDI`. + +Lastly, you can modify or add import functions that build upon `LightLogR`s import functionality. See the last chapter in this article for more information on that. + +# Importing data The first step in every analysis is data import. We will work with data collected as part of the Master Thesis *Insights into real-world human light exposure: relating self-report with eye-level light logging* by Carolina Guidolin (2023). The data is stored in 17 text files in the *data/* folder. You can access the data yourself through the [LightLogR GitHub repository](https://github.com/tscnlab/LightLogR/tree/main/vignettes/articles/data). @@ -50,6 +76,18 @@ Now we can import the data. Data were collected with the ActLumus device by Cond data <- import$ActLumus(files, tz = tz, auto.id = pattern, print_n=33) ``` +## My import is slow. Why is that and can I speed it up? + +There are several possibilities, why the import is slow. The most common reasons are: + +- The data files are simply large. With short measurement intervals, many participants, and long measurement periods, files for a single study can easily reach several gigabytes. This takes some time to import and is ok. +- The data files contain many gaps. During import, `LightLogR` checks for and visualizes gaps in the data. Especially large datasets with small intervals contain many gaps, which can slow down the import process. +- The device model you are importing from has non-consistent data structures. Some devices have a varying number of rows before the actual data starts. This means a small portion of every file has to be read in and the correct starting row has to be found. This can slow down the import process if you have many files. + +If you are experiencing slow imports, you can try the following: +- Only read in part of your datasets, or split your dataset into several peaces, that each gets loaded in separately. You can combine them afterwards with `join_datasets()`. +- If you have many gaps in your data, you can set `auto.plot = FALSE` in the import function. This will eliminate the call to `gg_overview()`, which calculates and visualizes the gaps in the data. + # Data cleaning #1 Before we can dive into the analysis part, we need to make sure we have a clean dataset. The import summary shows us two problems with the data: @@ -140,3 +178,68 @@ The data is now clean and we can proceed with the analysis. This dataset will be ```{r} # saveRDS(data, "cleaned_data/ll_data.rds") ``` + +# Importing data: Miscellaneous + +## Other import arguments + +Other potentially important arguments are the `locale` argument - this is useful if you have special characters in your data (e.g. German ü or ä) that are not recognized by the default locale. Look at `readr::default_locale()` for more information. + +The `...` argument is passed through to whichever import function is used for the data. For some devices, it is also used to provide additional information, such as `column_names` for the Actiwatch devices, that differ depending on the language setting of the device and software. Whether a device requires additional information can be found in the import documentation (see `import_Dataset()`). + +## Other ways to call import + +Instead of using the import function as described above (`import$device()`), you can also use the function `import_Dataset()` and specify the device as a character string in the first argument. This might be useful if you want to import data programmatically from different devices, e.g., through a `purrr::map()` function. Only `supported.devices` will be accepted by the function. + +Here is an example: + +``` +devices <- c("ActLumus", "Speccy") +files_AL <- c("path/to/ActLumus/file1.csv", "path/to/ActLumus/file2.csv") +files_Sy <- c("path/to/Speccy/file1.csv", "path/to/Speccy/file2.csv") +tz <- "Europe/Berlin" + +data <- purrr::map2(devices, list(files_AL, files_Sy), import_Dataset, tz = tz) +``` + +This way, you will end with a list of two dataframes, one with the ActLumus data and one with the Speccy data. + +## Creating your own import function + +**Note: This section is for advanced users only. You should be familiar with expressions in R and how to manipulate them.** + +`LightLogR` comes with a number of custom import routines for different devices, that are then implemented into the main import function, which covers some general aspects and also creates the summary overview. + +If you would like to write your own custom import function, `LightLogR` has you covered. First, you can see what makes all the import functions tick by looking at the included data set `ll_import_expr`. This is a list of all the individual routines. Let's have a look at the ActLumus routine + +```{r} +ll_import_expr$ActLumus +``` +We can see, it is rather simple, just a few lines of code. You can write your own expression and create an import function with it. The expression should create a `data` variable that contains the import script for the files. At the end of the expression, the `data` variable should contain the imported dataset and include a correctly formatted `Datetime` column, complete with the correct timezone. + +Here we will create a variation of the old routine, that just adds a short message: + +```{r} +ll_import_expr$ActLumus_new <- ll_import_expr$ActLumus +ll_import_expr$ActLumus_new[[4]] <- + rlang::expr({ cat("**Congratulation, you made a new import function**\n") + data + }) +ll_import_expr$ActLumus_new + +``` + +We can now create a new import function with this expression. The function will be called `import$ActLumus_new()`. + +```{r} +import <- import_adjustment(ll_import_expr) +``` + +Let us now import a file of the previous dataset, setting the main summary and plotting function silent + +```{r} +data <- import$ActLumus_new(files[1], tz = tz, auto.id = pattern, + auto.plot = FALSE, silent = TRUE) + +``` + diff --git a/vignettes/articles/Metrics.Rmd b/vignettes/articles/Metrics.Rmd index 061ceea..156bd7d 100644 --- a/vignettes/articles/Metrics.Rmd +++ b/vignettes/articles/Metrics.Rmd @@ -44,6 +44,8 @@ There are a lot of metrics associated with personal light exposure. You can find We will cover the practical considerations following from these aspects in the following sections. Further, every function documentation explicitly states whether different metrics are accessible through parameters, and which metrics are calculated by default. +**Note: Most metrics require complete and regular data for a sensible output. While some metrics can handle missing data, it is generally advisable to clean the data before calculating metrics. LightLogR helps to identify gaps and irregularities and can also aggregate data to larger intervals, which can be acceptable for small gaps. In cases of larger gaps, dates or participants might have to be removed from analysis.** + # Metric calculation: basics All metric functions are by default agnostic to the type of data. They require vectors of numeric data (e.g., light data) and commonly also of datetimes. This means that the functions can be used outside of the LightLogR framework, if applied correctly. Let us try this with a simple example for a days worth of light data for one participant across two functions. diff --git a/vignettes/articles/Visualizations.Rmd b/vignettes/articles/Visualizations.Rmd index 5a377b4..1b92f4f 100644 --- a/vignettes/articles/Visualizations.Rmd +++ b/vignettes/articles/Visualizations.Rmd @@ -15,6 +15,7 @@ The following packages are needed for the analysis: ```{r setup, message = FALSE} library(LightLogR) library(tidyverse) +library(patchwork) ``` # Importing Data @@ -113,7 +114,7 @@ data_subset %>% This is the companion function to `gg_day()`. Instead of using individual days, it will create a timeline of days across all Ids. -```{r, fig.width=10} +```{r, fig.width=12} data_subset2 <- data %>% filter(Id %in% c(205, 216, 219)) %>% #choosing 2 ids @@ -122,19 +123,20 @@ data %>% data_subset2 %>% gg_days() ``` -By default, `gg_days()` will always plot full days. Let us strip one participant of data for one day. +By default, `gg_days()` will always plot full days. Let us strip one participant of data for three days. -```{r, fig.width=10} +```{r, fig.width=12} data_subset3 <- data_subset2 %>% - filter(!(Id == 205 & date(Datetime) == "2023-08-28")) + filter(!(Id == 205 & + date(Datetime) %in% c("2023-08-28", "2023-08-29", "2023-08-30"))) data_subset3 %>% gg_days() ``` You can see the plots are misaligned in their facets. We can correct for that by providing an exact number of days to the `x.axis.limits` argument. `Datetime_limits()` is a helper function from `LightLogR` and the documentation reveals more about its arguments. -```{r, fig.width=10} +```{r, fig.width=12} data_subset3 %>% gg_days( x.axis.limits = @@ -175,7 +177,7 @@ data_subset <- data_subset %>% gap_handler(full.days = TRUE) The horizontal doubleplot is activated by default, if only one day is present within all provided groups, or it can be set explicitly by `type = "repeat"`. -```{r, fig.height=8} +```{r, fig.height=10} data_subset %>% gg_doubleplot(aes_fill = Id, jco_color = TRUE, type = "repeat") #identical: @@ -189,7 +191,7 @@ Each plot line thus is the same day, plotted twice. The vertical doubleplot is activated by default if any group has more than one day. It can be set explicitly by `type = "next"`. -```{r,fig.height=8} +```{r,fig.height=10} data_subset %>% gg_doubleplot(aes_fill = Id, jco_color = TRUE) #identical: @@ -219,17 +221,28 @@ data_two_groups <- data %>% ) %>% group_by(Month) ``` -Now we can aggregate the data to a single day per group and make a doubleplot from it. +Now we can aggregate the data to a single day per group and make a doubleplot from it. With `aggregate_Date()` we condense a large dataset with 10-second intervals to a single day for two groups with a 15 minute interval. The day that is assigned by default is the median measurement day of the group. ```{r} data_two_groups %>% aggregate_Date(unit = "15 mins") %>% gg_doubleplot(aes_fill = Month, jco_color = TRUE) + guides(fill = "none") +``` + +We can further improve this plot. First, we overwrite the default behavior by setting a specific (arbitrary) date for both groups. By ungrouping the data afterwards, we can plot the two groups in a single row, making the two times easily comparable. Setting `facetting = FALSE` gets rid of the strip label, that otherwise would show the (arbitrary) date. + +```{r} +data_two_groups %>% + aggregate_Date(unit = "15 mins", + date.handler = \(x) as_date("2023-09-15") + ) %>% + ungroup() %>% + gg_doubleplot(aes_fill = Month, jco_color = TRUE, facetting = FALSE) ``` -With `aggregate_Date()` we condensed a large dataset with 10-second intervals to a single day for two groups with a 15 minute interval. The day that is assigned by default is the median measurement day of the group, it is shown to the as part of the strip label on the left. +We clearly see now, that daytime light exposure starts later and ends earlier, with lower daytime values overall. Conversely, nighttime light exposure is increased in the second half of the experiment (Oct/Nov). By using the `gg_doubleplot()` feature, the nighttime light pattern is clearly visible even accross midnight. # Interactivity @@ -242,3 +255,65 @@ data_subset %>% ) ``` +# Miscellaneous + +## Non-Light properties + +`LightLogR` is designed to work with light data, but it can also be used for other types of data. Simply define the y.axis argument in the plotting functions. In the following example, we will plot the activity data from the `data` dataset. + +For comparison, the light data is added in the background with a lower alpha value. + +```{r, fig.width=12} +data_subset2 %>% + gg_days(y.axis = PIM, y.axis.label = "Activity (PIM)") + + geom_line(aes(y=MEDI), color = "red", alpha = 0.2) +``` + +## Scales + +By default, `LightLogR` uses a so-called `symlog` scale for visualizations. This scale is a combination of a linear and a logarithmic scale, which is useful for light data, as it allows to visualize very low and very high values in the same plot, including 0 and negative values. As light data is regularly zero, and exact values between 0 and 1 lux are usually not as relevant for devices measuring up to 10^5 lx, this scale is more useful compared to a linear or logarithmic scaling. + +The way `symlog` works is that there is a threshold up to which absolute values are kept linear, and beyond which they are transformed logarithmically. The default threshold is 1, which is a good choice for light data. However, this can be changed by setting the `threshold` argument in the plotting functions. See a full documentation of the `symlog` scale `symlog_trans()`. + +Here is an example to show how the transformation is particularly useful for differences that cross zero. We will use the single-day doubleplot data from above. + +```{r, fig.height = 6} +#dataset from above +data <- +data_two_groups %>% + aggregate_Date(unit = "15 mins", + date.handler = \(x) as_date("2023-09-15") + ) %>% + ungroup() + +#original doubleplot from above +original_db <- data %>% + gg_doubleplot(aes_fill = Month, jco_color = TRUE, facetting = FALSE) + + guides(fill = "none") + +#difference doubleplot, showing the average difference between the to phases +difference_db <- +data %>% + select(Datetime, MEDI, Month) %>% + pivot_wider(names_from = Month, values_from = MEDI) %>% + gg_doubleplot(y.axis = `Oct/Nov`-`Aug/Sep`, facetting = FALSE, + y.axis.label = "difference (lx, MEDI)") + +#plotting +original_db / difference_db + +``` + +We can clearly see the difference in light exposure is crossing 0 several times. With the symlog scale no values are discarded, because they are outside the traditional range of a logarithmic scale. Should values below 1 lux be of interest, the parameters of the transformation can be adjusted. + +```{r} +data %>% + select(Datetime, MEDI, Month) %>% + pivot_wider(names_from = Month, values_from = MEDI) %>% + gg_doubleplot(y.axis = `Oct/Nov`-`Aug/Sep`, facetting = FALSE, + y.axis.label = "difference (lx, MEDI)", + y.scale = symlog_trans(thr = 0.001), + y.axis.breaks = c(-10^(-2:5), 0, 10^(5:-2)) + ) +``` +