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