Skip to contents

This function clusters the light data into continuous clusters (pulses) of light above/below a given threshold. Clustering may be fine-tuned by setting the minimum length of the clusters and by allowing brief interruptions to be included in a single cluster, with a specified maximum length of interruption episodes and proportion of total amount of interruptions to light above threshold.

Usage

pulses_above_threshold(
  Light.vector,
  Time.vector,
  comparison = c("above", "below"),
  threshold,
  min.length = "2 mins",
  max.interrupt = "8 mins",
  prop.interrupt = 0.25,
  epoch = "dominant.epoch",
  return.indices = FALSE,
  na.rm = FALSE,
  as.df = FALSE
)

Arguments

Light.vector

Numeric vector containing the light data. Missing values will be considered as FALSE when comparing light levels against the threshold.

Time.vector

Vector containing the time data. Can be POSIXct, hms, duration, or difftime.

comparison

String specifying whether the time above or below threshold should be calculated. Can be either "above" (the default) or "below". If two values are provided for threshold, this argument will be ignored.

threshold

Single numeric value or two numeric values specifying the threshold light level(s) to compare with. If a vector with two values is provided, the timing corresponding to light levels between the two thresholds will be calculated.

min.length

The minimum length of a pulse. Can be either a duration or a string. If it is a string, it needs to be a valid duration string, e.g., "1 day" or "10 sec". Defaults to "2 mins" as in Wilson et al. (2018).

max.interrupt

Maximum length of each episode of interruptions. Can be either a duration or a string. If it is a string, it needs to be a valid duration string, e.g., "1 day" or "10 sec". Defaults to "8 mins" as in Wilson et al. (2018).

prop.interrupt

Numeric value between 0 and 1 specifying the maximum proportion of the total number of interruptions. Defaults to 0.25 as in Wilson et al. (2018).

epoch

The epoch at which the data was sampled. Can be either a 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 duration string, e.g., "1 day" or "10 sec".

return.indices

Logical. Should the cluster indices be returned? Only works if as.df is FALSE. Defaults to FALSE.

na.rm

Logical. Should missing values be removed for the calculation of pulse metrics? Defaults to FALSE.

as.df

Logical. Should a data frame be returned? If TRUE, a data frame with seven columns ("n", "mean_level", "mean_duration", "total_duration", "mean_onset", "mean_midpoint", "mean_offset") and the threshold (e.g., _{threshold}) will be returned. Defaults to FALSE.

Value

List or data frame with calculated values.

Details

The timeseries is assumed to be regular. Missing values in the light data will be replaced by 0.

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. Sleep, 41(11). doi:10.1093/sleep/zsy166

Examples

# Sample data
data = sample.data.environment %>%
  dplyr::filter(Id == "Participant") %>%
  filter_Datetime(length = lubridate::days(1)) %>% 
  dplyr::mutate(
    Time = hms::as_hms(Datetime),
  )

# Time vector as datetime
data %>%
  dplyr::reframe(pulses_above_threshold(MEDI, Datetime, threshold = 250, as.df = TRUE))
#> # A tibble: 1 × 8
#>   Id          n_pulses_above_250 mean_level_pulses_abov…¹ mean_duration_pulses…²
#>   <chr>                    <int>                    <dbl> <Duration>            
#> 1 Participant                 10                    1579. 3149s (~52.48 minutes)
#> # ℹ abbreviated names: ¹​mean_level_pulses_above_250,
#> #   ²​mean_duration_pulses_above_250
#> # ℹ 4 more variables: total_duration_pulses_above_250 <Duration>,
#> #   mean_onset_pulses_above_250 <dttm>, mean_midpoint_pulses_above_250 <dttm>,
#> #   mean_offset_pulses_above_250 <dttm>

# Time vector as hms time
data %>%
  dplyr::reframe(pulses_above_threshold(MEDI, Time, threshold = 250, as.df = TRUE))
#> # A tibble: 1 × 8
#>   Id          n_pulses_above_250 mean_level_pulses_abov…¹ mean_duration_pulses…²
#>   <chr>                    <int>                    <dbl> <Duration>            
#> 1 Participant                 10                    1579. 3149s (~52.48 minutes)
#> # ℹ abbreviated names: ¹​mean_level_pulses_above_250,
#> #   ²​mean_duration_pulses_above_250
#> # ℹ 4 more variables: total_duration_pulses_above_250 <Duration>,
#> #   mean_onset_pulses_above_250 <time>, mean_midpoint_pulses_above_250 <time>,
#> #   mean_offset_pulses_above_250 <time>

# Pulses below threshold 
data %>%
  dplyr::reframe(pulses_above_threshold(MEDI, Datetime, "below", threshold = 250, as.df = TRUE))
#> # A tibble: 1 × 8
#>   Id          n_pulses_below_250 mean_level_pulses_belo…¹ mean_duration_pulses…²
#>   <chr>                    <int>                    <dbl> <Duration>            
#> 1 Participant                 13                     124. 3677s (~1.02 hours)   
#> # ℹ abbreviated names: ¹​mean_level_pulses_below_250,
#> #   ²​mean_duration_pulses_below_250
#> # ℹ 4 more variables: total_duration_pulses_below_250 <Duration>,
#> #   mean_onset_pulses_below_250 <dttm>, mean_midpoint_pulses_below_250 <dttm>,
#> #   mean_offset_pulses_below_250 <dttm>

# Pulses within threshold range
data %>%
  dplyr::reframe(pulses_above_threshold(MEDI, Datetime, threshold = c(250,1000), as.df = TRUE))
#> # A tibble: 1 × 8
#>   Id        n_pulses_within_250-…¹ mean_level_pulses_wi…² mean_duration_pulses…³
#>   <chr>                      <int>                  <dbl> <Duration>            
#> 1 Particip…                     11                   568. 449s (~7.48 minutes)  
#> # ℹ abbreviated names: ¹​`n_pulses_within_250-1000`,
#> #   ²​`mean_level_pulses_within_250-1000`,
#> #   ³​`mean_duration_pulses_within_250-1000`
#> # ℹ 4 more variables: `total_duration_pulses_within_250-1000` <Duration>,
#> #   `mean_onset_pulses_within_250-1000` <dttm>,
#> #   `mean_midpoint_pulses_within_250-1000` <dttm>,
#> #   `mean_offset_pulses_within_250-1000` <dttm>