Skip to content

Commit a793a16

Browse files
committed
implement mesa adaptor subclass
1 parent 99350fa commit a793a16

3 files changed

Lines changed: 340 additions & 47 deletions

File tree

circStudio/io/mesa/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .mesa import MESA
2+
from .mesa import read_mesa
3+
4+
__all__ = ["MESA", "read_mesa"]

circStudio/io/mesa/mesa.py

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
import pandas as pd
2+
import os
3+
import warnings
4+
from ..base import Raw
5+
6+
7+
class MESA(Raw):
8+
r"""Raw object from MESA files
9+
10+
Parameters
11+
----------
12+
input_fname: str
13+
Path to the MESA file.
14+
time_origin: datetime-like
15+
Time origin of the timestamps.
16+
Required as the MESA files do not contain date informations.
17+
Default is '2000-01-01'
18+
start_time: datetime-like, optional
19+
Read data from this time.
20+
Default is None.
21+
period: str, optional
22+
Length of the read data.
23+
Cf. #timeseries-offset-aliases in
24+
<https://pandas.pydata.org/pandas-docs/stable/timeseries.html>.
25+
Default is None (i.e all the data).
26+
intervals: dict, optional
27+
Map manually annotated periods to specific scores.
28+
If set to None, the names of the annotated periods is returned instead.
29+
Default is {'EXCLUDED': -1, 'ACTIVE': 1, 'REST': 0.5, 'REST-S': 0}.
30+
check_dayofweek: bool, optional
31+
If set to True, check if the day of the week reported in the original
32+
recording is aligned with the reconstructed index.
33+
Default is False.
34+
light_mode : str,
35+
Select light channel for analysis. Available modes for mesa are 'whitelight',
36+
'redlight', 'greenlight' and 'bluelight'. Default is 'whitelight'.
37+
"""
38+
39+
def __init__(
40+
self,
41+
input_fname,
42+
time_origin='2000-01-01',
43+
start_time=None,
44+
period=None,
45+
intervals=None,
46+
check_dayofweek=False,
47+
light_mode='whitelight'
48+
):
49+
if intervals is None:
50+
intervals = {'EXCLUDED': -1, 'ACTIVE': 1, 'REST': 0.5, 'REST-S': 0}
51+
52+
# get absolute file path
53+
input_fname = os.path.abspath(input_fname)
54+
55+
# read file
56+
data = pd.read_csv(input_fname, index_col='line')
57+
58+
freq = pd.Timedelta(30, unit='s')
59+
60+
# day of the week
61+
self._dayofweek = data['dayofweek']
62+
63+
# reconstruct MESA datetime index
64+
date = pd.to_datetime(
65+
data['daybymidnight'] - 1 + data.loc[1, 'dayofweek'],
66+
unit='D',
67+
origin=time_origin
68+
).astype(str)
69+
time = data['linetime']
70+
71+
index = pd.DatetimeIndex(date + ' ' + time, freq='infer')
72+
73+
data.set_index(index, inplace=True)
74+
75+
if check_dayofweek:
76+
# Shift day of the week to match Pandas' convention (0=Monday, etc)
77+
dw = self.__dayofweek - 2
78+
if (data.index.dayofweek - dw.where(dw >= 0, dw + 7)).sum() != 0:
79+
warnings.warn((
80+
"Specified time_origin is such that the day of the week in"
81+
" the reconstructed time index is *not* aligned with the"
82+
" day of the week reported in the recording."
83+
))
84+
85+
# set start and stop times
86+
if start_time is not None:
87+
start_time = pd.to_datetime(start_time)
88+
else:
89+
start_time = data.index[0]
90+
91+
if period is not None:
92+
period = pd.Timedelta(period)
93+
stop_time = start_time+period
94+
else:
95+
stop_time = data.index[-1]
96+
period = stop_time - start_time
97+
98+
data = data[start_time:stop_time]
99+
100+
# no wear indicator
101+
self._nowear = data['offwrist']
102+
103+
# event marker indicator
104+
self._marker = data['marker']
105+
106+
# LIGHT
107+
self._white_light = data['whitelight']
108+
109+
# wake indicator
110+
self._wake = data['wake']
111+
112+
# intervals
113+
if intervals is not None:
114+
self._intervals = data['interval'].map(intervals)
115+
else:
116+
self._intervals = data['interval']
117+
118+
# call __init__ function of the base class
119+
super().__init__(
120+
df = data,
121+
fpath=input_fname,
122+
start_time=start_time,
123+
period=period,
124+
frequency=freq,
125+
activity=data['activity'],
126+
light=data[light_mode]
127+
)
128+
129+
@property
130+
def marker(self):
131+
r"""Event marker indicator."""
132+
return self._marker
133+
134+
@property
135+
def wake(self):
136+
r"""Awake indicator."""
137+
return self._wake
138+
139+
@property
140+
def nowear(self):
141+
r"""Off-wrist indicator."""
142+
return self._nowear
143+
144+
@property
145+
def intervals(self):
146+
r"""Interval type (manual rest-activty scoring)."""
147+
return self._intervals
148+
149+
@property
150+
def dayofweek(self):
151+
r"""Day of the week (1=Sunday, 2=Monday, etc)."""
152+
return self._dayofweek
153+
154+
@property
155+
def white_light(self):
156+
r"""Value of the white light illuminance in lux."""
157+
return self._white_light
158+
159+
160+
def read_mesa(
161+
input_fname,
162+
time_origin='2000-01-01',
163+
start_time=None,
164+
period=None,
165+
intervals=None,
166+
check_dayofweek=False,
167+
light_mode='whitelight'
168+
):
169+
r"""Reader function for MESA files
170+
171+
Parameters
172+
----------
173+
input_fname: str
174+
Path to the ActTrust file.
175+
time_origin: datetime-like
176+
Time origin of the timestamps.
177+
Required as the MESA files do not contain date informations.
178+
Default is '2000-01-01'
179+
start_time: datetime-like, optional
180+
Read data from this time.
181+
Default is None.
182+
period: str, optional
183+
Length of the read data.
184+
Cf. #timeseries-offset-aliases in
185+
<https://pandas.pydata.org/pandas-docs/stable/timeseries.html>.
186+
Default is None (i.e., all the data).
187+
intervals: dict, optional
188+
Map manually annotated periods to specific scores.
189+
If set to None, the names of the annotated periods is returned instead.
190+
Default is {'EXCLUDED': -1, 'ACTIVE': 1, 'REST': 0.5, 'REST-S': 0}.
191+
check_dayofweek: bool, optional
192+
If set to True, check if the day of the week reported in the original
193+
recording is aligned with the reconstructed index.
194+
Default is False.
195+
light_mode : str,
196+
Select light channel for analysis. Available modes for mesa are 'whitelight',
197+
'redlight', 'greenlight' and 'bluelight'. Default is 'whitelight'.
198+
199+
Returns
200+
-------
201+
raw : Instance of RawMESA
202+
An object containing raw MESA data
203+
"""
204+
if intervals is None:
205+
intervals = {'EXCLUDED': -1, 'ACTIVE': 1, 'REST': 0.5, 'REST-S': 0}
206+
207+
return MESA(
208+
input_fname=input_fname,
209+
time_origin=time_origin,
210+
start_time=start_time,
211+
period=period,
212+
intervals=intervals,
213+
check_dayofweek=check_dayofweek,
214+
light_mode=light_mode
215+
)

0 commit comments

Comments
 (0)