noctsleepy
noctsleepy
A Python package for computing nocturnal sleep metrics from processed actigraphy data.
Overview
noctsleepy is a Python-based toolbox for computing comprehensive sleep metrics from processed actigraphy data. Sleep metrics are computed from a user-defined nocturnal window, thus the impact of naps/secondary sleep can be removed if needed. The package handles timezone-aware processing, including proper daylight saving time (DST) transitions, and computes both individual night metrics and summary statistics across multiple nights.
Key Features
- Comprehensive Sleep Metrics: Computes sleep duration, time in bed, sleep efficiency, wake after sleep onset (WASO), number of awakenings, sleep onset/wakeup times, and sleep midpoints.
- DST-Aware Processing: Properly handles daylight saving time transitions using IANA timezone database, ensuring accurate sleep timing metrics during time changes.
- Summary Statistics: Automatically computes mean and standard deviation for all requested metrics.
- Flexible Nocturnal Windows: Users can define custom start and end times for the nocturnal interval.
- Non-wear Filtering: Filters out nights with excessive non-wear time based on user-defined thresholds.
Installation
Install the noctsleepy package from PyPI via:
pip install noctsleepy
Quick Start
noctsleepy provides two flexible interfaces: a command-line tool for direct execution and an importable Python library.
Using noctsleepy through the command-line:
Basic usage:
noctsleepy /path/to/data.csv america/new_york
Custom parameters:
noctsleepy /path/to/data.csv europe/london \
--night-start 22:00 \
--night-end 07:00 \
--nw-threshold 0.3 \
--metrics sleep_duration \
--metrics sleep_timing
For a full list of command line arguments:
noctsleepy --help
Using noctsleepy through a Python script or notebook:
import noctsleepy
import pathlib
import datetime
# Define input file path
input_path = pathlib.Path('/path/to/your/data.csv')
# Compute all sleep metrics
sleep_metrics = noctsleepy.compute_sleep_metrics(
input_data=input_path,
timezone='America/New_York'
)
# Compute custom pipeline
custom_metrics = noctsleepy.compute_sleep_metrics(
input_data=input_path,
timezone='America/Toronto',
night_start=datetime.time(22, 0),
night_end=datetime.time(6, 0),
nw_threshold=0.15,
selected_metrics=['sleep_continuity', 'sleep_timing']
)
# Access computed metrics
sleep_duration = sleep_metrics.sleep_duration
sleep_onset = sleep_metrics.sleep_onset
sleep_efficiency = sleep_metrics.sleep_efficiency
Input Data Requirements
noctsleepy requires processed actigraphy data with the following columns:
time: Timestamps for each data point, it should be a singular sampling rate.sib_periods: Boolean indicating sustained inactivity bouts (sleep detection).spt_periods: Boolean indicating sleep period time windows.nonwear_status: Boolean indicating non-wear periods.
The input data should ideally be processed with wristpy or have a compatible output format. Supported input formats include CSV and Parquet files.
Computed Sleep Metrics
All metrics are computed only during the defined nocturnal window, any sleep that occurs outside of this window is ignored.
Sleep Duration Metrics
- sleep_duration: Total sleep time in minutes (sum of sustained inactivity bouts within sleep period time).
- time_in_bed: Total time in bed in minutes (duration of sleep period time windows).
Sleep Continuity Metrics
- sleep_efficiency: Ratio of total sleep time to time in bed, as a percentage.
- waso: Wake After Sleep Onset, in minutes.
- num_awakenings: Number of awakening episodes during the sleep period.
- waso_30: Number of nights with WASO exceeding 30 minutes (normalized to 30-day protocol).
Sleep Timing Metrics
- sleep_onset: Time when the first sleep period starts (HH:MM format).
- sleep_wakeup: Time when the last sleep period ends (HH:MM format).
- sleep_midpoint: Midpoint of the sleep period (HH:MM format).
- weekday_midpoint: Average sleep midpoint on weekdays (Monday-Friday).
- weekend_midpoint: Average sleep midpoint on weekends (Saturday-Sunday).
- social_jetlag: Absolute difference between weekend and weekday midpoints, in hours.
Summary Statistics
For each metric, noctsleepy automatically computes:
- Mean: Average value across all valid nights
- Standard Deviation: Measure of variability across nights
- Duration metrics use standard statistics
- Time-based metrics use circular statistics to properly handle times crossing midnight
Handling Timezones and Daylight Saving Time
noctsleepy requires users to specify a timezone-aware location using IANA timezone database names (e.g., America/New_York, Europe/London). The package properly handles DST transitions:
Wall-Clock vs. Anatomical Clock
- Wall-clock metrics (sleep onset, wakeup, midpoint): Reported based on the local time displayed on a clock
- Anatomical clock metrics (sleep duration, time in bed, WASO, sleep efficiency): Account for actual elapsed time, including DST changes.
Example: During a "fall back" DST transition, if someone sleeps from 10:00 PM to 6:00 AM (wall-clock time), their sleep duration will reflect the additional hour gained during the transition (9 hours of actual sleep), while the onset/wakeup times show the wall-clock times (10:00 PM and 6:00 AM).
Supported Timezones
noctsleepy supports timezones across many regions, including:
- North America:
us_eastern,us_central,us_mountain,us_pacific,us_alaska,us_hawaii,canada_eastern,mexico_central, etc. - Europe:
europe_london,europe_paris,europe_berlin,europe_rome,europe_moscow, etc. - Asia:
asia_tokyo,asia_shanghai,asia_kolkata,asia_singapore,asia_dubai, etc. - South America:
brazil_eastern,argentina,chile,colombia, etc. - Africa:
africa_cairo,africa_johannesburg,africa_nairobi,africa_lagos, etc. - Oceania:
australia_sydney,australia_melbourne,new_zealand,pacific_fiji, etc.
For a complete list of supported timezones, run:
noctsleepy compute-metrics --help
Output Format
Results are automatically saved as a JSON file in the same directory as the input file, containing both per night statistics and summary statistics.
Support
For questions, bug reports, or feature requests, please open an issue on GitHub.
30def compute_sleep_metrics( 31 input_data: pathlib.Path | str, 32 timezone: str, 33 night_start: Optional[datetime.time] = None, 34 night_end: Optional[datetime.time] = None, 35 nw_threshold: float = 0.2, 36 selected_metrics: Optional[Iterable[SLEEP_METRIC_CATEGORIES]] = None, 37) -> sleep_variables.SleepMetrics: 38 """Compute sleep metrics from the provided data file. 39 40 The input data file contains time-series data from processed actigraphy devices. 41 Ideally, the raw actigraphy data is processed with `wristpy`, or at the minimum 42 must have a compatible output format. 43 44 Users can specify the start and end times of the night to filter the data, 45 a non-wear threshold, and the metrics they want to compute. Summary statistics 46 (mean, standard deviation) are also computed for each metric across all nights. 47 48 **Handling Timezones and Daylight Savings Time (DST)** 49 Users must provide a location-aware timezone that conforms to the IANA timezone 50 database. During/after DST transitions, the nocturnal interval window will be 51 defined based on the wall-clock time. 52 53 Certain metrics, such as sleep onset, sleep wakeup, and sleep midpoint, 54 are calculated based solely on the wall clock time within the nocturnal interval. 55 However, sleep duration, time in bed, sleep efficiency, WASO are computed based 56 on the anatomical clock, accounting for any DST changes. 57 For example, if a night includes a "fall back" transition, the sleep duration 58 will reflect the additional hour gained during the transition. 59 60 61 The output is saved to csv format. 62 63 Args: 64 input_data: Path to the input data file (CSV or Parquet). 65 timezone: Timezone aware location of the input data. Used for Daylight 66 Savings Time processing, this must be an IANA timezone string. 67 night_start: Start time of the nocturnal interval. If None, defaults to 20:00. 68 night_end: End time of the nocturnal interval. If None, defaults to 08:00. 69 nw_threshold: Non-wear threshold, below which a night is considered valid. 70 If None, defaults to 0.2. 71 selected_metrics: Specific metrics to compute. 72 If None, all metrics are computed. 73 74 Returns: 75 An instance of SleepMetrics containing the computed metrics. 76 77 Raises: 78 ValueError: If the provided timezone is not valid. 79 """ 80 if timezone not in list(timezones.CommonTimezones.__args__): # type: ignore[attr-defined] #Valid attribute for Literal 81 raise ValueError(f"Invalid timezone: {timezone}") 82 if night_start is None: 83 night_start = datetime.time(hour=20, minute=0) 84 if night_end is None: 85 night_end = datetime.time(hour=8, minute=0) 86 output_file = pathlib.Path(input_data).with_name( 87 pathlib.Path(input_data).stem + "_sleep_metrics.json" 88 ) 89 90 data = readers.read_wristpy_data(pathlib.Path(input_data)) 91 sleep_data = sleep_variables.SleepMetrics( 92 data=data, 93 night_start=night_start, 94 night_end=night_end, 95 nw_threshold=nw_threshold, 96 timezone=timezone, 97 ) 98 99 if selected_metrics is None: 100 selected_metrics = ["sleep_duration", "sleep_continuity", "sleep_timing"] 101 102 metrics_to_compute = itertools.chain.from_iterable( 103 METRIC_MAPPING[metric] for metric in selected_metrics 104 ) 105 106 sleep_metrics_dict = sleep_data.save_to_dict(metrics_to_compute) 107 108 summary_stats = sleep_variables.extract_simple_statistics(sleep_data) 109 110 output_file.write_text( 111 json.dumps( 112 { 113 "sleep_metrics": sleep_metrics_dict, 114 "summary_statistics": summary_stats, 115 }, 116 indent=4, 117 default=str, 118 ) 119 ) 120 121 return sleep_data
Compute sleep metrics from the provided data file.
The input data file contains time-series data from processed actigraphy devices.
Ideally, the raw actigraphy data is processed with wristpy, or at the minimum
must have a compatible output format.
Users can specify the start and end times of the night to filter the data, a non-wear threshold, and the metrics they want to compute. Summary statistics (mean, standard deviation) are also computed for each metric across all nights.
Handling Timezones and Daylight Savings Time (DST) Users must provide a location-aware timezone that conforms to the IANA timezone database. During/after DST transitions, the nocturnal interval window will be defined based on the wall-clock time.
Certain metrics, such as sleep onset, sleep wakeup, and sleep midpoint, are calculated based solely on the wall clock time within the nocturnal interval. However, sleep duration, time in bed, sleep efficiency, WASO are computed based on the anatomical clock, accounting for any DST changes. For example, if a night includes a "fall back" transition, the sleep duration will reflect the additional hour gained during the transition.
The output is saved to csv format.
Arguments:
- input_data: Path to the input data file (CSV or Parquet).
- timezone: Timezone aware location of the input data. Used for Daylight Savings Time processing, this must be an IANA timezone string.
- night_start: Start time of the nocturnal interval. If None, defaults to 20:00.
- night_end: End time of the nocturnal interval. If None, defaults to 08:00.
- nw_threshold: Non-wear threshold, below which a night is considered valid. If None, defaults to 0.2.
- selected_metrics: Specific metrics to compute. If None, all metrics are computed.
Returns:
An instance of SleepMetrics containing the computed metrics.
Raises:
- ValueError: If the provided timezone is not valid.