|
1 | 1 | import numpy as np |
2 | 2 | import pandas as pd |
3 | 3 | import re |
| 4 | +import warnings |
4 | 5 | from .scoring import csm, roenneberg, sleep_midpoint, sri |
5 | 6 | from .scoring.utils import rescore |
6 | 7 | from scipy.ndimage import binary_closing, binary_opening |
@@ -1576,6 +1577,83 @@ def main_sleep_bouts(data, report='major'): |
1576 | 1577 | #mean = minor_sleep['duration'].mean().total_seconds() / 60 |
1577 | 1578 | mean = np.mean(minor_sleep['duration']) |
1578 | 1579 |
|
1579 | | - |
1580 | 1580 | # Return dataframe with major sleep events and summary stats |
1581 | 1581 | 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