ethoscopy 2.0.1__tar.gz → 2.0.4__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 (82) hide show
  1. ethoscopy-2.0.4/.claude/settings.local.json +25 -0
  2. ethoscopy-2.0.4/.codecov.yml +26 -0
  3. ethoscopy-2.0.4/.github/workflows/ci.yml +151 -0
  4. ethoscopy-2.0.4/.github/workflows/release.yml +74 -0
  5. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/.gitignore +2 -1
  6. ethoscopy-2.0.4/.pre-commit-config.yaml +62 -0
  7. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/CLAUDE.md +37 -2
  8. ethoscopy-2.0.4/Docker/.claude/settings.local.json +41 -0
  9. ethoscopy-2.0.4/Docker/.env +39 -0
  10. ethoscopy-2.0.4/Docker/.env.keycloak +39 -0
  11. ethoscopy-2.0.4/Docker/README.md +227 -0
  12. ethoscopy-2.0.4/Docker/config/jupyterhub.sqlite +0 -0
  13. ethoscopy-2.0.4/Docker/config/jupyterhub_cookie_secret +1 -0
  14. ethoscopy-2.0.4/Docker/jupyterhub_data/jupyterhub-proxy.pid +1 -0
  15. ethoscopy-2.0.4/Docker/jupyterhub_data/jupyterhub.sqlite +0 -0
  16. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/Docker/jupyterhub_data/jupyterhub_config.py +4 -4
  17. ethoscopy-2.0.4/Docker/jupyterhub_data/jupyterhub_cookie_secret +1 -0
  18. ethoscopy-2.0.1/README.md → ethoscopy-2.0.4/PKG-INFO +83 -3
  19. ethoscopy-2.0.4/QWEN.md +88 -0
  20. ethoscopy-2.0.1/PKG-INFO → ethoscopy-2.0.4/README.md +44 -22
  21. ethoscopy-2.0.4/TESTING.md +275 -0
  22. ethoscopy-2.0.4/_config.yml +1 -0
  23. ethoscopy-2.0.4/pyproject.toml +63 -0
  24. ethoscopy-2.0.4/pytest.ini +22 -0
  25. ethoscopy-2.0.4/run_tests.py +76 -0
  26. ethoscopy-2.0.4/scripts/README.md +121 -0
  27. ethoscopy-2.0.4/scripts/convert_databases.sh +51 -0
  28. ethoscopy-2.0.4/scripts/convert_wal_to_delete.py +240 -0
  29. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/setup.py +2 -2
  30. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/__init__.py +20 -20
  31. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/analyse.py +318 -242
  32. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/behavpy.py +31 -15
  33. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/behavpy_HMM_class.py +24 -14
  34. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/behavpy_class.py +24 -14
  35. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/behavpy_core.py +1152 -642
  36. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/behavpy_draw.py +1162 -531
  37. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/behavpy_periodogram_class.py +24 -14
  38. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/behavpy_plotly.py +2527 -1230
  39. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/behavpy_seaborn.py +1881 -704
  40. ethoscopy-2.0.4/src/ethoscopy/load.py +1011 -0
  41. ethoscopy-2.0.4/src/ethoscopy/metadata_db.py +422 -0
  42. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/misc/circadian_bars.py +58 -32
  43. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/misc/general_functions.py +41 -33
  44. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/misc/get_HMM.py +9 -9
  45. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/misc/get_tutorials.py +15 -11
  46. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/misc/hmm_functions.py +43 -38
  47. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/misc/periodogram_functions.py +139 -99
  48. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/misc/validate_datetime.py +16 -11
  49. ethoscopy-2.0.4/tests/__init__.py +3 -0
  50. ethoscopy-2.0.4/tests/conftest.py +247 -0
  51. ethoscopy-2.0.4/tests/data/README.md +13 -0
  52. ethoscopy-2.0.4/tests/data/test_ethoscope.db +0 -0
  53. ethoscopy-2.0.4/tests/test_analyse.py +438 -0
  54. ethoscopy-2.0.4/tests/test_baseline_enhancements.py +452 -0
  55. ethoscopy-2.0.4/tests/test_behavpy.py +408 -0
  56. ethoscopy-2.0.4/tests/test_behavpy_core_simple.py +298 -0
  57. ethoscopy-2.0.4/tests/test_compatibility_classes.py +285 -0
  58. ethoscopy-2.0.4/tests/test_general_functions.py +135 -0
  59. ethoscopy-2.0.4/tests/test_get_tutorials.py +136 -0
  60. ethoscopy-2.0.4/tests/test_load.py +431 -0
  61. ethoscopy-2.0.4/tests/test_load_comprehensive.py +782 -0
  62. ethoscopy-2.0.4/tests/test_load_optimizations.py +635 -0
  63. ethoscopy-2.0.1/.claude/settings.local.json +0 -16
  64. ethoscopy-2.0.1/Docker/README.md +0 -87
  65. ethoscopy-2.0.1/_config.yml +0 -1
  66. ethoscopy-2.0.1/pyproject.toml +0 -38
  67. ethoscopy-2.0.1/src/ethoscopy/load.py +0 -618
  68. ethoscopy-2.0.1/src/ethoscopy/metadata_db.py +0 -380
  69. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/Docker/Dockerfile +0 -0
  70. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/Docker/docker-compose.yml +0 -0
  71. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/Docker/install_r_packages.r +0 -0
  72. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/LICENSE +0 -0
  73. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/src/ethoscopy/misc/__init__.py +0 -0
  74. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/tutorial_notebook/1_Overview_tutorial.ipynb +0 -0
  75. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/tutorial_notebook/2_HMM_tutorial.ipynb +0 -0
  76. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/tutorial_notebook/3_Circadian_tutorial.ipynb +0 -0
  77. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/tutorial_notebook/4_Navigating_db_tutorial.ipynb +0 -0
  78. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/tutorial_notebook/5_Ethoscopy_catch22_tutorial.ipynb +0 -0
  79. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/tutorial_notebook/6_Ethoscopy_to_hctsa_tutorial.ipynb +0 -0
  80. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/tutorial_notebook/ethoscope_db.csv +0 -0
  81. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/tutorial_notebook/jones_et_al_metadata.csv +0 -0
  82. {ethoscopy-2.0.1 → ethoscopy-2.0.4}/tutorial_notebook/notebook_paper.ipynb +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/*
@@ -7,4 +7,5 @@ __pycache__/
7
7
  ethoscopy.egg-info/
8
8
  .gitignore
9
9
  *.pkl
10
- .python-version
10
+ .python-version
11
+ tmp
@@ -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]
@@ -10,7 +10,7 @@ Ethoscopy is a Python data analysis toolbox for behavioral time series data from
10
10
 
11
11
  ### Python Environment
12
12
  - **Use Python 3.10+** (project requires >=3.10,<4.0)
13
- - **Always use virtual environment** (`venv_linux` as mentioned in user's global instructions)
13
+ - **Always use virtual environment** (`.venv` as mentioned in user's global instructions)
14
14
  - **Install in development mode**: `pip install -e .`
15
15
 
16
16
  ### Package Management
@@ -45,6 +45,41 @@ pip install -e ".[dev]"
45
45
  - Build: `JUPYTER_HUB_TAG=5.3.0 ETHOSCOPE_LAB_TAG=1.0 docker compose build`
46
46
  - Run: `docker compose up -d` (from Docker/ directory)
47
47
 
48
+ ### Troubleshooting: Database "Malformed" Errors
49
+
50
+ **Problem**: Intermittent "database disk image is malformed" errors when loading ethoscope data in Docker
51
+
52
+ **Root Cause**: SQLite databases in WAL (Write-Ahead Logging) mode on read-only Docker mounts
53
+
54
+ **Solution Options**:
55
+ 1. **Convert databases to DELETE mode** (recommended for immediate fix)
56
+ ```bash
57
+ # Using the conversion script (from project root)
58
+ python3 scripts/convert_wal_to_delete.py /mnt/ethoscope_data/results --verbose
59
+
60
+ # Or using bash wrapper
61
+ ./scripts/convert_databases.sh /mnt/ethoscope_data/results
62
+ ```
63
+
64
+ 2. **Improved connection handling** (v2.0.4+)
65
+ - The `_connect_db()` function in `load.py` now detects WAL mode automatically
66
+ - Uses `mode=ro&nolock=1` URI parameters for WAL databases on read-only mounts
67
+ - Includes retry logic in `read_single_roi_optimized()` for resilience
68
+
69
+ **Key Implementation Details** (load.py):
70
+ - Lines 18-70: `_connect_db()` - Smart connection with WAL detection and appropriate parameters
71
+ - Lines 943-979: Retry logic in `read_single_roi_optimized()` - Handles transient errors with fresh connections
72
+
73
+ **Testing After Changes**:
74
+ ```python
75
+ import ethoscopy as etho
76
+ metadata = etho.link_meta_index('metadata.csv', '/mnt/ethoscope_results')
77
+ data = etho.load_ethoscope(metadata, reference_hour=9.0, FUN=etho.sleep_annotation)
78
+ # Should load all ROIs without "malformed" errors
79
+ ```
80
+
81
+ **See Also**: `Docker/README.md` for detailed database preparation instructions
82
+
48
83
  ## Architecture and Code Structure
49
84
 
50
85
  ### Core Architecture
@@ -108,4 +143,4 @@ df = etho.behavpy(data, metadata, check=True, canvas='plotly', palette='Set2')
108
143
  ### Documentation
109
144
  - **Docstrings**: Google style required for all functions
110
145
  - **Tutorial notebooks**: Primary documentation method
111
- - **README.md**: Keep updated with installation and basic usage
146
+ - **README.md**: Keep updated with installation and basic usage
@@ -0,0 +1,41 @@
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
+ "Bash(ip addr:*)",
17
+ "Bash(systemctl status:*)",
18
+ "Bash(docker ps:*)",
19
+ "Bash(wg show:*)",
20
+ "Bash(ip route:*)",
21
+ "Bash(ip rule:*)",
22
+ "Bash(docker inspect:*)",
23
+ "Bash(docker logs:*)",
24
+ "Bash(nc:*)",
25
+ "Bash(timeout 3 bash -c 'cat < /dev/tcp/192.168.254.10/8082')",
26
+ "Bash(docker network inspect:*)",
27
+ "Bash(ss:*)",
28
+ "Bash(host:*)",
29
+ "Bash(chmod:*)",
30
+ "Bash(tree:*)",
31
+ "Bash(source:*)",
32
+ "Bash(pip install:*)",
33
+ "Bash(git add:*)",
34
+ "Bash(git commit -m \"$\\(cat <<''EOF''\nfix: resolve \"database disk image is malformed\" errors for WAL-mode databases\n\nAdd comprehensive solution for SQLite WAL-mode database errors on read-only Docker mounts:\n\n- Improve connection handling in load.py:\n - Detect WAL mode databases and use appropriate connection parameters\n - Add retry logic with fresh connections for transient errors\n - Use mode=ro&nolock=1 for WAL databases on read-only filesystems\n\n- Add database conversion scripts:\n - convert_wal_to_delete.py: Python script to convert databases from WAL to DELETE mode\n - convert_databases.sh: Bash wrapper for easy bulk conversion\n - scripts/README.md: Comprehensive documentation for database utilities\n\n- Update documentation:\n - Docker/README.md: Add \"Database Preparation for Docker\" section\n - CLAUDE.md: Add troubleshooting section for database errors\n\n- Bump version to 2.0.4\n\nThis resolves intermittent loading failures for ROIs when ethoscope databases\nin WAL mode are mounted read-only in Docker containers.\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
35
+ "Bash(git push:*)",
36
+ "Bash(git tag:*)",
37
+ "Bash(python -m build:*)"
38
+ ],
39
+ "deny": []
40
+ }
41
+ }
@@ -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=