Skip to content

Commit 457098c

Browse files
committed
Implement waso functionality
1 parent b7dcc71 commit 457098c

4 files changed

Lines changed: 221 additions & 90 deletions

File tree

circStudio/analysis/sleep/diary.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,3 @@ def sleep_onset_latency(self, data):
309309
# Typecast and return, sol to a pd.Series, along with the mean
310310
sol = pd.Series(sol)
311311
return pd.Series(sol), np.mean(sol)
312-

circStudio/analysis/sleep/sleep.py

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import numpy as np
22
import pandas as pd
33
import re
4+
import warnings
45
from .scoring import csm, roenneberg, sleep_midpoint, sri
56
from .scoring.utils import rescore
67
from scipy.ndimage import binary_closing, binary_opening
@@ -1576,6 +1577,83 @@ def main_sleep_bouts(data, report='major'):
15761577
#mean = minor_sleep['duration'].mean().total_seconds() / 60
15771578
mean = np.mean(minor_sleep['duration'])
15781579

1579-
15801580
# Return dataframe with major sleep events and summary stats
15811581
return minor_sleep, mean
1582+
1583+
def waso(data, algo='Cole-Kripke', **kwargs):
1584+
"""
1585+
Calculate Wake After Sleep Onset (WASO)
1586+
1587+
Parameters
1588+
----------
1589+
data : pandas.Series, optional
1590+
Input data series with a DatetimeIndex, where the index specifies the time points and
1591+
the values represent the input variable (e.g., activity, light). Time and value arrays
1592+
are extracted from this series.
1593+
algo
1594+
Sleep detection algorithm to use to detect sleep fragments during a consolidated sleep
1595+
period (as determined by the Roenneberg algorithm). It can be either 'Cole-Kripke',
1596+
'Sadeh' or 'Scripps'.
1597+
**kwargs
1598+
Pass the 'settings' keyword argument to if Cole-Kripke is used. Available settings are:
1599+
* "mean": mean activity per minute
1600+
* "10sec_max_overlap": maximum 10-second overlapping epoch per minute
1601+
* "10sec_max_non_overlap": maximum 10-second non-overlapping epoch per minute
1602+
* "30sec_max_non_overlap": maximum 30-second non-overlapping epoch per minute
1603+
1604+
1605+
Returns
1606+
-------
1607+
pd.Series
1608+
A series containing WASO values per day
1609+
np.float64
1610+
Mean WASO value
1611+
1612+
1613+
"""
1614+
# Calculate main consolidated sleep episodes using the Roenneberg algorithm
1615+
main_sleep_df = main_sleep_bouts(data)[0]
1616+
1617+
# Initialize the sleep_flags variable to store sleep segments
1618+
sleep_flags = None
1619+
1620+
# Select an algorithm to detect sleep segments
1621+
match algo:
1622+
case 'Cole-Kripke':
1623+
# User must provide a 'settings' argument to use Cole-Kripke
1624+
if 'settings' not in kwargs.keys():
1625+
# In case no setting is provided, use the 'mean' and warn
1626+
warnings.warn('No settings provided, using "mean" instead')
1627+
kwargs['settings'] = 'mean'
1628+
# Populate sleep_flags with the results from 'Cole-Kripke'
1629+
sleep_flags = Cole_Kripke(data, settings=kwargs.get('settings', {}))
1630+
case 'Sadeh':
1631+
# Populate sleep_flags with the results from 'Sadeh'
1632+
sleep_flags = Sadeh(data)
1633+
case 'Scripps':
1634+
# Populate sleep_flags with the results from 'Scripps'
1635+
sleep_flags = Scripps(data)
1636+
case _:
1637+
# Raise an error in case the algorithm selected is not available
1638+
raise ValueError('Algorithm {} is not valid.'.format(algo))
1639+
1640+
# Create an empty list to store daily waso values
1641+
waso_values = {}
1642+
1643+
# Iterate over the main sleep episodes in the recording
1644+
for _, row in main_sleep_df.iterrows():
1645+
# Extract the date from the current row
1646+
date = row['START'].date()
1647+
1648+
# Use the consolidated sleep episode to define the start and stop borders
1649+
sleep_window = sleep_flags[row['start_time']:row['stop_time']]
1650+
1651+
# Count minutes in which individual is awake during the consolidated sleep window
1652+
# (0: sleep, 1: wake)
1653+
waso_minutes = ((1 - sleep_window).sum())
1654+
1655+
# Append the result to the waso_values list
1656+
waso_values[date] = waso_minutes
1657+
1658+
waso_values = pd.Series(waso_values)
1659+
return waso_values, np.mean(waso_values)

0 commit comments

Comments
 (0)