wormscore 0.6.1__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.
- wormscore-0.6.1/LICENSE +21 -0
- wormscore-0.6.1/PKG-INFO +164 -0
- wormscore-0.6.1/README.md +132 -0
- wormscore-0.6.1/pyproject.toml +55 -0
- wormscore-0.6.1/setup.cfg +4 -0
- wormscore-0.6.1/src/wormscore/__init__.py +3 -0
- wormscore-0.6.1/src/wormscore/cli.py +81 -0
- wormscore-0.6.1/src/wormscore/config.py +265 -0
- wormscore-0.6.1/src/wormscore/copydata.py +33 -0
- wormscore-0.6.1/src/wormscore/demo.py +96 -0
- wormscore-0.6.1/src/wormscore/launcher.py +272 -0
- wormscore-0.6.1/src/wormscore/measure.py +145 -0
- wormscore-0.6.1/src/wormscore/methods.py +183 -0
- wormscore-0.6.1/src/wormscore/pipeline.py +481 -0
- wormscore-0.6.1/src/wormscore/readers.py +392 -0
- wormscore-0.6.1/src/wormscore/realdemo.py +94 -0
- wormscore-0.6.1/src/wormscore/server.py +263 -0
- wormscore-0.6.1/src/wormscore/static/app.js +555 -0
- wormscore-0.6.1/src/wormscore/static/icon.svg +1 -0
- wormscore-0.6.1/src/wormscore/static/index.html +107 -0
- wormscore-0.6.1/src/wormscore/static/style.css +147 -0
- wormscore-0.6.1/src/wormscore/stats.py +237 -0
- wormscore-0.6.1/src/wormscore/unblind.py +304 -0
- wormscore-0.6.1/src/wormscore.egg-info/PKG-INFO +164 -0
- wormscore-0.6.1/src/wormscore.egg-info/SOURCES.txt +36 -0
- wormscore-0.6.1/src/wormscore.egg-info/dependency_links.txt +1 -0
- wormscore-0.6.1/src/wormscore.egg-info/entry_points.txt +5 -0
- wormscore-0.6.1/src/wormscore.egg-info/requires.txt +11 -0
- wormscore-0.6.1/src/wormscore.egg-info/top_level.txt +1 -0
- wormscore-0.6.1/tests/test_add_images.py +72 -0
- wormscore-0.6.1/tests/test_analysis_plan.py +154 -0
- wormscore-0.6.1/tests/test_app.py +117 -0
- wormscore-0.6.1/tests/test_measure.py +84 -0
- wormscore-0.6.1/tests/test_pipeline.py +90 -0
- wormscore-0.6.1/tests/test_readers.py +122 -0
- wormscore-0.6.1/tests/test_realdemo.py +47 -0
- wormscore-0.6.1/tests/test_results_options.py +155 -0
- wormscore-0.6.1/tests/test_stats.py +44 -0
wormscore-0.6.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Arjun Bansal
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
wormscore-0.6.1/PKG-INFO
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wormscore
|
|
3
|
+
Version: 0.6.1
|
|
4
|
+
Summary: Blind scoring of fluorescent neurons in C. elegans confocal stacks, with measurement and genetics statistics.
|
|
5
|
+
Author: Arjun Bansal
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/arjunkai/wormscore
|
|
8
|
+
Project-URL: Documentation, https://github.com/arjunkai/wormscore/blob/main/docs/METHODS.md
|
|
9
|
+
Project-URL: Issues, https://github.com/arjunkai/wormscore/issues
|
|
10
|
+
Project-URL: Releases, https://github.com/arjunkai/wormscore/releases
|
|
11
|
+
Keywords: C. elegans,worm,neuron,blind scoring,fluorescence,microscopy,confocal,penetrance
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
18
|
+
Requires-Python: >=3.12
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: numpy>=1.26
|
|
22
|
+
Requires-Dist: scipy>=1.11
|
|
23
|
+
Requires-Dist: pillow>=10
|
|
24
|
+
Requires-Dist: liffile>=2026.10.14
|
|
25
|
+
Requires-Dist: czifile>=2026.10.14
|
|
26
|
+
Requires-Dist: tifffile>=2024.1
|
|
27
|
+
Requires-Dist: imagecodecs>=2024.1
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
30
|
+
Requires-Dist: pyinstaller>=6.10; extra == "dev"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# wormscore
|
|
34
|
+
|
|
35
|
+
Blind scoring of fluorescent neurons in *C. elegans*, with measurement and genetics statistics.
|
|
36
|
+
Built for scoring reporter neurons (normal / dim / missing) in confocal z-stacks. Nothing is tied
|
|
37
|
+
to one neuron, marker or microscope: those are settings in each project's `config.json`, so other
|
|
38
|
+
organisms work the same way.
|
|
39
|
+
|
|
40
|
+
- **Blind:** every image gets a random code. Genotypes and file names stay in a sealed key
|
|
41
|
+
until you finish scoring.
|
|
42
|
+
- **Fixed display:** every image from the same microscope is shown with the same brightness range.
|
|
43
|
+
You can page through z-planes and overlay brightfield.
|
|
44
|
+
- **Measured, not decided:** suggested cell bodies and your drawn regions are measured (peak, mean,
|
|
45
|
+
local background, sharpest plane, saturation). The numbers are written to files and never shown
|
|
46
|
+
while you score. The software never labels a cell normal, dim or missing.
|
|
47
|
+
- **Traceable:** every number links to the exact file, path, series and SHA-256 checksum it came from.
|
|
48
|
+
- **Reproducible:** every parameter and software version is appended to `log.md` on each run.
|
|
49
|
+
- **Local:** runs on your computer only. Nothing is uploaded.
|
|
50
|
+
|
|
51
|
+
Supported raw formats: Leica `.lif`, Zeiss `.czi`, OME-TIFF (including Micro-Manager style files with
|
|
52
|
+
a `.companion.ome`). Channel identity (marker vs brightfield) is read from metadata, never guessed.
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
**Windows, no Python needed:** download `wormscore-windows.zip` from the Releases page, unzip it,
|
|
57
|
+
and double-click `wormscore.exe`.
|
|
58
|
+
|
|
59
|
+
**With Python 3.12 or newer:**
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
pip install git+https://github.com/arjunkai/wormscore.git
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
This installs a `wormscore` command and a `wormscore-launcher` window.
|
|
66
|
+
|
|
67
|
+
## Try it in two minutes (simulated data)
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
wormscore demo my_demo
|
|
71
|
+
wormscore inventory my_demo
|
|
72
|
+
wormscore prepare my_demo
|
|
73
|
+
wormscore app my_demo
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`demo` writes 20 simulated worm heads (controls with two normal cells; mutants with cells that are
|
|
77
|
+
normal, dim or missing at random) and a `demo_truth.csv` you can check your calls against later.
|
|
78
|
+
In the launcher window the same steps are buttons: **Demo... > 1. Scan data > 2. Build blind set > 3. Score**.
|
|
79
|
+
|
|
80
|
+
**Real worms:** `wormscore demo my_demo --real` (or Yes in the launcher's Demo dialog) downloads four
|
|
81
|
+
L1 heads with an endogenous GFP reporter, about 150 MB, from
|
|
82
|
+
[Sun and Hobert 2021](https://doi.org/10.1038/s41586-021-04071-4)
|
|
83
|
+
([Zenodo 5602160](https://doi.org/10.5281/zenodo.5602160), CC BY 4.0). Each file is checked against its
|
|
84
|
+
MD5 from the Zenodo record and cached in `%LOCALAPPDATA%\wormscore\demo_cache` (`~/.cache` elsewhere).
|
|
85
|
+
The two reporters stand in for two genotypes; both are normal animals, so this is for practice.
|
|
86
|
+
The images are not part of this repository.
|
|
87
|
+
|
|
88
|
+
## Using it on your own images
|
|
89
|
+
|
|
90
|
+
1. **Copy your data** to a local folder (not a synced cloud folder if the data is not yours to share):
|
|
91
|
+
`wormscore copy D:\from\drive C:\data\my_copy` copies every file, checks each one by SHA-256 and
|
|
92
|
+
makes the copies read-only.
|
|
93
|
+
2. **Make a project:** `wormscore init C:\projects\my_project`, then edit `config.json`:
|
|
94
|
+
point `sources` at your images, write genotype rules, and name your neurons. See
|
|
95
|
+
[`examples/config_example.json`](https://github.com/arjunkai/wormscore/blob/main/examples/config_example.json).
|
|
96
|
+
3. **Scan:** `wormscore inventory my_project` lists every file (`outputs/manifest.csv`: raw image,
|
|
97
|
+
duplicate, derived projection, reference, hidden system file) and every image with its metadata
|
|
98
|
+
and channel identity (`outputs/inventory.csv`). Check the flags column.
|
|
99
|
+
4. **Build the blind set:** `wormscore prepare my_project` applies the inclusion rules, assigns codes,
|
|
100
|
+
finds and measures suggested cells, and writes the sealed key. Excluded images and the reasons are
|
|
101
|
+
in `outputs/excluded.csv`. To leave out images by name (for example a plate with the wrong
|
|
102
|
+
reporter), add `"exclude": [{"match": "*pattern*", "reason": "why"}]` to that source.
|
|
103
|
+
Images taken after scoring started can be added with `wormscore prepare my_project --add-new-images`
|
|
104
|
+
(scan first): existing codes stay the same and new images get codes after the last one.
|
|
105
|
+
5. **Score:** `wormscore app my_project`. For each image: answer any yellow questions, score each
|
|
106
|
+
neuron, save, then outline each cell body (or accept a suggestion) and save regions.
|
|
107
|
+
6. **Unblind after scoring:** `wormscore unblind my_project --i-have-finished-scoring`. Writes
|
|
108
|
+
`outputs/unblinded/merged.csv` (scores + numbers + key, one row per image), a summary, and results
|
|
109
|
+
tables: `per_neuron.csv` (one row per animal and neuron, for plotting), `penetrance.csv` (animals with
|
|
110
|
+
0, 1, 2 ... affected neurons) and `fisher_tests.csv` (Fisher's exact within each microscope,
|
|
111
|
+
Bonferroni-corrected). Set `unblinding.reference_genotype` in `config.json` to test against a control.
|
|
112
|
+
Optional, off unless set in `unblinding`: `question_outcomes` turns the per-neuron questions into
|
|
113
|
+
the same penetrance and Fisher tables (for example "process defect" when a dendrite question is
|
|
114
|
+
answered "no"), and `interaction` tests a double mutant against the value two single mutants predict
|
|
115
|
+
(Product model by default) with a binomial test. Also optional: a secondary definition of "affected"
|
|
116
|
+
(descriptive, within one microscope), planned comparisons, one-sided tests, labelled sources, and
|
|
117
|
+
comparisons across microscopes for chosen measures (with warnings). All of these are recorded as an
|
|
118
|
+
analysis plan before scoring and locked once scoring starts. See [docs/METHODS.md](https://github.com/arjunkai/wormscore/blob/main/docs/METHODS.md#8-unblinding).
|
|
119
|
+
`methods_text.md` is a draft Methods paragraph on blinding, measurement and statistics; fill in the
|
|
120
|
+
`blinding` section of `config.json` (who coded, who scored) or edit the [brackets] it leaves.
|
|
121
|
+
|
|
122
|
+
## Project folder
|
|
123
|
+
|
|
124
|
+
| Path | Contents | Open while scoring? |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| `config.json` | every parameter | yes |
|
|
127
|
+
| `log.md` | every run: parameters, software versions, counts | yes |
|
|
128
|
+
| `outputs/manifest.csv`, `inventory.csv`, `excluded.csv` | what was found and what was left out | yes |
|
|
129
|
+
| `outputs/auto_measurements.csv` | numbers for suggested spots | avoid until done |
|
|
130
|
+
| `blind/` | images for scoring, named by code | used by the app |
|
|
131
|
+
| `scoring/` | your scores, regions and their measurements | scores yes; avoid `roi_measurements.csv` |
|
|
132
|
+
| `key/` | code to file, genotype, settings | **no, not until scoring is finished** |
|
|
133
|
+
|
|
134
|
+
## How it works
|
|
135
|
+
|
|
136
|
+
See [docs/METHODS.md](https://github.com/arjunkai/wormscore/blob/main/docs/METHODS.md) for every step in plain language, suitable for adapting into
|
|
137
|
+
a Methods section, including the measurement definitions and their limits.
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
pip install -e .[dev]
|
|
143
|
+
pytest
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The tests build a simulated project and check the measurements, the blinding (no genotype or file
|
|
147
|
+
name reaches the scoring page), code stability, the unblinding locks and traceability. Leica and
|
|
148
|
+
Zeiss readers are checked against real files locally; real images are never committed.
|
|
149
|
+
|
|
150
|
+
Build the Windows app: `packaging\build_windows.bat`.
|
|
151
|
+
|
|
152
|
+
## Privacy
|
|
153
|
+
|
|
154
|
+
This repository contains code only. `.gitignore` excludes image formats, keys, scores and outputs.
|
|
155
|
+
Do not commit or upload data that belongs to someone else.
|
|
156
|
+
|
|
157
|
+
## License and citation
|
|
158
|
+
|
|
159
|
+
MIT License (see [LICENSE](https://github.com/arjunkai/wormscore/blob/main/LICENSE)). If you use wormscore in research, please cite it: GitHub's
|
|
160
|
+
"Cite this repository" button (from [CITATION.cff](https://github.com/arjunkai/wormscore/blob/main/CITATION.cff)) gives the reference.
|
|
161
|
+
|
|
162
|
+
wormscore reads Leica files with [liffile](https://github.com/cgohlke/liffile) and Zeiss files with
|
|
163
|
+
[czifile](https://github.com/cgohlke/czifile) (both BSD-3). The Windows app bundles these and other
|
|
164
|
+
libraries; their licenses are in `THIRD_PARTY_LICENSES.txt` next to `wormscore.exe`.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# wormscore
|
|
2
|
+
|
|
3
|
+
Blind scoring of fluorescent neurons in *C. elegans*, with measurement and genetics statistics.
|
|
4
|
+
Built for scoring reporter neurons (normal / dim / missing) in confocal z-stacks. Nothing is tied
|
|
5
|
+
to one neuron, marker or microscope: those are settings in each project's `config.json`, so other
|
|
6
|
+
organisms work the same way.
|
|
7
|
+
|
|
8
|
+
- **Blind:** every image gets a random code. Genotypes and file names stay in a sealed key
|
|
9
|
+
until you finish scoring.
|
|
10
|
+
- **Fixed display:** every image from the same microscope is shown with the same brightness range.
|
|
11
|
+
You can page through z-planes and overlay brightfield.
|
|
12
|
+
- **Measured, not decided:** suggested cell bodies and your drawn regions are measured (peak, mean,
|
|
13
|
+
local background, sharpest plane, saturation). The numbers are written to files and never shown
|
|
14
|
+
while you score. The software never labels a cell normal, dim or missing.
|
|
15
|
+
- **Traceable:** every number links to the exact file, path, series and SHA-256 checksum it came from.
|
|
16
|
+
- **Reproducible:** every parameter and software version is appended to `log.md` on each run.
|
|
17
|
+
- **Local:** runs on your computer only. Nothing is uploaded.
|
|
18
|
+
|
|
19
|
+
Supported raw formats: Leica `.lif`, Zeiss `.czi`, OME-TIFF (including Micro-Manager style files with
|
|
20
|
+
a `.companion.ome`). Channel identity (marker vs brightfield) is read from metadata, never guessed.
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
**Windows, no Python needed:** download `wormscore-windows.zip` from the Releases page, unzip it,
|
|
25
|
+
and double-click `wormscore.exe`.
|
|
26
|
+
|
|
27
|
+
**With Python 3.12 or newer:**
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
pip install git+https://github.com/arjunkai/wormscore.git
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
This installs a `wormscore` command and a `wormscore-launcher` window.
|
|
34
|
+
|
|
35
|
+
## Try it in two minutes (simulated data)
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
wormscore demo my_demo
|
|
39
|
+
wormscore inventory my_demo
|
|
40
|
+
wormscore prepare my_demo
|
|
41
|
+
wormscore app my_demo
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`demo` writes 20 simulated worm heads (controls with two normal cells; mutants with cells that are
|
|
45
|
+
normal, dim or missing at random) and a `demo_truth.csv` you can check your calls against later.
|
|
46
|
+
In the launcher window the same steps are buttons: **Demo... > 1. Scan data > 2. Build blind set > 3. Score**.
|
|
47
|
+
|
|
48
|
+
**Real worms:** `wormscore demo my_demo --real` (or Yes in the launcher's Demo dialog) downloads four
|
|
49
|
+
L1 heads with an endogenous GFP reporter, about 150 MB, from
|
|
50
|
+
[Sun and Hobert 2021](https://doi.org/10.1038/s41586-021-04071-4)
|
|
51
|
+
([Zenodo 5602160](https://doi.org/10.5281/zenodo.5602160), CC BY 4.0). Each file is checked against its
|
|
52
|
+
MD5 from the Zenodo record and cached in `%LOCALAPPDATA%\wormscore\demo_cache` (`~/.cache` elsewhere).
|
|
53
|
+
The two reporters stand in for two genotypes; both are normal animals, so this is for practice.
|
|
54
|
+
The images are not part of this repository.
|
|
55
|
+
|
|
56
|
+
## Using it on your own images
|
|
57
|
+
|
|
58
|
+
1. **Copy your data** to a local folder (not a synced cloud folder if the data is not yours to share):
|
|
59
|
+
`wormscore copy D:\from\drive C:\data\my_copy` copies every file, checks each one by SHA-256 and
|
|
60
|
+
makes the copies read-only.
|
|
61
|
+
2. **Make a project:** `wormscore init C:\projects\my_project`, then edit `config.json`:
|
|
62
|
+
point `sources` at your images, write genotype rules, and name your neurons. See
|
|
63
|
+
[`examples/config_example.json`](https://github.com/arjunkai/wormscore/blob/main/examples/config_example.json).
|
|
64
|
+
3. **Scan:** `wormscore inventory my_project` lists every file (`outputs/manifest.csv`: raw image,
|
|
65
|
+
duplicate, derived projection, reference, hidden system file) and every image with its metadata
|
|
66
|
+
and channel identity (`outputs/inventory.csv`). Check the flags column.
|
|
67
|
+
4. **Build the blind set:** `wormscore prepare my_project` applies the inclusion rules, assigns codes,
|
|
68
|
+
finds and measures suggested cells, and writes the sealed key. Excluded images and the reasons are
|
|
69
|
+
in `outputs/excluded.csv`. To leave out images by name (for example a plate with the wrong
|
|
70
|
+
reporter), add `"exclude": [{"match": "*pattern*", "reason": "why"}]` to that source.
|
|
71
|
+
Images taken after scoring started can be added with `wormscore prepare my_project --add-new-images`
|
|
72
|
+
(scan first): existing codes stay the same and new images get codes after the last one.
|
|
73
|
+
5. **Score:** `wormscore app my_project`. For each image: answer any yellow questions, score each
|
|
74
|
+
neuron, save, then outline each cell body (or accept a suggestion) and save regions.
|
|
75
|
+
6. **Unblind after scoring:** `wormscore unblind my_project --i-have-finished-scoring`. Writes
|
|
76
|
+
`outputs/unblinded/merged.csv` (scores + numbers + key, one row per image), a summary, and results
|
|
77
|
+
tables: `per_neuron.csv` (one row per animal and neuron, for plotting), `penetrance.csv` (animals with
|
|
78
|
+
0, 1, 2 ... affected neurons) and `fisher_tests.csv` (Fisher's exact within each microscope,
|
|
79
|
+
Bonferroni-corrected). Set `unblinding.reference_genotype` in `config.json` to test against a control.
|
|
80
|
+
Optional, off unless set in `unblinding`: `question_outcomes` turns the per-neuron questions into
|
|
81
|
+
the same penetrance and Fisher tables (for example "process defect" when a dendrite question is
|
|
82
|
+
answered "no"), and `interaction` tests a double mutant against the value two single mutants predict
|
|
83
|
+
(Product model by default) with a binomial test. Also optional: a secondary definition of "affected"
|
|
84
|
+
(descriptive, within one microscope), planned comparisons, one-sided tests, labelled sources, and
|
|
85
|
+
comparisons across microscopes for chosen measures (with warnings). All of these are recorded as an
|
|
86
|
+
analysis plan before scoring and locked once scoring starts. See [docs/METHODS.md](https://github.com/arjunkai/wormscore/blob/main/docs/METHODS.md#8-unblinding).
|
|
87
|
+
`methods_text.md` is a draft Methods paragraph on blinding, measurement and statistics; fill in the
|
|
88
|
+
`blinding` section of `config.json` (who coded, who scored) or edit the [brackets] it leaves.
|
|
89
|
+
|
|
90
|
+
## Project folder
|
|
91
|
+
|
|
92
|
+
| Path | Contents | Open while scoring? |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| `config.json` | every parameter | yes |
|
|
95
|
+
| `log.md` | every run: parameters, software versions, counts | yes |
|
|
96
|
+
| `outputs/manifest.csv`, `inventory.csv`, `excluded.csv` | what was found and what was left out | yes |
|
|
97
|
+
| `outputs/auto_measurements.csv` | numbers for suggested spots | avoid until done |
|
|
98
|
+
| `blind/` | images for scoring, named by code | used by the app |
|
|
99
|
+
| `scoring/` | your scores, regions and their measurements | scores yes; avoid `roi_measurements.csv` |
|
|
100
|
+
| `key/` | code to file, genotype, settings | **no, not until scoring is finished** |
|
|
101
|
+
|
|
102
|
+
## How it works
|
|
103
|
+
|
|
104
|
+
See [docs/METHODS.md](https://github.com/arjunkai/wormscore/blob/main/docs/METHODS.md) for every step in plain language, suitable for adapting into
|
|
105
|
+
a Methods section, including the measurement definitions and their limits.
|
|
106
|
+
|
|
107
|
+
## Development
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
pip install -e .[dev]
|
|
111
|
+
pytest
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The tests build a simulated project and check the measurements, the blinding (no genotype or file
|
|
115
|
+
name reaches the scoring page), code stability, the unblinding locks and traceability. Leica and
|
|
116
|
+
Zeiss readers are checked against real files locally; real images are never committed.
|
|
117
|
+
|
|
118
|
+
Build the Windows app: `packaging\build_windows.bat`.
|
|
119
|
+
|
|
120
|
+
## Privacy
|
|
121
|
+
|
|
122
|
+
This repository contains code only. `.gitignore` excludes image formats, keys, scores and outputs.
|
|
123
|
+
Do not commit or upload data that belongs to someone else.
|
|
124
|
+
|
|
125
|
+
## License and citation
|
|
126
|
+
|
|
127
|
+
MIT License (see [LICENSE](https://github.com/arjunkai/wormscore/blob/main/LICENSE)). If you use wormscore in research, please cite it: GitHub's
|
|
128
|
+
"Cite this repository" button (from [CITATION.cff](https://github.com/arjunkai/wormscore/blob/main/CITATION.cff)) gives the reference.
|
|
129
|
+
|
|
130
|
+
wormscore reads Leica files with [liffile](https://github.com/cgohlke/liffile) and Zeiss files with
|
|
131
|
+
[czifile](https://github.com/cgohlke/czifile) (both BSD-3). The Windows app bundles these and other
|
|
132
|
+
libraries; their licenses are in `THIRD_PARTY_LICENSES.txt` next to `wormscore.exe`.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "wormscore"
|
|
7
|
+
version = "0.6.1"
|
|
8
|
+
description = "Blind scoring of fluorescent neurons in C. elegans confocal stacks, with measurement and genetics statistics."
|
|
9
|
+
keywords = ["C. elegans", "worm", "neuron", "blind scoring", "fluorescence", "microscopy", "confocal", "penetrance"]
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Arjun Bansal" }]
|
|
14
|
+
requires-python = ">=3.12"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Intended Audience :: Science/Research",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
21
|
+
"Topic :: Scientific/Engineering :: Image Processing",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"numpy>=1.26",
|
|
25
|
+
"scipy>=1.11",
|
|
26
|
+
"pillow>=10",
|
|
27
|
+
"liffile>=2026.10.14",
|
|
28
|
+
"czifile>=2026.10.14",
|
|
29
|
+
"tifffile>=2024.1",
|
|
30
|
+
"imagecodecs>=2024.1",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/arjunkai/wormscore"
|
|
35
|
+
Documentation = "https://github.com/arjunkai/wormscore/blob/main/docs/METHODS.md"
|
|
36
|
+
Issues = "https://github.com/arjunkai/wormscore/issues"
|
|
37
|
+
Releases = "https://github.com/arjunkai/wormscore/releases"
|
|
38
|
+
|
|
39
|
+
[project.optional-dependencies]
|
|
40
|
+
dev = ["pytest>=8", "pyinstaller>=6.10"]
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
wormscore = "wormscore.cli:main"
|
|
44
|
+
|
|
45
|
+
[project.gui-scripts]
|
|
46
|
+
wormscore-launcher = "wormscore.launcher:main"
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.packages.find]
|
|
49
|
+
where = ["src"]
|
|
50
|
+
|
|
51
|
+
[tool.setuptools.package-data]
|
|
52
|
+
wormscore = ["static/*"]
|
|
53
|
+
|
|
54
|
+
[tool.pytest.ini_options]
|
|
55
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Command line: wormscore <command> <project folder> ..."""
|
|
2
|
+
import argparse
|
|
3
|
+
import json
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from . import __version__
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main(argv=None):
|
|
11
|
+
p = argparse.ArgumentParser(prog="wormscore", description="Blind scoring and measurement of neurons in confocal stacks.")
|
|
12
|
+
p.add_argument("--version", action="version", version=f"wormscore {__version__}")
|
|
13
|
+
sub = p.add_subparsers(dest="cmd", required=True)
|
|
14
|
+
|
|
15
|
+
s = sub.add_parser("init", help="create a project folder with a config.json to edit")
|
|
16
|
+
s.add_argument("project")
|
|
17
|
+
s.add_argument("--name", default="My project")
|
|
18
|
+
s = sub.add_parser("demo", help="create a demo project with simulated worms")
|
|
19
|
+
s.add_argument("project")
|
|
20
|
+
s.add_argument("--n", type=int, default=10, help="simulated worms per genotype")
|
|
21
|
+
s.add_argument("--real", action="store_true",
|
|
22
|
+
help="download 4 real worm heads (about 150 MB, CC BY 4.0) instead of simulating")
|
|
23
|
+
s = sub.add_parser("copy", help="copy a data folder and verify every file by SHA-256")
|
|
24
|
+
s.add_argument("source")
|
|
25
|
+
s.add_argument("destination")
|
|
26
|
+
s = sub.add_parser("inventory", help="list every file and image in the project's sources")
|
|
27
|
+
s.add_argument("project")
|
|
28
|
+
s = sub.add_parser("prepare", help="build the blind image set, key and automatic measurements")
|
|
29
|
+
s.add_argument("project")
|
|
30
|
+
s.add_argument("--reassign-codes", action="store_true", help="new codes (only allowed before any scoring)")
|
|
31
|
+
s.add_argument("--add-new-images", dest="add", action="store_true",
|
|
32
|
+
help="code only images not yet in the key; existing codes are kept")
|
|
33
|
+
s = sub.add_parser("app", help="open the scoring app")
|
|
34
|
+
s.add_argument("project")
|
|
35
|
+
s.add_argument("--port", type=int, default=8765)
|
|
36
|
+
s.add_argument("--no-browser", action="store_true")
|
|
37
|
+
s = sub.add_parser("unblind", help="join scores, measurements and the key (after scoring)")
|
|
38
|
+
s.add_argument("project")
|
|
39
|
+
s.add_argument("--i-have-finished-scoring", dest="finished", action="store_true")
|
|
40
|
+
s.add_argument("--anyway", action="store_true", help="unblind below the planned minimum number of scores")
|
|
41
|
+
|
|
42
|
+
a = p.parse_args(argv)
|
|
43
|
+
try:
|
|
44
|
+
if a.cmd == "init":
|
|
45
|
+
from .config import template
|
|
46
|
+
proj = Path(a.project)
|
|
47
|
+
proj.mkdir(parents=True, exist_ok=True)
|
|
48
|
+
cfg = proj / "config.json"
|
|
49
|
+
if cfg.exists():
|
|
50
|
+
sys.exit(f"{cfg} already exists; not overwriting.")
|
|
51
|
+
cfg.write_text(json.dumps(template(a.name), indent=2), encoding="utf-8")
|
|
52
|
+
print(f"Created {cfg}. Edit 'sources' to point at your images, then run 'wormscore inventory {proj}'.")
|
|
53
|
+
elif a.cmd == "demo":
|
|
54
|
+
if a.real:
|
|
55
|
+
from .realdemo import make_real_demo
|
|
56
|
+
make_real_demo(a.project)
|
|
57
|
+
else:
|
|
58
|
+
from .demo import make_demo
|
|
59
|
+
make_demo(a.project, n_per_group=a.n)
|
|
60
|
+
print(f"Next: wormscore inventory {a.project} && wormscore prepare {a.project} && wormscore app {a.project}")
|
|
61
|
+
elif a.cmd == "copy":
|
|
62
|
+
from .copydata import copy_verified
|
|
63
|
+
copy_verified(a.source, a.destination)
|
|
64
|
+
elif a.cmd == "inventory":
|
|
65
|
+
from .pipeline import inventory
|
|
66
|
+
inventory(a.project)
|
|
67
|
+
elif a.cmd == "prepare":
|
|
68
|
+
from .pipeline import prepare
|
|
69
|
+
prepare(a.project, reassign=a.reassign_codes, add=a.add)
|
|
70
|
+
elif a.cmd == "app":
|
|
71
|
+
from .server import serve
|
|
72
|
+
serve(a.project, port=a.port, open_browser=not a.no_browser)
|
|
73
|
+
elif a.cmd == "unblind":
|
|
74
|
+
from .unblind import unblind
|
|
75
|
+
unblind(a.project, finished=a.finished, anyway=a.anyway)
|
|
76
|
+
except FileNotFoundError as exc:
|
|
77
|
+
sys.exit(str(exc))
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
if __name__ == "__main__":
|
|
81
|
+
main()
|