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 forthreshold
, 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
and1
specifying the maximum proportion of the total number of interruptions. Defaults to0.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
isFALSE
. Defaults toFALSE
.- 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 toFALSE
.
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
See also
Other metrics:
bright_dark_period()
,
centroidLE()
,
disparity_index()
,
duration_above_threshold()
,
exponential_moving_average()
,
frequency_crossing_threshold()
,
interdaily_stability()
,
intradaily_variability()
,
midpointCE()
,
nvRC()
,
nvRD()
,
nvRD_cumulative_response()
,
period_above_threshold()
,
threshold_for_duration()
,
timing_above_threshold()
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>