ethoscopy 2.0__tar.gz → 2.0.3__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.
- ethoscopy-2.0.3/.claude/settings.local.json +25 -0
- ethoscopy-2.0.3/.codecov.yml +26 -0
- ethoscopy-2.0.3/.github/workflows/ci.yml +151 -0
- ethoscopy-2.0.3/.github/workflows/release.yml +74 -0
- ethoscopy-2.0.3/.gitignore +11 -0
- ethoscopy-2.0.3/.pre-commit-config.yaml +62 -0
- ethoscopy-2.0.3/CLAUDE.md +111 -0
- ethoscopy-2.0.3/Docker/.claude/settings.local.json +19 -0
- ethoscopy-2.0.3/Docker/.env +39 -0
- ethoscopy-2.0.3/Docker/.env.keycloak +39 -0
- ethoscopy-2.0.3/Docker/Dockerfile +108 -0
- ethoscopy-2.0.3/Docker/README.md +85 -0
- ethoscopy-2.0.3/Docker/config/jupyterhub.sqlite +0 -0
- ethoscopy-2.0.3/Docker/config/jupyterhub_cookie_secret +1 -0
- ethoscopy-2.0.3/Docker/docker-compose.yml +25 -0
- ethoscopy-2.0.3/Docker/install_r_packages.r +75 -0
- ethoscopy-2.0.3/Docker/jupyterhub_data/jupyterhub-proxy.pid +1 -0
- ethoscopy-2.0.3/Docker/jupyterhub_data/jupyterhub.sqlite +0 -0
- ethoscopy-2.0.3/Docker/jupyterhub_data/jupyterhub_config.py +54 -0
- ethoscopy-2.0.3/Docker/jupyterhub_data/jupyterhub_cookie_secret +1 -0
- ethoscopy-2.0/README.md → ethoscopy-2.0.3/PKG-INFO +92 -4
- ethoscopy-2.0.3/QWEN.md +88 -0
- ethoscopy-2.0/PKG-INFO → ethoscopy-2.0.3/README.md +52 -29
- ethoscopy-2.0.3/TESTING.md +275 -0
- ethoscopy-2.0.3/_config.yml +1 -0
- ethoscopy-2.0.3/pyproject.toml +63 -0
- ethoscopy-2.0.3/pytest.ini +22 -0
- ethoscopy-2.0.3/run_tests.py +76 -0
- ethoscopy-2.0.3/setup.py +39 -0
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/__init__.py +20 -20
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/analyse.py +318 -242
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/behavpy.py +31 -15
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/behavpy_HMM_class.py +24 -14
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/behavpy_class.py +24 -14
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/behavpy_core.py +1152 -642
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/behavpy_draw.py +1162 -531
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/behavpy_periodogram_class.py +24 -14
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/behavpy_plotly.py +2527 -1230
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/behavpy_seaborn.py +1881 -704
- ethoscopy-2.0.3/src/ethoscopy/load.py +954 -0
- ethoscopy-2.0.3/src/ethoscopy/metadata_db.py +422 -0
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/misc/circadian_bars.py +58 -32
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/misc/general_functions.py +41 -33
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/misc/get_HMM.py +9 -9
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/misc/get_tutorials.py +15 -11
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/misc/hmm_functions.py +43 -38
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/misc/periodogram_functions.py +139 -99
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/misc/validate_datetime.py +16 -11
- ethoscopy-2.0.3/tests/__init__.py +3 -0
- ethoscopy-2.0.3/tests/conftest.py +247 -0
- ethoscopy-2.0.3/tests/data/README.md +13 -0
- ethoscopy-2.0.3/tests/data/test_ethoscope.db +0 -0
- ethoscopy-2.0.3/tests/test_analyse.py +438 -0
- ethoscopy-2.0.3/tests/test_baseline_enhancements.py +452 -0
- ethoscopy-2.0.3/tests/test_behavpy.py +408 -0
- ethoscopy-2.0.3/tests/test_behavpy_core_simple.py +298 -0
- ethoscopy-2.0.3/tests/test_compatibility_classes.py +285 -0
- ethoscopy-2.0.3/tests/test_general_functions.py +135 -0
- ethoscopy-2.0.3/tests/test_get_tutorials.py +136 -0
- ethoscopy-2.0.3/tests/test_load.py +431 -0
- ethoscopy-2.0.3/tests/test_load_comprehensive.py +782 -0
- ethoscopy-2.0.3/tests/test_load_optimizations.py +635 -0
- ethoscopy-2.0.3/tutorial_notebook/1_Overview_tutorial.ipynb +1837 -0
- ethoscopy-2.0.3/tutorial_notebook/2_HMM_tutorial.ipynb +827 -0
- ethoscopy-2.0.3/tutorial_notebook/3_Circadian_tutorial.ipynb +1766 -0
- ethoscopy-2.0.3/tutorial_notebook/4_Navigating_db_tutorial.ipynb +415 -0
- ethoscopy-2.0.3/tutorial_notebook/5_Ethoscopy_catch22_tutorial.ipynb +1149 -0
- ethoscopy-2.0.3/tutorial_notebook/6_Ethoscopy_to_hctsa_tutorial.ipynb +468 -0
- ethoscopy-2.0.3/tutorial_notebook/ethoscope_db.csv +16801 -0
- ethoscopy-2.0.3/tutorial_notebook/jones_et_al_metadata.csv +8721 -0
- ethoscopy-2.0.3/tutorial_notebook/notebook_paper.ipynb +206 -0
- ethoscopy-2.0/pyproject.toml +0 -28
- ethoscopy-2.0/src/ethoscopy/load.py +0 -551
- ethoscopy-2.0/src/ethoscopy/metadata_db.py +0 -380
- ethoscopy-2.0/src/ethoscopy/misc/tutorial_data/4_states_F_WT.pkl +0 -0
- ethoscopy-2.0/src/ethoscopy/misc/tutorial_data/4_states_M_WT.pkl +0 -0
- ethoscopy-2.0/src/ethoscopy/misc/tutorial_data/circadian_data.pkl +0 -0
- ethoscopy-2.0/src/ethoscopy/misc/tutorial_data/circadian_meta.pkl +0 -0
- ethoscopy-2.0/src/ethoscopy/misc/tutorial_data/overview_data.pkl +0 -0
- ethoscopy-2.0/src/ethoscopy/misc/tutorial_data/overview_meta.pkl +0 -0
- {ethoscopy-2.0 → ethoscopy-2.0.3}/LICENSE +0 -0
- {ethoscopy-2.0 → ethoscopy-2.0.3}/src/ethoscopy/misc/__init__.py +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(git add:*)",
|
|
5
|
+
"Bash(git commit:*)",
|
|
6
|
+
"Bash(python:*)",
|
|
7
|
+
"Bash(ls:*)",
|
|
8
|
+
"Bash(find:*)",
|
|
9
|
+
"Bash(docker exec ethoscope-lab ls -la \"/mnt/ethoscope_results/26634d78becf48628fe5d9ffc67fae04/ETHOSCOPE_266/2025-07-29_19-12-16/2025-07-29_19-12-16_26634d78becf48628fe5d9ffc67fae04.db\")",
|
|
10
|
+
"Bash(docker exec:*)",
|
|
11
|
+
"Bash(source:*)",
|
|
12
|
+
"Bash(git push:*)",
|
|
13
|
+
"Bash(mkdir:*)",
|
|
14
|
+
"Bash(cp:*)",
|
|
15
|
+
"Bash(sqlite3:*)",
|
|
16
|
+
"Bash(black:*)",
|
|
17
|
+
"Bash(grep:*)",
|
|
18
|
+
"Bash(pip install:*)",
|
|
19
|
+
"Bash(git stash pop:*)",
|
|
20
|
+
"Bash(git checkout:*)",
|
|
21
|
+
"Bash(git tag:*)"
|
|
22
|
+
],
|
|
23
|
+
"deny": []
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
coverage:
|
|
2
|
+
range: 50..90
|
|
3
|
+
round: down
|
|
4
|
+
precision: 2
|
|
5
|
+
|
|
6
|
+
status:
|
|
7
|
+
project:
|
|
8
|
+
default:
|
|
9
|
+
target: auto
|
|
10
|
+
threshold: 1%
|
|
11
|
+
base: auto
|
|
12
|
+
patch:
|
|
13
|
+
default:
|
|
14
|
+
target: auto
|
|
15
|
+
threshold: 1%
|
|
16
|
+
base: auto
|
|
17
|
+
|
|
18
|
+
comment:
|
|
19
|
+
layout: "reach, diff, flags, files"
|
|
20
|
+
behavior: default
|
|
21
|
+
|
|
22
|
+
ignore:
|
|
23
|
+
- "tests/"
|
|
24
|
+
- "tutorial_notebook/"
|
|
25
|
+
- "setup.py"
|
|
26
|
+
- "run_tests.py"
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
name: CI/CD Pipeline
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, develop ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
schedule:
|
|
9
|
+
# Run tests daily at 6 AM UTC
|
|
10
|
+
- cron: '0 6 * * *'
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ['3.10', '3.11', '3.12']
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
23
|
+
uses: actions/setup-python@v4
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- name: Cache pip dependencies
|
|
28
|
+
uses: actions/cache@v3
|
|
29
|
+
with:
|
|
30
|
+
path: ~/.cache/pip
|
|
31
|
+
key: ${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }}
|
|
32
|
+
restore-keys: |
|
|
33
|
+
${{ runner.os }}-pip-
|
|
34
|
+
|
|
35
|
+
- name: Install dependencies
|
|
36
|
+
run: |
|
|
37
|
+
python -m pip install --upgrade pip
|
|
38
|
+
pip install -e ".[dev]"
|
|
39
|
+
pip install pytest-cov pytest-xdist pytest-mock
|
|
40
|
+
|
|
41
|
+
- name: Lint with ruff
|
|
42
|
+
run: |
|
|
43
|
+
pip install ruff
|
|
44
|
+
ruff check src/
|
|
45
|
+
|
|
46
|
+
- name: Format check with black
|
|
47
|
+
run: |
|
|
48
|
+
pip install black
|
|
49
|
+
black --check src/ tests/
|
|
50
|
+
|
|
51
|
+
- name: Run unit tests
|
|
52
|
+
run: |
|
|
53
|
+
python -m pytest tests/ -v --cov=ethoscopy --cov-report=xml --cov-report=term-missing -m "unit"
|
|
54
|
+
|
|
55
|
+
- name: Run integration tests
|
|
56
|
+
run: |
|
|
57
|
+
python -m pytest tests/ -v -m "integration"
|
|
58
|
+
|
|
59
|
+
- name: Upload coverage reports to Codecov
|
|
60
|
+
uses: codecov/codecov-action@v5
|
|
61
|
+
with:
|
|
62
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
63
|
+
slug: gilestrolab/ethoscopy
|
|
64
|
+
|
|
65
|
+
test-notebooks:
|
|
66
|
+
runs-on: ubuntu-latest
|
|
67
|
+
needs: test
|
|
68
|
+
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v4
|
|
71
|
+
|
|
72
|
+
- name: Set up Python 3.11
|
|
73
|
+
uses: actions/setup-python@v4
|
|
74
|
+
with:
|
|
75
|
+
python-version: '3.11'
|
|
76
|
+
|
|
77
|
+
- name: Install dependencies
|
|
78
|
+
run: |
|
|
79
|
+
python -m pip install --upgrade pip
|
|
80
|
+
pip install -e ".[dev]"
|
|
81
|
+
pip install nbval jupyter
|
|
82
|
+
|
|
83
|
+
- name: Test notebooks
|
|
84
|
+
run: |
|
|
85
|
+
pytest --nbval-lax tutorial_notebook/*.ipynb -v
|
|
86
|
+
continue-on-error: true # Notebooks may fail due to data dependencies
|
|
87
|
+
|
|
88
|
+
build:
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
needs: [test, test-notebooks]
|
|
91
|
+
|
|
92
|
+
steps:
|
|
93
|
+
- uses: actions/checkout@v4
|
|
94
|
+
|
|
95
|
+
- name: Set up Python 3.11
|
|
96
|
+
uses: actions/setup-python@v4
|
|
97
|
+
with:
|
|
98
|
+
python-version: '3.11'
|
|
99
|
+
|
|
100
|
+
- name: Install build dependencies
|
|
101
|
+
run: |
|
|
102
|
+
python -m pip install --upgrade pip
|
|
103
|
+
pip install build twine
|
|
104
|
+
|
|
105
|
+
- name: Build package
|
|
106
|
+
run: |
|
|
107
|
+
python -m build
|
|
108
|
+
|
|
109
|
+
- name: Check package
|
|
110
|
+
run: |
|
|
111
|
+
twine check dist/*
|
|
112
|
+
|
|
113
|
+
- name: Upload build artifacts
|
|
114
|
+
uses: actions/upload-artifact@v4
|
|
115
|
+
with:
|
|
116
|
+
name: dist-files
|
|
117
|
+
path: dist/
|
|
118
|
+
|
|
119
|
+
security-scan:
|
|
120
|
+
runs-on: ubuntu-latest
|
|
121
|
+
|
|
122
|
+
steps:
|
|
123
|
+
- uses: actions/checkout@v4
|
|
124
|
+
|
|
125
|
+
- name: Set up Python 3.11
|
|
126
|
+
uses: actions/setup-python@v4
|
|
127
|
+
with:
|
|
128
|
+
python-version: '3.11'
|
|
129
|
+
|
|
130
|
+
- name: Install dependencies
|
|
131
|
+
run: |
|
|
132
|
+
python -m pip install --upgrade pip
|
|
133
|
+
pip install bandit safety
|
|
134
|
+
|
|
135
|
+
- name: Run security scan with bandit
|
|
136
|
+
run: |
|
|
137
|
+
bandit -r src/ -f json -o bandit-report.json
|
|
138
|
+
continue-on-error: true
|
|
139
|
+
|
|
140
|
+
- name: Run safety check
|
|
141
|
+
run: |
|
|
142
|
+
safety check --json --output safety-report.json
|
|
143
|
+
continue-on-error: true
|
|
144
|
+
|
|
145
|
+
- name: Upload security reports
|
|
146
|
+
uses: actions/upload-artifact@v4
|
|
147
|
+
with:
|
|
148
|
+
name: security-reports
|
|
149
|
+
path: |
|
|
150
|
+
bandit-report.json
|
|
151
|
+
safety-report.json
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: Release to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
push:
|
|
7
|
+
tags:
|
|
8
|
+
- 'v*.*.*'
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ['3.10', '3.11', '3.12']
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
21
|
+
uses: actions/setup-python@v4
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
pip install -e ".[dev]"
|
|
29
|
+
pip install pytest-cov
|
|
30
|
+
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: |
|
|
33
|
+
python -m pytest tests/ -v --cov=ethoscopy -m "not slow"
|
|
34
|
+
|
|
35
|
+
build-and-publish:
|
|
36
|
+
needs: test
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v4
|
|
41
|
+
|
|
42
|
+
- name: Set up Python 3.11
|
|
43
|
+
uses: actions/setup-python@v4
|
|
44
|
+
with:
|
|
45
|
+
python-version: '3.11'
|
|
46
|
+
|
|
47
|
+
- name: Install build dependencies
|
|
48
|
+
run: |
|
|
49
|
+
python -m pip install --upgrade pip
|
|
50
|
+
pip install build twine
|
|
51
|
+
|
|
52
|
+
- name: Build package
|
|
53
|
+
run: |
|
|
54
|
+
python -m build
|
|
55
|
+
|
|
56
|
+
- name: Check package
|
|
57
|
+
run: |
|
|
58
|
+
twine check dist/*
|
|
59
|
+
|
|
60
|
+
- name: Publish to Test PyPI
|
|
61
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
|
62
|
+
env:
|
|
63
|
+
TWINE_USERNAME: __token__
|
|
64
|
+
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
|
|
65
|
+
run: |
|
|
66
|
+
twine upload --repository testpypi dist/*
|
|
67
|
+
|
|
68
|
+
- name: Publish to PyPI
|
|
69
|
+
if: github.event_name == 'release'
|
|
70
|
+
env:
|
|
71
|
+
TWINE_USERNAME: __token__
|
|
72
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
73
|
+
run: |
|
|
74
|
+
twine upload dist/*
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
# General file checks
|
|
3
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
4
|
+
rev: v5.0.0
|
|
5
|
+
hooks:
|
|
6
|
+
- id: trailing-whitespace
|
|
7
|
+
files: \.(py|yml|yaml|md|txt)$
|
|
8
|
+
- id: end-of-file-fixer
|
|
9
|
+
files: \.(py|yml|yaml|md|txt)$
|
|
10
|
+
- id: check-yaml
|
|
11
|
+
- id: check-toml
|
|
12
|
+
- id: check-merge-conflict
|
|
13
|
+
- id: check-added-large-files
|
|
14
|
+
args: ['--maxkb=1000']
|
|
15
|
+
- id: debug-statements
|
|
16
|
+
files: ^(src/|tests/).*\.py$
|
|
17
|
+
- id: check-ast
|
|
18
|
+
files: ^(src/|tests/).*\.py$
|
|
19
|
+
|
|
20
|
+
# Black - Code formatting
|
|
21
|
+
- repo: https://github.com/psf/black
|
|
22
|
+
rev: 24.10.0
|
|
23
|
+
hooks:
|
|
24
|
+
- id: black
|
|
25
|
+
args: [--line-length=88]
|
|
26
|
+
files: ^(src/|tests/).*\.py$
|
|
27
|
+
|
|
28
|
+
# Ruff - Linting and code analysis
|
|
29
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
30
|
+
rev: v0.8.4
|
|
31
|
+
hooks:
|
|
32
|
+
- id: ruff
|
|
33
|
+
args: [--fix, --exit-non-zero-on-fix]
|
|
34
|
+
files: ^src/.*\.py$
|
|
35
|
+
- id: ruff-format
|
|
36
|
+
files: ^(src/|tests/).*\.py$
|
|
37
|
+
|
|
38
|
+
# Import sorting
|
|
39
|
+
- repo: https://github.com/pycqa/isort
|
|
40
|
+
rev: 5.13.2
|
|
41
|
+
hooks:
|
|
42
|
+
- id: isort
|
|
43
|
+
args: [--profile, black, --line-length=88]
|
|
44
|
+
files: ^(src/|tests/).*\.py$
|
|
45
|
+
|
|
46
|
+
- repo: local
|
|
47
|
+
hooks:
|
|
48
|
+
- id: pytest-unit
|
|
49
|
+
name: pytest-unit
|
|
50
|
+
entry: .venv/bin/python -m pytest tests/ -m "unit" -v
|
|
51
|
+
language: system
|
|
52
|
+
pass_filenames: false
|
|
53
|
+
always_run: true
|
|
54
|
+
stages: [commit]
|
|
55
|
+
|
|
56
|
+
- id: pytest-fast
|
|
57
|
+
name: pytest-fast
|
|
58
|
+
entry: .venv/bin/python -m pytest tests/ -m "not slow" -v --tb=short
|
|
59
|
+
language: system
|
|
60
|
+
pass_filenames: false
|
|
61
|
+
always_run: true
|
|
62
|
+
stages: [push]
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
Ethoscopy is a Python data analysis toolbox for behavioral time series data from Ethoscope (Drosophila monitoring system). It's built as a specialized pandas DataFrame subclass that maintains linked metadata and provides analysis/visualization tools for circadian rhythms, sleep patterns, and behavioral states using HMM.
|
|
8
|
+
|
|
9
|
+
## Development Environment
|
|
10
|
+
|
|
11
|
+
### Python Environment
|
|
12
|
+
- **Use Python 3.10+** (project requires >=3.10,<4.0)
|
|
13
|
+
- **Always use virtual environment** (`.venv` as mentioned in user's global instructions)
|
|
14
|
+
- **Install in development mode**: `pip install -e .`
|
|
15
|
+
|
|
16
|
+
### Package Management
|
|
17
|
+
- Uses **pyproject.toml** for modern Python packaging (not setup.py for production)
|
|
18
|
+
- **Hatchling** as build backend
|
|
19
|
+
- **Rye** for dependency management (managed = true in pyproject.toml)
|
|
20
|
+
|
|
21
|
+
### Key Dependencies
|
|
22
|
+
- Core: pandas >=2.2.2, numpy >=2.0.0
|
|
23
|
+
- Visualization: plotly >=5.22.0, seaborn >=0.13.2
|
|
24
|
+
- Analysis: hmmlearn >=0.3.2, astropy >=6.1, pywavelets >=1.6.0
|
|
25
|
+
- Dev: ipykernel for Jupyter notebook support
|
|
26
|
+
|
|
27
|
+
## Build and Development Commands
|
|
28
|
+
|
|
29
|
+
### Installation
|
|
30
|
+
```bash
|
|
31
|
+
# Install in development mode
|
|
32
|
+
pip install -e .
|
|
33
|
+
|
|
34
|
+
# For Jupyter notebook development
|
|
35
|
+
pip install -e ".[dev]"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Testing
|
|
39
|
+
- **No formal test suite found** - project relies on Jupyter notebooks for validation
|
|
40
|
+
- Use the tutorial notebooks in `tutorial_notebook/` for testing functionality
|
|
41
|
+
- Run notebooks: `jupyter notebook tutorial_notebook/`
|
|
42
|
+
|
|
43
|
+
### Docker Environment
|
|
44
|
+
- **Docker available** for JupyterHub deployment
|
|
45
|
+
- Build: `JUPYTER_HUB_TAG=5.3.0 ETHOSCOPE_LAB_TAG=1.0 docker compose build`
|
|
46
|
+
- Run: `docker compose up -d` (from Docker/ directory)
|
|
47
|
+
|
|
48
|
+
## Architecture and Code Structure
|
|
49
|
+
|
|
50
|
+
### Core Architecture
|
|
51
|
+
- **behavpy_core**: Base DataFrame subclass with core functionality (xmv, curate, summary)
|
|
52
|
+
- **behavpy**: Main user-facing class for backward compatibility
|
|
53
|
+
- **Canvas System**: Supports both 'plotly' and 'seaborn' for visualization backends
|
|
54
|
+
|
|
55
|
+
### Key Components
|
|
56
|
+
1. **Data Loading** (`load.py`): FTP download, ethoscope database loading, metadata linking
|
|
57
|
+
2. **Analysis** (`analyse.py`): Sleep annotation, velocity detection, stimulus response
|
|
58
|
+
3. **Visualization**: Split between plotly (`behavpy_plotly.py`) and seaborn (`behavpy_seaborn.py`)
|
|
59
|
+
4. **Specialized Classes**:
|
|
60
|
+
- `behavpy_HMM_class.py`: Hidden Markov Model analysis
|
|
61
|
+
- `behavpy_periodogram_class.py`: Circadian rhythm analysis
|
|
62
|
+
5. **Utilities** (`misc/`): General functions, validation, tutorial data
|
|
63
|
+
|
|
64
|
+
### Data Structure
|
|
65
|
+
- **Dual DataFrame design**: Main data + linked metadata via shared 'id' column
|
|
66
|
+
- **Metadata cleaning**: Automatically removes columns like 'path', 'file_name', 'file_size', 'machine_id'
|
|
67
|
+
- **Index requirement**: Data must have 'id' as index name
|
|
68
|
+
|
|
69
|
+
### Import Pattern
|
|
70
|
+
```python
|
|
71
|
+
import ethoscopy as etho
|
|
72
|
+
df = etho.behavpy(data, metadata, check=True, canvas='plotly', palette='Set2')
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Key Design Patterns
|
|
76
|
+
|
|
77
|
+
### Version 2.0 Migration
|
|
78
|
+
- **Backward compatible** with pre-2.0 pickled data
|
|
79
|
+
- **Unified class structure**: All analysis under single `behavpy()` class
|
|
80
|
+
- **Canvas selection**: Choose between plotly/seaborn at initialization
|
|
81
|
+
- **New concat function**: Use `etho.concat()` instead of `behavpy_object.concat()`
|
|
82
|
+
|
|
83
|
+
### Plotting Architecture
|
|
84
|
+
- **Dual backend support**: Plotly (interactive) vs Seaborn (static)
|
|
85
|
+
- **Built-in statistical processing**: Z-score normalization, bootstrapping for plotly
|
|
86
|
+
- **Seaborn backend**: Uses seaborn's internal statistics
|
|
87
|
+
- **Performance consideration**: Plotly can create large notebook files
|
|
88
|
+
|
|
89
|
+
### Analysis Capabilities
|
|
90
|
+
- **Sleep detection**: Movement-based sleep annotation
|
|
91
|
+
- **Circadian analysis**: Periodograms (Lomb-Scargle, Fourier, Wavelet)
|
|
92
|
+
- **HMM behavioral states**: Using hmmlearn with visualization tools
|
|
93
|
+
- **Data curation**: Dead specimen removal, interpolation, filtering
|
|
94
|
+
|
|
95
|
+
## Development Guidelines
|
|
96
|
+
|
|
97
|
+
### Code Organization
|
|
98
|
+
- **src/ethoscopy/**: Main package code
|
|
99
|
+
- **tutorial_notebook/**: Jupyter notebooks for testing and examples
|
|
100
|
+
- **Docker/**: JupyterHub deployment configuration
|
|
101
|
+
- **Keep files under 500 lines** (per user's global instructions)
|
|
102
|
+
|
|
103
|
+
### Testing Approach
|
|
104
|
+
- **Use Jupyter notebooks** for validation and testing
|
|
105
|
+
- **Tutorial notebooks serve as integration tests**
|
|
106
|
+
- **Always test with both canvas options** (plotly/seaborn)
|
|
107
|
+
|
|
108
|
+
### Documentation
|
|
109
|
+
- **Docstrings**: Google style required for all functions
|
|
110
|
+
- **Tutorial notebooks**: Primary documentation method
|
|
111
|
+
- **README.md**: Keep updated with installation and basic usage
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(ls:*)",
|
|
5
|
+
"Bash(git checkout:*)",
|
|
6
|
+
"Bash(docker images:*)",
|
|
7
|
+
"Read(//tmp/**)",
|
|
8
|
+
"Bash(JUPYTER_HUB_TAG=5.3.0 ETHOSCOPE_LAB_TAG=1.1 docker compose build:*)",
|
|
9
|
+
"Bash(tee:*)",
|
|
10
|
+
"Bash(docker compose:*)",
|
|
11
|
+
"Bash(find:*)",
|
|
12
|
+
"Bash(sqlite3:*)",
|
|
13
|
+
"Bash(python3:*)",
|
|
14
|
+
"Bash(docker exec:*)",
|
|
15
|
+
"Bash(docker cp:*)"
|
|
16
|
+
],
|
|
17
|
+
"deny": []
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Keycloak OAuth Configuration for JupyterHub
|
|
2
|
+
# To use: cp .env.keycloak .env && docker compose restart
|
|
3
|
+
|
|
4
|
+
# Image versions
|
|
5
|
+
JUPYTER_HUB_TAG=5.3.0
|
|
6
|
+
ETHOSCOPE_LAB_TAG=1.1
|
|
7
|
+
|
|
8
|
+
# Authentication
|
|
9
|
+
AUTHENTICATOR_CLASS=generic
|
|
10
|
+
DUMMY_PASSWORD=ethoscope
|
|
11
|
+
|
|
12
|
+
# User configuration
|
|
13
|
+
ALLOWED_USERS=amadabhushi,ggilestro,mjoyce,lguo,labguest1,labguest2,labguest3,labguest4,labguest5,labguest6,labguest7,ethoscopelab
|
|
14
|
+
ADMIN_USERS=ggilestro
|
|
15
|
+
|
|
16
|
+
# User/Group IDs (must match your host system)
|
|
17
|
+
UID=1000
|
|
18
|
+
GID=1000
|
|
19
|
+
|
|
20
|
+
# Keycloak OAuth Settings
|
|
21
|
+
OAUTH_CLIENT_ID=jupyter-lab
|
|
22
|
+
OAUTH_CLIENT_SECRET=pBUaqP6b8bO5IamJ7jw4lD3l5EyKJaKq
|
|
23
|
+
OAUTH_CALLBACK_URL=https://jupyter.lab.gilest.ro/hub/oauth_callback
|
|
24
|
+
|
|
25
|
+
# Keycloak endpoints (realm: gilestro-lab)
|
|
26
|
+
OAUTH_AUTHORIZE_URL=https://auth.gilest.ro/realms/gilestro-lab/protocol/openid-connect/auth
|
|
27
|
+
OAUTH_TOKEN_URL=https://auth.gilest.ro/realms/gilestro-lab/protocol/openid-connect/token
|
|
28
|
+
OAUTH_USERDATA_URL=https://auth.gilest.ro/realms/gilestro-lab/protocol/openid-connect/userinfo
|
|
29
|
+
|
|
30
|
+
# Username claim (Keycloak typically uses 'preferred_username')
|
|
31
|
+
OAUTH_USERNAME_CLAIM=preferred_username
|
|
32
|
+
|
|
33
|
+
# OAuth scopes
|
|
34
|
+
OAUTH_SCOPE=openid profile email
|
|
35
|
+
|
|
36
|
+
# Provider-specific (not used for Keycloak, but needed for env validation)
|
|
37
|
+
GITHUB_ORG=
|
|
38
|
+
GOOGLE_HOSTED_DOMAIN=
|
|
39
|
+
GITLAB_URL=
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Keycloak OAuth Configuration for JupyterHub
|
|
2
|
+
# To use: cp .env.keycloak .env && docker compose restart
|
|
3
|
+
|
|
4
|
+
# Image versions
|
|
5
|
+
JUPYTER_HUB_TAG=5.3.0
|
|
6
|
+
ETHOSCOPE_LAB_TAG=1.1
|
|
7
|
+
|
|
8
|
+
# Authentication
|
|
9
|
+
AUTHENTICATOR_CLASS=generic
|
|
10
|
+
DUMMY_PASSWORD=ethoscope
|
|
11
|
+
|
|
12
|
+
# User configuration
|
|
13
|
+
ALLOWED_USERS=amadabhushi,ggilestro,mjoyce,lguo,labguest1,labguest2,labguest3,labguest4,labguest5,labguest6,labguest7,ethoscopelab
|
|
14
|
+
ADMIN_USERS=ggilestro
|
|
15
|
+
|
|
16
|
+
# User/Group IDs (must match your host system)
|
|
17
|
+
UID=1000
|
|
18
|
+
GID=1000
|
|
19
|
+
|
|
20
|
+
# Keycloak OAuth Settings
|
|
21
|
+
OAUTH_CLIENT_ID=jupyter-lab
|
|
22
|
+
OAUTH_CLIENT_SECRET=pBUaqP6b8bO5IamJ7jw4lD3l5EyKJaKq
|
|
23
|
+
OAUTH_CALLBACK_URL=https://jupyter.lab.gilest.ro/hub/oauth_callback
|
|
24
|
+
|
|
25
|
+
# Keycloak endpoints (realm: gilestro-lab)
|
|
26
|
+
OAUTH_AUTHORIZE_URL=https://auth.gilest.ro/realms/gilestro-lab/protocol/openid-connect/auth
|
|
27
|
+
OAUTH_TOKEN_URL=https://auth.gilest.ro/realms/gilestro-lab/protocol/openid-connect/token
|
|
28
|
+
OAUTH_USERDATA_URL=https://auth.gilest.ro/realms/gilestro-lab/protocol/openid-connect/userinfo
|
|
29
|
+
|
|
30
|
+
# Username claim (Keycloak typically uses 'preferred_username')
|
|
31
|
+
OAUTH_USERNAME_CLAIM=preferred_username
|
|
32
|
+
|
|
33
|
+
# OAuth scopes
|
|
34
|
+
OAUTH_SCOPE=openid profile email
|
|
35
|
+
|
|
36
|
+
# Provider-specific (not used for Keycloak, but needed for env validation)
|
|
37
|
+
GITHUB_ORG=
|
|
38
|
+
GOOGLE_HOSTED_DOMAIN=
|
|
39
|
+
GITLAB_URL=
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Dockerfile for jupyter-rethomics
|
|
2
|
+
ARG JUPYTER_HUB_TAG=5.3.0
|
|
3
|
+
FROM jupyterhub/jupyterhub:${JUPYTER_HUB_TAG}
|
|
4
|
+
|
|
5
|
+
# ============================================================================
|
|
6
|
+
# SYSTEM DEPENDENCIES AND TOOLS
|
|
7
|
+
# ============================================================================
|
|
8
|
+
|
|
9
|
+
# Install system prerequisites and build tools
|
|
10
|
+
RUN apt-get update && \
|
|
11
|
+
apt-get install -y --no-install-recommends \
|
|
12
|
+
fonts-dejavu \
|
|
13
|
+
apt-utils \
|
|
14
|
+
nano \
|
|
15
|
+
jq \
|
|
16
|
+
git \
|
|
17
|
+
gfortran \
|
|
18
|
+
file \
|
|
19
|
+
gcc \
|
|
20
|
+
cmake \
|
|
21
|
+
libcurl4-openssl-dev \
|
|
22
|
+
libfontconfig1-dev \
|
|
23
|
+
libharfbuzz-dev \
|
|
24
|
+
libfribidi-dev \
|
|
25
|
+
libtiff-dev \
|
|
26
|
+
libxml2-dev \
|
|
27
|
+
libpam0g-dev \
|
|
28
|
+
wget \
|
|
29
|
+
lsb-release \
|
|
30
|
+
software-properties-common \
|
|
31
|
+
dirmngr \
|
|
32
|
+
jupyter && \
|
|
33
|
+
apt-get clean && \
|
|
34
|
+
rm -rf /var/lib/apt/lists/*
|
|
35
|
+
|
|
36
|
+
# ============================================================================
|
|
37
|
+
# R INSTALLATION AND SETUP
|
|
38
|
+
# ============================================================================
|
|
39
|
+
|
|
40
|
+
# Add CRAN repository for latest R version
|
|
41
|
+
RUN wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | tee -a /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc && \
|
|
42
|
+
add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/" -y
|
|
43
|
+
|
|
44
|
+
# Install R from CRAN repository
|
|
45
|
+
RUN apt-get update && \
|
|
46
|
+
apt-get install -y r-base r-base-dev && \
|
|
47
|
+
apt-get clean && \
|
|
48
|
+
rm -rf /var/lib/apt/lists/*
|
|
49
|
+
|
|
50
|
+
# Install R packages and rethomics
|
|
51
|
+
COPY install_r_packages.r /root/install_r_packages.r
|
|
52
|
+
RUN ln -s /bin/tar /bin/gtar && \
|
|
53
|
+
Rscript /root/install_r_packages.r
|
|
54
|
+
|
|
55
|
+
# ============================================================================
|
|
56
|
+
# JUPYTER INSTALLATION AND CONFIGURATION
|
|
57
|
+
# ============================================================================
|
|
58
|
+
|
|
59
|
+
# Install JupyterLab (version 3.6.4)
|
|
60
|
+
RUN pip3 install jupyterlab --ignore-installed
|
|
61
|
+
|
|
62
|
+
# To upgrade to version 4.0.2 (commented out)
|
|
63
|
+
# RUN pip3 install jupyterlab --upgrade
|
|
64
|
+
|
|
65
|
+
# Install Jupyter extensions (compatible with 3.x only)
|
|
66
|
+
RUN pip3 install jupyterlab-spreadsheet-editor
|
|
67
|
+
|
|
68
|
+
# ============================================================================
|
|
69
|
+
# PYTHON PACKAGES AND ETHOSCOPE SETUP
|
|
70
|
+
# ============================================================================
|
|
71
|
+
|
|
72
|
+
# Install Python data science packages
|
|
73
|
+
RUN pip3 install \
|
|
74
|
+
pandas \
|
|
75
|
+
seaborn \
|
|
76
|
+
bokeh \
|
|
77
|
+
lifelines \
|
|
78
|
+
opencv-python \
|
|
79
|
+
mysql-connector \
|
|
80
|
+
ethoscopy
|
|
81
|
+
# pycatch22
|
|
82
|
+
|
|
83
|
+
# Install Ethoscope from source
|
|
84
|
+
RUN git clone https://github.com/gilestrolab/ethoscope.git /opt/ethoscope && \
|
|
85
|
+
cd /opt/ethoscope/ && git checkout dev && \
|
|
86
|
+
cd /opt/ethoscope/src/ethoscope && pip install .
|
|
87
|
+
|
|
88
|
+
# ============================================================================
|
|
89
|
+
# USER SETUP
|
|
90
|
+
# ============================================================================
|
|
91
|
+
|
|
92
|
+
# Add default user ethoscopelab with password ethoscopelab
|
|
93
|
+
RUN useradd -m ethoscopelab && \
|
|
94
|
+
echo 'ethoscopelab:ethoscope' | chpasswd
|
|
95
|
+
|
|
96
|
+
# ============================================================================
|
|
97
|
+
# FINAL CONFIGURATION
|
|
98
|
+
# ============================================================================
|
|
99
|
+
|
|
100
|
+
WORKDIR /srv/jupyterhub/
|
|
101
|
+
# JupyterHub config will be mounted via docker-compose
|
|
102
|
+
|
|
103
|
+
EXPOSE 8000
|
|
104
|
+
|
|
105
|
+
LABEL maintainer="Giorgio Gilestro <giorgio@gilest.ro>" \
|
|
106
|
+
org.jupyter.service="ethoscope-lab"
|
|
107
|
+
|
|
108
|
+
CMD ["jupyterhub"]
|