actirhythm-toolkit 0.1.0__tar.gz

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 (28) hide show
  1. actirhythm_toolkit-0.1.0/PKG-INFO +477 -0
  2. actirhythm_toolkit-0.1.0/README.md +417 -0
  3. actirhythm_toolkit-0.1.0/actirhythm_toolkit.egg-info/PKG-INFO +477 -0
  4. actirhythm_toolkit-0.1.0/actirhythm_toolkit.egg-info/SOURCES.txt +26 -0
  5. actirhythm_toolkit-0.1.0/actirhythm_toolkit.egg-info/dependency_links.txt +1 -0
  6. actirhythm_toolkit-0.1.0/actirhythm_toolkit.egg-info/entry_points.txt +2 -0
  7. actirhythm_toolkit-0.1.0/actirhythm_toolkit.egg-info/requires.txt +33 -0
  8. actirhythm_toolkit-0.1.0/actirhythm_toolkit.egg-info/top_level.txt +3 -0
  9. actirhythm_toolkit-0.1.0/improved_pipeline.py +416 -0
  10. actirhythm_toolkit-0.1.0/pyproject.toml +3 -0
  11. actirhythm_toolkit-0.1.0/run_updated_analysis.py +811 -0
  12. actirhythm_toolkit-0.1.0/setup.cfg +4 -0
  13. actirhythm_toolkit-0.1.0/setup.py +72 -0
  14. actirhythm_toolkit-0.1.0/src/__init__.py +25 -0
  15. actirhythm_toolkit-0.1.0/src/cli.py +149 -0
  16. actirhythm_toolkit-0.1.0/src/config.py +203 -0
  17. actirhythm_toolkit-0.1.0/src/cosinor.py +660 -0
  18. actirhythm_toolkit-0.1.0/src/doctor.py +65 -0
  19. actirhythm_toolkit-0.1.0/src/effects.py +563 -0
  20. actirhythm_toolkit-0.1.0/src/eval.py +296 -0
  21. actirhythm_toolkit-0.1.0/src/features.py +672 -0
  22. actirhythm_toolkit-0.1.0/src/io.py +420 -0
  23. actirhythm_toolkit-0.1.0/src/logging_config.py +78 -0
  24. actirhythm_toolkit-0.1.0/src/models_hmm.py +741 -0
  25. actirhythm_toolkit-0.1.0/src/qc.py +215 -0
  26. actirhythm_toolkit-0.1.0/src/workflows.py +228 -0
  27. actirhythm_toolkit-0.1.0/tests/test_cli.py +134 -0
  28. actirhythm_toolkit-0.1.0/tests/test_effects.py +26 -0
@@ -0,0 +1,477 @@
1
+ Metadata-Version: 2.4
2
+ Name: actirhythm-toolkit
3
+ Version: 0.1.0
4
+ Summary: Reproducible accelerometer analysis pipeline for circadian and behavioral rhythm studies
5
+ Home-page: https://github.com/nerminjukan/masters-thesis
6
+ Author: Nermin Jukan
7
+ License: MIT
8
+ Project-URL: Source, https://github.com/nerminjukan/masters-thesis
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
17
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
18
+ Requires-Python: >=3.8
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: numpy>=1.21.0
21
+ Requires-Dist: pandas>=1.3.0
22
+ Requires-Dist: scipy>=1.7.0
23
+ Requires-Dist: pyarrow>=5.0.0
24
+ Requires-Dist: matplotlib>=3.4.0
25
+ Requires-Dist: seaborn>=0.11.0
26
+ Requires-Dist: statsmodels>=0.13.0
27
+ Requires-Dist: scikit-learn>=1.0.0
28
+ Requires-Dist: hmmlearn>=0.2.7
29
+ Requires-Dist: pyyaml>=5.4.0
30
+ Requires-Dist: loguru>=0.5.3
31
+ Provides-Extra: ml
32
+ Requires-Dist: xgboost>=1.5.0; extra == "ml"
33
+ Requires-Dist: pomegranate>=0.14.8; extra == "ml"
34
+ Requires-Dist: CosinorPy>=1.1; extra == "ml"
35
+ Provides-Extra: glmm
36
+ Requires-Dist: pymer4>=0.7.0; extra == "glmm"
37
+ Requires-Dist: polars>=1.0.0; extra == "glmm"
38
+ Requires-Dist: rpy2>=3.6.0; extra == "glmm"
39
+ Requires-Dist: great-tables>=0.23.0; extra == "glmm"
40
+ Provides-Extra: notebooks
41
+ Requires-Dist: jupyter>=1.0.0; extra == "notebooks"
42
+ Requires-Dist: ipykernel>=6.0.0; extra == "notebooks"
43
+ Requires-Dist: nbformat>=5.1.0; extra == "notebooks"
44
+ Requires-Dist: tqdm>=4.62.0; extra == "notebooks"
45
+ Provides-Extra: dev
46
+ Requires-Dist: pytest>=6.2.0; extra == "dev"
47
+ Requires-Dist: pytest-cov>=3.0.0; extra == "dev"
48
+ Requires-Dist: python-dotenv>=0.19.0; extra == "dev"
49
+ Dynamic: author
50
+ Dynamic: classifier
51
+ Dynamic: description
52
+ Dynamic: description-content-type
53
+ Dynamic: home-page
54
+ Dynamic: license
55
+ Dynamic: project-url
56
+ Dynamic: provides-extra
57
+ Dynamic: requires-dist
58
+ Dynamic: requires-python
59
+ Dynamic: summary
60
+
61
+ # Masters Thesis Analysis Pipeline
62
+
63
+ A reproducible Python-based data analysis pipeline for thesis research, focusing on time series analysis, hidden Markov models, cosinor analysis, and machine learning.
64
+
65
+ **Designed for accelerometer data analysis** with support for 3-axis accelerometer readings and activity metrics.
66
+
67
+ ## ⚠️ Important: Methodological Corrections
68
+
69
+ **This pipeline has been updated with critical methodological corrections** for biological and statistical validity. If you're using this for animal activity rhythm analysis:
70
+
71
+ 1. **READ FIRST**: [`METHODOLOGY_CORRECTIONS.md`](METHODOLOGY_CORRECTIONS.md) - Detailed explanation of all corrections
72
+ 2. **QUICK START**: [`QUICK_START.md`](QUICK_START.md) - Quick reference guide for the corrected pipeline
73
+
74
+ ### Key Corrections Implemented
75
+ - ✅ Feature standardization to prevent HMM state flickering
76
+ - ✅ Biological state validation (replaces unreliable AIC/BIC selection)
77
+ - ✅ Minimum dwell-time filtering for realistic behavioral dynamics
78
+ - ✅ State-based cosinor analysis (correct approach - applied AFTER state identification)
79
+ - ✅ Per-individual feature computation for multi-subject studies
80
+ - ✅ Complete documentation of methodological choices
81
+
82
+ **Previous pipeline order (incorrect):** Raw → Features → Cosinor → HMM
83
+ **Corrected pipeline order:** Raw → Features → Standardization → HMM → Dwell-time Filter → Biological Validation → State-Based Cosinor
84
+
85
+ See [`METHODOLOGY_CORRECTIONS.md`](METHODOLOGY_CORRECTIONS.md) for full details.
86
+
87
+ ---
88
+
89
+ ## Data Format
90
+
91
+ The pipeline is configured to work with accelerometer data in CSV format with the following columns:
92
+
93
+ - **ActMindata**: Tag-derived activity metric (PRIMARY ACTIVITY SIGNAL)
94
+ - **XAccel, YAccel, ZAccel**: 3-axis accelerometer readings (UNSIGNED RELATIVE VALUES, 0-255)
95
+ - **PostChg**: Posture change indicator
96
+ - **PostCt**: Posture count
97
+ - **ACTEndTimeAllS**: Timestamp of the reading (e.g., "7/8/23 10:46")
98
+ - **serial**: Device serial number
99
+ - **subject**: Subject identifier
100
+
101
+ ### IMPORTANT: Accelerometer Data Assumptions
102
+
103
+ **CRITICAL**: XAccel/YAccel/ZAccel are **UNSIGNED RELATIVE VALUES** (typically 0-255), NOT calibrated acceleration in physical units.
104
+
105
+ **What this means**:
106
+ - Absolute axis values encode device orientation + gravity (NOT activity intensity)
107
+ - DO NOT compute VeDBA, ODBA, or raw magnitude: `sqrt(X² + Y² + Z²)` is INCORRECT
108
+ - DO NOT square or directly combine axes assuming zero-centered data
109
+ - USE ActMindata as your primary activity signal (validated by tag manufacturer)
110
+ - DERIVE relative movement features from axes (variance, std, absolute differences)
111
+
112
+ **Correct workflow**:
113
+ ```python
114
+ # CORRECT: Use ActMindata as primary signal
115
+ df['activity'] = df['ActMindata']
116
+
117
+ # CORRECT: Add relative movement features from axes
118
+ df = features.add_accelerometer_movement_features(df, subject_column='subject')
119
+
120
+ # INCORRECT: Do not compute magnitude from unsigned axes
121
+ # df['activity'] = sqrt(XAccel² + YAccel² + ZAccel²) # WRONG!
122
+ ```
123
+
124
+ A sample dataset is provided in `data/raw/sample_accelerometer_data.csv`.
125
+
126
+ ## Project Structure
127
+
128
+ ```
129
+ masters-thesis/
130
+ ├── data/
131
+ │ ├── raw/ # Raw data files (not committed to git)
132
+ │ └── processed/ # Processed data files (not committed to git)
133
+ ├── notebooks/ # Jupyter notebooks for analysis
134
+ │ ├── 00_intake.ipynb # Data intake
135
+ │ ├── 01_qc_eda.ipynb # Quality control and EDA
136
+ │ ├── 02_features.ipynb # Feature engineering (⚠️ WITH STANDARDIZATION)
137
+ │ ├── 03_hmm_hsmm.ipynb # HMM/HSMM modeling (⚠️ BIOLOGICAL VALIDATION)
138
+ │ ├── 04_cosinor.ipynb # Cosinor analysis (⚠️ STATE-BASED)
139
+ │ └── 05_glmm_ml.ipynb # GLMM and ML models
140
+ ├── src/ # Source code modules
141
+ │ ├── __init__.py
142
+ │ ├── io.py # Data I/O functions
143
+ │ ├── qc.py # Quality control
144
+ │ ├── features.py # Feature engineering (⚠️ NEW: standardization, log transform)
145
+ │ ├── models_hmm.py # HMM/HSMM (⚠️ NEW: dwell-time filter, biological validation)
146
+ │ ├── cosinor.py # Cosinor analysis (⚠️ NEW: state-based methods)
147
+ │ ├── effects.py # GLMM and ML models
148
+ │ └── eval.py # Evaluation utilities
149
+ ├── outputs/ # Generated outputs (plots, results)
150
+ ├── logs/ # Log files
151
+ ├── docs/ # Documentation
152
+ ├── METHODOLOGY_CORRECTIONS.md # ⚠️ CRITICAL: Read this for methodological details
153
+ ├── QUICK_START.md # Quick reference guide
154
+ ├── requirements.txt # Python dependencies
155
+ ├── setup.py # Package setup
156
+ └── README.md # This file
157
+ ```
158
+
159
+ ⚠️ = Contains critical methodological corrections
160
+
161
+ ## Features
162
+
163
+ ### Reproducible Pipeline
164
+
165
+ The pipeline implements the following workflow:
166
+
167
+ 1. **Data Intake** (`00_intake.ipynb`)
168
+ - Load accelerometer data from CSV files
169
+ - Use ActMindata as primary activity signal (NOT magnitude from axes)
170
+ - Parse timestamps
171
+ - Initial data exploration
172
+ - Logging of parameters and random seeds
173
+
174
+ 2. **Quality Control** (`01_qc_eda.ipynb`)
175
+ - Detection of missing values
176
+ - Detection and removal of duplicates
177
+ - Time gap analysis
178
+ - Exploratory data analysis with visualizations
179
+
180
+ 3. **Feature Engineering** (`02_features.ipynb`)
181
+ - Use ActMindata as primary activity signal (NOT axis magnitude)
182
+ - Add relative movement features from accelerometer axes (variance, std, changes)
183
+ - Rolling statistics (mean, std, min, max) per individual
184
+ - Time-based features (hour, day of week, etc.)
185
+ - Log transformation and z-score standardization per individual
186
+ - Lag and difference features
187
+
188
+ 4. **HMM/HSMM Analysis** (`03_hmm_hsmm.ipynb`)
189
+ - Input: ActMin + relative movement features (standardized)
190
+ - Gaussian Hidden Markov Models with K=2..5 states
191
+ - Minimum dwell-time filtering to prevent state flickering
192
+ - Biological state validation (not just IC-based selection)
193
+ - State labeling and interpretation
194
+ - State sequence prediction (Viterbi algorithm)
195
+ - Posterior probability estimation
196
+
197
+ 5. **Cosinor Analysis** (`04_cosinor.ipynb`)
198
+ - Applied AFTER behavioral state identification (CORRECT approach)
199
+ - State-based cosinor: probability of active states
200
+ - Per-state cosinor: state-conditioned activity rhythms
201
+ - MESOR (mean level) estimation per state
202
+ - Amplitude and acrophase extraction per state
203
+ - Multi-period analysis
204
+ - Statistical significance testing
205
+
206
+ 6. **GLMM and Machine Learning** (`05_glmm_ml.ipynb`)
207
+ - Generalized Linear Mixed Models (GLMM)
208
+ - Random Forest regression/classification
209
+ - XGBoost models
210
+ - Model comparison and evaluation
211
+ - Feature importance analysis
212
+
213
+ ### Key Modules
214
+
215
+ - **io.py**: Functions for loading and saving data in multiple formats
216
+ - `load_accelerometer_data()`: Load accelerometer CSV data with format validation
217
+ - `load_raw_data()`: Generic loader for CSV, Excel, Parquet, JSON, Feather
218
+ - `save_processed_data()`: Save processed data
219
+ - **qc.py**: Quality control checks (gaps, duplicates, validation)
220
+ - **features.py**: Feature engineering utilities
221
+ - `add_accelerometer_movement_features()`: Compute relative movement features (variance, std, changes) from XAccel/YAccel/ZAccel
222
+ - `add_rolling_statistics_per_individual()`: Rolling window features per subject
223
+ - `standardize_features()`: Z-score normalization per individual (CRITICAL for HMM)
224
+ - `log_transform_activity()`: Log transform for count data
225
+ - `add_time_features()`: Extract time-based features
226
+ - ~~`calculate_accelerometer_activity()`~~: DEPRECATED - do not use for unsigned axes
227
+ - **models_hmm.py**: HMM/HSMM implementation with model selection
228
+ - `fit_hmm_pipeline()`: Complete HMM workflow
229
+ - `apply_minimum_dwell_time()`: Post-process to prevent state flickering
230
+ - `analyze_state_characteristics()`: Biological validation of states
231
+ - `select_states_biologically()`: State selection based on interpretability
232
+ - **cosinor.py**: Cosinor analysis for circadian rhythms
233
+ - `fit_cosinor_per_state()`: State-based cosinor (CORRECT approach)
234
+ - `fit_cosinor_per_individual_per_state()`: Per-individual state-based analysis
235
+ - `fit_cosinor()`: Basic cosinor fitting
236
+ - **effects.py**: Mixed effects models and machine learning
237
+ - **eval.py**: Evaluation metrics and visualization utilities
238
+
239
+ ## Installation
240
+
241
+ 1. Clone the repository:
242
+ ```bash
243
+ git clone https://github.com/nerminjukan/masters-thesis.git
244
+ cd masters-thesis
245
+ ```
246
+
247
+ 2. Create a virtual environment:
248
+ ```bash
249
+ python -m venv venv
250
+ source venv/bin/activate # On Windows: venv\Scripts\activate
251
+ ```
252
+
253
+ 3. Install dependencies:
254
+ ```bash
255
+ pip install -r requirements.txt
256
+ ```
257
+
258
+ Or install as a package:
259
+ ```bash
260
+ pip install -e .
261
+ ```
262
+
263
+ Optional extras:
264
+
265
+ ```bash
266
+ pip install -e .[dev]
267
+ pip install -e .[notebooks]
268
+ pip install -e .[ml]
269
+ pip install -e .[glmm]
270
+ ```
271
+
272
+ Validated packaging states:
273
+
274
+ ```bash
275
+ # Base CLI/runtime only
276
+ pip install -e .
277
+
278
+ # Add optional machine-learning/research extras
279
+ pip install -e .[ml]
280
+
281
+ # Add GLMM support used by optional pymer4 workflows
282
+ pip install -e .[glmm]
283
+ ```
284
+
285
+ GLMM note:
286
+
287
+ ```text
288
+ The Python extra installs the pymer4-side Python dependencies, but a working R installation
289
+ and required R packages are still needed for pymer4-backed models. In a clean Windows test
290
+ environment, pymer4 additionally required R packages such as tibble.
291
+ ```
292
+
293
+ You can diagnose the GLMM environment with:
294
+
295
+ ```bash
296
+ actirhythm glmm-doctor
297
+ ```
298
+
299
+ ### Run as an Installed Package (CLI)
300
+
301
+ After installation, run the full workflow from the project root with a single command:
302
+
303
+ ```bash
304
+ actirhythm
305
+ ```
306
+
307
+ Equivalent explicit commands:
308
+
309
+ ```bash
310
+ actirhythm full --run-version v3
311
+ actirhythm run --run-version v3
312
+ ```
313
+
314
+ Run stages separately:
315
+
316
+ ```bash
317
+ actirhythm preprocess --run-version v3
318
+ actirhythm analytics --run-version v3
319
+ ```
320
+
321
+ Advanced options:
322
+
323
+ ```bash
324
+ # Show what will run and where outputs will go (no execution)
325
+ actirhythm full --run-version v4 --dry-run
326
+
327
+ # Resume safely: skip stages whose expected outputs already exist
328
+ actirhythm full --run-version v4 --skip-existing
329
+
330
+ # Override input/output locations
331
+ actirhythm preprocess \
332
+ --data-revised-dir ./my-revised-data \
333
+ --config ./config.yaml \
334
+ --raw-data-file ./data/raw/fallback.csv \
335
+ --processed-base-dir ./custom-processed \
336
+ --output-base-dir ./custom-runs \
337
+ --run-version experiment-01
338
+
339
+ # Run analytics from an explicit HMM parquet file
340
+ actirhythm analytics \
341
+ --hmm-input-file ./custom-processed/experiment-01/hmm_results_improved.parquet \
342
+ --output-base-dir ./custom-runs \
343
+ --run-version experiment-01
344
+
345
+ # Use a non-default config file
346
+ actirhythm full --project-root /path/to/masters-thesis --config ./config.custom.yaml --dry-run
347
+
348
+ # Check optional GLMM prerequisites on the current machine
349
+ actirhythm glmm-doctor
350
+ ```
351
+
352
+ Release validation:
353
+
354
+ ```bash
355
+ python -m build
356
+ python -m twine check dist/*
357
+ ```
358
+
359
+ Run from another folder by passing the project root:
360
+
361
+ ```bash
362
+ actirhythm full --project-root /path/to/masters-thesis --run-version v3
363
+ ```
364
+
365
+ ## Usage
366
+
367
+ ### Running the Pipeline
368
+
369
+ Execute notebooks in sequence:
370
+
371
+ ```bash
372
+ cd notebooks
373
+ jupyter notebook
374
+ ```
375
+
376
+ Run notebooks in order (00 → 01 → 02 → 03 → 04 → 05).
377
+
378
+ ### Using Modules in Code
379
+
380
+ ```python
381
+ from src import io, qc, features, models_hmm, cosinor, effects, eval
382
+
383
+ # Load accelerometer data
384
+ df = io.load_accelerometer_data('data/raw/sample_accelerometer_data.csv')
385
+
386
+ # CORRECT: Use ActMindata as primary activity signal
387
+ df['activity'] = df['ActMindata']
388
+
389
+ # CORRECT: Add relative movement features from accelerometer axes
390
+ # These capture variance and changes, NOT absolute magnitude
391
+ df = features.add_accelerometer_movement_features(
392
+ df,
393
+ subject_column='subject',
394
+ windows=[6, 12, 24],
395
+ standardize=True
396
+ )
397
+
398
+ # Quality control
399
+ qc_report = qc.qc_report(df, time_column='timestamp')
400
+
401
+ # Feature engineering - use ActMin, NOT magnitude
402
+ df_features = features.add_rolling_statistics_per_individual(
403
+ df,
404
+ 'activity', # ActMin
405
+ subject_column='subject',
406
+ windows=[6, 12, 24]
407
+ )
408
+ df_features = features.add_time_features(df_features, 'timestamp')
409
+
410
+ # Standardize features before HMM (CRITICAL)
411
+ df_features = features.log_transform_activity(df_features, 'activity', offset=1.0)
412
+ df_features = features.standardize_features(
413
+ df_features,
414
+ ['activity_log'],
415
+ group_by='subject'
416
+ )
417
+
418
+ # HMM analysis with standardized features
419
+ feature_cols = ['activity_log_standardized']
420
+ # Add standardized movement features
421
+ movement_features = [col for col in df_features.columns if 'movement_var' in col and '_standardized' in col]
422
+ feature_cols.extend(movement_features[:3])
423
+
424
+ X = df_features[feature_cols].dropna().values
425
+ hmm_results = models_hmm.fit_hmm_pipeline(X, state_range=range(2, 6))
426
+
427
+ # Apply dwell-time filter
428
+ states_filtered = models_hmm.apply_minimum_dwell_time(
429
+ hmm_results['states'],
430
+ min_dwell=4
431
+ )
432
+
433
+ # State-based cosinor (CORRECT - applied AFTER state identification)
434
+ df_with_states = df.copy()
435
+ df_with_states['hmm_state'] = states_filtered
436
+ cosinor_results = cosinor.fit_cosinor_per_state(
437
+ df_with_states,
438
+ time_column='timestamp',
439
+ state_column='hmm_state',
440
+ activity_column='activity'
441
+ )
442
+
443
+ # Machine learning
444
+ rf_results = effects.fit_random_forest(X_train, y_train, X_test, y_test)
445
+ ```
446
+
447
+ ## Reproducibility
448
+
449
+ All analyses use fixed random seeds (default: 42) for reproducibility. Parameters and seeds are logged in each notebook for full traceability.
450
+
451
+ ## Dependencies
452
+
453
+ Core dependencies:
454
+ - numpy, pandas, scipy
455
+ - matplotlib, seaborn
456
+ - scikit-learn, xgboost
457
+ - hmmlearn, pomegranate
458
+ - statsmodels, pymer4
459
+ - jupyter, loguru
460
+
461
+ See `requirements.txt` for complete list.
462
+
463
+ ## Contributing
464
+
465
+ This is a thesis project. For questions or suggestions, please open an issue.
466
+
467
+ ## License
468
+
469
+ This project is part of a master's thesis research.
470
+
471
+ ## Author
472
+
473
+ Masters Thesis Author
474
+
475
+ ## Citation
476
+
477
+ If you use this pipeline in your research, please cite appropriately.