circStudio 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. circstudio/.DS_Store +0 -0
  2. circstudio/__init__.py +7 -0
  3. circstudio/analysis/__init__.py +11 -0
  4. circstudio/analysis/cosinor/__init__.py +2 -0
  5. circstudio/analysis/cosinor/cosinor.py +278 -0
  6. circstudio/analysis/flm/__init__.py +3 -0
  7. circstudio/analysis/flm/flm.py +402 -0
  8. circstudio/analysis/fractal/__init__.py +4 -0
  9. circstudio/analysis/fractal/fractal.py +727 -0
  10. circstudio/analysis/lids/__init__.py +3 -0
  11. circstudio/analysis/lids/lids.py +605 -0
  12. circstudio/analysis/lids/likelihood.py +112 -0
  13. circstudio/analysis/lids/model_functions.py +80 -0
  14. circstudio/analysis/lids/signal_functions.py +78 -0
  15. circstudio/analysis/lids/smoothing.py +38 -0
  16. circstudio/analysis/lids/transforms.py +63 -0
  17. circstudio/analysis/metrics/__init__.py +2 -0
  18. circstudio/analysis/metrics/feature_screening.py +442 -0
  19. circstudio/analysis/metrics/metrics.py +1854 -0
  20. circstudio/analysis/models/__init__.py +3 -0
  21. circstudio/analysis/models/light_tools.py +778 -0
  22. circstudio/analysis/models/math_models.py +3010 -0
  23. circstudio/analysis/models/tools.py +306 -0
  24. circstudio/analysis/sleep/__init__.py +3 -0
  25. circstudio/analysis/sleep/diary.py +406 -0
  26. circstudio/analysis/sleep/scoring/__init__.py +5 -0
  27. circstudio/analysis/sleep/scoring/csm.py +235 -0
  28. circstudio/analysis/sleep/scoring/roenneberg.py +354 -0
  29. circstudio/analysis/sleep/scoring/smp.py +225 -0
  30. circstudio/analysis/sleep/scoring/sri.py +164 -0
  31. circstudio/analysis/sleep/scoring/utils.py +441 -0
  32. circstudio/analysis/sleep/sleep.py +1910 -0
  33. circstudio/analysis/sleep/sleep_tools.py +206 -0
  34. circstudio/analysis/ssa/__init__.py +3 -0
  35. circstudio/analysis/ssa/ssa.py +557 -0
  36. circstudio/analysis/tools.py +476 -0
  37. circstudio/data/.DS_Store +0 -0
  38. circstudio/data/example_01.AWD +18408 -0
  39. circstudio/data/example_01_mask.AWD +18408 -0
  40. circstudio/data/example_01_sleepdiary.ods +0 -0
  41. circstudio/data/example_01_sleepdiary_extra_states.ods +0 -0
  42. circstudio/data/example_02.AWD +18420 -0
  43. circstudio/data/example_03.AWD +21463 -0
  44. circstudio/data/example_04.AWD +31306 -0
  45. circstudio/data/example_05.AWD +21710 -0
  46. circstudio/data/example_masklog.csv +3 -0
  47. circstudio/data/example_sstlog.csv +4 -0
  48. circstudio/data/example_sstlog.ods +0 -0
  49. circstudio/data/example_sstlog.xls +0 -0
  50. circstudio/data/example_sstlog.xlsx +0 -0
  51. circstudio/data/sample-summary-no-calibration.json +32 -0
  52. circstudio/data/sample-summary-wrong-name.json +32 -0
  53. circstudio/data/sample-summary.json +837 -0
  54. circstudio/data/sample-timeSeries.csv.gz +0 -0
  55. circstudio/data/sleepdiary_atr.ods +0 -0
  56. circstudio/data/test_sample.AWD +11725 -0
  57. circstudio/data/test_sample.agd +0 -0
  58. circstudio/data/test_sample.csv +11712 -0
  59. circstudio/data/test_sample.mtn +1234 -0
  60. circstudio/data/test_sample_atr.txt +5785 -0
  61. circstudio/data/test_sample_aw4.AWD +31861 -0
  62. circstudio/data/test_sample_aw7.AWD +30630 -0
  63. circstudio/data/test_sample_awi.AWD +6169 -0
  64. circstudio/data/test_sample_awl.AWD +12781 -0
  65. circstudio/data/test_sample_awlp.AWD +10110 -0
  66. circstudio/data/test_sample_awmk2.AWD +29999 -0
  67. circstudio/data/test_sample_aws.AWD +1528 -0
  68. circstudio/data/test_sample_awt.AWD +3869 -0
  69. circstudio/data/test_sample_dqt.csv +43215 -0
  70. circstudio/data/test_sample_mesa.csv +5 -0
  71. circstudio/data/test_sample_rpx_eng.csv +20308 -0
  72. circstudio/data/test_sample_rpx_fr.csv +11712 -0
  73. circstudio/data/test_sample_rpx_ger_no_light.csv +20313 -0
  74. circstudio/data/test_sample_rpx_ger_with_light.csv +20316 -0
  75. circstudio/data/test_sample_tal.txt +10088 -0
  76. circstudio/io/.DS_Store +0 -0
  77. circstudio/io/__init__.py +10 -0
  78. circstudio/io/agd/__init__.py +5 -0
  79. circstudio/io/agd/agd.py +252 -0
  80. circstudio/io/atr/__init__.py +5 -0
  81. circstudio/io/atr/atr.py +133 -0
  82. circstudio/io/awd/__init__.py +4 -0
  83. circstudio/io/awd/awd.py +279 -0
  84. circstudio/io/base.py +194 -0
  85. circstudio/io/dqt/__init__.py +5 -0
  86. circstudio/io/dqt/dqt.py +171 -0
  87. circstudio/io/mask.py +395 -0
  88. circstudio/io/mesa/__init__.py +4 -0
  89. circstudio/io/mesa/mesa.py +215 -0
  90. circstudio/io/rpx/__init__.py +4 -0
  91. circstudio/io/rpx/multilang.py +112 -0
  92. circstudio/io/rpx/rpx.py +407 -0
  93. circstudio/io/tal/__init__.py +5 -0
  94. circstudio/io/tal/tal.py +217 -0
  95. circstudio-1.0.0.dist-info/METADATA +807 -0
  96. circstudio-1.0.0.dist-info/RECORD +97 -0
  97. circstudio-1.0.0.dist-info/WHEEL +4 -0
circstudio/.DS_Store ADDED
Binary file
circstudio/__init__.py ADDED
@@ -0,0 +1,7 @@
1
+ from . import analysis
2
+ from . import io
3
+ from .analysis import *
4
+
5
+ __version__ = '1.0.0'
6
+
7
+
@@ -0,0 +1,11 @@
1
+ from .metrics.metrics import *
2
+ from .cosinor.cosinor import *
3
+ from .models.light_tools import *
4
+ from .models.math_models import *
5
+ from .models.tools import *
6
+ from .sleep.sleep import *
7
+ from .metrics.feature_screening import *
8
+ from .ssa import SSA
9
+ from .fractal import Fractal
10
+ from .flm import FLM
11
+ from .lids import LIDS
@@ -0,0 +1,2 @@
1
+ from .cosinor import Cosinor
2
+
@@ -0,0 +1,278 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ from lmfit import fit_report, minimize, Parameters
4
+ import plotly.graph_objects as go
5
+
6
+
7
+ class Cosinor:
8
+ """
9
+ Class for Cosinor analysis. Cosinor analysis fits a cosine curve to a time series
10
+ to summarize a rhythmic pattern using a small set of interpretable parameters.
11
+
12
+ It answers questions like:
13
+ - What is the typical baseline level of the signal? -> **Mesor**
14
+ - How large is the rhythm around that baseline? -> **Amplitude**
15
+ - When does the peak occur within the cycle? -> **Acrophase**
16
+ - What cycle length best matches the data? -> **Period**
17
+
18
+ Model
19
+ -----
20
+ This implementation uses a standard 1-harmonic cosinor model:
21
+
22
+ y(x) = Mesor + Amplitude * cos(2π/Period * x + Acrophase)
23
+
24
+ where `x`is time expressed in sample units (e.g., minutes since start),
25
+ not necessarily clock time.
26
+
27
+ Typical usage
28
+ -------------
29
+ >>> model = Cosinor()
30
+ >>> result = model.fit(series)
31
+ >>> mesor = result.params['Mesor'].value
32
+ >>> amplitude = result.params['Amplitude'].value
33
+ >>> period = result.params['Period'].value
34
+ >>> acrophase = result.params['Acrophase'].value
35
+ >>> best = model.best_fit(series, result.params)
36
+ >>> fig = model.plot(series, result.params)
37
+
38
+ References
39
+ ----------
40
+ This code is derived from the original implementation in pyActigraphy, distributed under the BSD 3-Clause License.
41
+ Original author: Grégory Hammad (gregory.hammad@uliege.be).
42
+
43
+ [1] Hammad, G., Reyt, M., Beliy, N., Baillet, M., Deantoni, M., Lesoinne, A., Muto, V., & Schmidt, C. (2021).
44
+ pyActigraphy: Open-source python package for actigraphy data visualization and analysis.
45
+ PLoS Computational Biology, 17(10), 1009514–1009535. https://doi.org/10.1371/journal.pcbi.1009514
46
+
47
+ [2] Hammad, G., Wulff, K., Skene, D. J., Münch, M., & Spitschan, M. (2024). Open-Source Python Module for the
48
+ Analysis of Personalized Light Exposure Data from Wearable Light Loggers and Dosimeters.
49
+ LEUKOS, 20(4), 380–389. https://doi.org/10.1080/15502724.2023.2296863
50
+
51
+ [3] Cornelissen, G. (2014). Cosinor-based rhythmometry. Theoretical Biology and Medical Modelling, 11(1), 16.
52
+ https://doi.org/10.1186/1742-4682-11-16
53
+
54
+ """
55
+ @staticmethod
56
+ def _cosinor(x, params):
57
+ """
58
+ 1-harmonic cosine function
59
+
60
+ Parameters
61
+ ----------
62
+ x : np.ndarray
63
+ Time values expressed in sample units (e.g., minutes since start).
64
+ params : lmfit.Parameters
65
+ Must contain: 'Amplitude', 'Acrophase', 'Period', 'Mesor'.
66
+
67
+ Returns
68
+ -------
69
+ np.ndarray
70
+ Model values evaluated at `x`.
71
+ """
72
+ A = params['Amplitude']
73
+ phi = params['Acrophase']
74
+ T = params['Period']
75
+ M = params['Mesor']
76
+ return M + A * np.cos(2 * np.pi / T * x + phi)
77
+
78
+ @staticmethod
79
+ def _residual(params, x, data, fit_func):
80
+ """
81
+ Residuals to be minimized by the optimizer.
82
+
83
+ Residuals are simply: observed - model.
84
+
85
+ Parameters
86
+ ----------
87
+ params : lmfit.Parameters
88
+ Candidate parameter values during optimization.
89
+ x : np.ndarray
90
+ Time values (in sample units).
91
+ data : np.ndarray
92
+ Observed data values.
93
+ fit_func : callable
94
+ Model function such as `_cosinor`.
95
+
96
+ Returns
97
+ -------
98
+ np.ndarray
99
+ Residual vector used by the optimizer.
100
+
101
+ """
102
+ model = fit_func(x, params)
103
+ return data - model
104
+
105
+ def __init__(self,fit_params=None):
106
+ """
107
+ Create a Cosinor model with default or user-provided initial parameters.
108
+
109
+ Parameters
110
+ ----------
111
+ fit_params : lmfit.Parameters, optional
112
+ Initial guesses and bounds for the fit. If None, sensible defaults
113
+ are created.
114
+ """
115
+ self.fit_func = self.__class__._cosinor
116
+ self.fit_obj_func = self.__class__._residual
117
+
118
+ if fit_params is None:
119
+ fit_params = Parameters()
120
+ # Default parameters for the cosinor fit function
121
+ fit_params.add('Amplitude', value=50, min=0)
122
+ fit_params.add('Acrophase', value=np.pi, min=0, max=2*np.pi)
123
+ fit_params.add('Period', value=1440, min=0)
124
+ fit_params.add('Mesor', value=50, min=0)
125
+ self.fit_initial_params = fit_params
126
+
127
+ # ----------------------------
128
+ # Time handling
129
+ # ----------------------------
130
+
131
+ @staticmethod
132
+ def _convert_timestamp_to_index(data):
133
+ """Convert timestamps"""
134
+ # Define the x range by converting timestamps to indices, in order to
135
+ # deal with time series with irregular index.
136
+ return ((data.index - data.index[0]) / data.index.freq).values
137
+
138
+ def fit(
139
+ self,
140
+ data,
141
+ params=None,
142
+ method='leastsq',
143
+ nan_policy='raise',
144
+ reduce_fcn=None,
145
+ verbose=False
146
+ ):
147
+ """
148
+ Fit the actigraphy data using a cosinor function.
149
+
150
+ Parameters
151
+ ----------
152
+ data : pandas.Series
153
+ Input time series.
154
+ params: instance of Parameters [1]_, optional.
155
+ Initial fit parameters. If None, use the default parameters.
156
+ Default is None.
157
+ method: str, optional
158
+ Name of the fitting method to use [1]_.
159
+ Default is 'leastsq'.
160
+ nan_policy: str, optional
161
+ Specifies action if the objective function returns NaN values.
162
+ One of:
163
+
164
+ * 'raise': a ValueError is raised
165
+ * 'propagate': the values returned from userfcn are un-altered
166
+ * 'omit': non-finite values are filtered
167
+
168
+ Default is 'raise'.
169
+ reduce_fcn: str, optional
170
+ Function to convert a residual array to a scalar value for the
171
+ scalar minimizers. Optional values are:
172
+
173
+ * 'None' : sum of squares of residual
174
+ * 'negentropy' : neg entropy, using normal distribution
175
+ * 'neglogcauchy': neg log likelihood, using Cauchy distribution
176
+
177
+ Default is None.
178
+ verbose: bool, optional
179
+ If set to True, display fit informations.
180
+ Default is False.
181
+
182
+ Returns
183
+ -------
184
+ fit_results : MinimizerResult
185
+ Fit results.
186
+
187
+ References
188
+ ----------
189
+ This code is derived from the original implementation in pyActigraphy, distributed under the BSD 3-Clause License.
190
+ Original author: Grégory Hammad (gregory.hammad@uliege.be).
191
+
192
+ [1] Hammad, G., Reyt, M., Beliy, N., Baillet, M., Deantoni, M., Lesoinne, A., Muto, V., & Schmidt, C. (2021).
193
+ pyActigraphy: Open-source python package for actigraphy data visualization and analysis.
194
+ PLoS Computational Biology, 17(10), 1009514–1009535. https://doi.org/10.1371/journal.pcbi.1009514
195
+
196
+ [2] Hammad, G., Wulff, K., Skene, D. J., Münch, M., & Spitschan, M. (2024). Open-Source Python Module for the
197
+ Analysis of Personalized Light Exposure Data from Wearable Light Loggers and Dosimeters.
198
+ LEUKOS, 20(4), 380–389. https://doi.org/10.1080/15502724.2023.2296863
199
+
200
+ [3] Non-Linear Least-Squares Minimization and Curve-Fitting for Python.
201
+ https://lmfit.github.io/lmfit-py/index.html
202
+ """
203
+
204
+ # Define the x range by converting timestamps to indices, in order to
205
+ # deal with time series with irregular index.
206
+ x = self._convert_timestamp_to_index(data)
207
+
208
+ # Minimize residuals
209
+ fit_results = minimize(
210
+ self.fit_obj_func,
211
+ self.fit_initial_params if params is None else params,
212
+ method=method,
213
+ args=(x, data.values, self.fit_func),
214
+ nan_policy=nan_policy,
215
+ reduce_fcn=reduce_fcn
216
+ )
217
+ # Print fit parameters if verbose
218
+ if verbose:
219
+ print(fit_report(fit_results))
220
+
221
+ return fit_results
222
+
223
+ def best_fit(self, data, params):
224
+ """
225
+ Best fit function of the data.
226
+
227
+ Parameters
228
+ ----------
229
+ data : pandas.Series
230
+ Originally fitted time series.
231
+ params: instance of Parameters [1]_
232
+ Best fit parameters.
233
+
234
+ Returns
235
+ -------
236
+ bestfit_data : pandas.Series
237
+ Time series of the best fit data.
238
+
239
+ References
240
+ ----------
241
+ This code is derived from the original implementation in pyActigraphy, distributed under the BSD 3-Clause License.
242
+ Original author: Grégory Hammad (gregory.hammad@uliege.be).
243
+
244
+ [1] Hammad, G., Reyt, M., Beliy, N., Baillet, M., Deantoni, M., Lesoinne, A., Muto, V., & Schmidt, C. (2021).
245
+ pyActigraphy: Open-source python package for actigraphy data visualization and analysis.
246
+ PLoS Computational Biology, 17(10), 1009514–1009535. https://doi.org/10.1371/journal.pcbi.1009514
247
+
248
+ [2] Hammad, G., Wulff, K., Skene, D. J., Münch, M., & Spitschan, M. (2024). Open-Source Python Module for the
249
+ Analysis of Personalized Light Exposure Data from Wearable Light Loggers and Dosimeters.
250
+ LEUKOS, 20(4), 380–389. https://doi.org/10.1080/15502724.2023.2296863
251
+
252
+ [3] Non-Linear Least-Squares Minimization and Curve-Fitting for Python.
253
+ https://lmfit.github.io/lmfit-py/index.html
254
+ """
255
+ # Define the x range by converting timestamps to indices, in order to
256
+ # deal with time series with irregular index.
257
+ x = self._convert_timestamp_to_index(data)
258
+ y = self.fit_func(x, params)
259
+ return pd.Series(index=data.index, data=y)
260
+
261
+ def plot(self, data, best_params):
262
+ layout = go.Layout(
263
+ title="Cosinor",
264
+ xaxis=dict(title="Date time"),
265
+ yaxis=dict(title="Counts/period"),
266
+ showlegend=False
267
+ )
268
+
269
+ fig = go.Figure(
270
+ data=[
271
+ go.Scatter(x=data.index.astype(str),
272
+ y=data, name='Raw data'),
273
+ go.Scatter(x=self.best_fit(data, best_params).index.astype(str),
274
+ y=self.best_fit(data, best_params),
275
+ name='Best fit')
276
+ ], layout=layout,
277
+ )
278
+ return fig
@@ -0,0 +1,3 @@
1
+ from .flm import FLM
2
+
3
+ __all__ = ['FLM']