phasor-handler 2.3.0__tar.gz → 3.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.
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/CONTRIBUTING.md +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/LICENSE.md +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/MANIFEST.in +0 -0
- {phasor_handler-2.3.0/phasor_handler.egg-info → phasor_handler-3.1.0}/PKG-INFO +176 -136
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/README.md +56 -16
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/environment.yml +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/__init__.py +1 -1
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/app.py +102 -28
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/img/icons/chevron-down.svg +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/img/icons/chevron-up.svg +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/img/logo.ico +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/models/dir_manager.py +148 -100
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/scripts/contrast.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/scripts/convert.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/scripts/meta_reader.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/scripts/plot.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/scripts/register.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/themes/__init__.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/themes/dark_theme.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/tools/__init__.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/tools/check_stylesheet.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/tools/misc.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/__init__.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/__init__.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/bnc.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/circle_roi.py +15 -4
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/image_view.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/meta_info.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/roi_list.py +39 -18
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/trace_plot.py +212 -56
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/view.py +4 -3
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/conversion/view.py +22 -12
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/registration/view.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/secondlevel/view.py +117 -36
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/__init__.py +5 -4
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/analysis_worker.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/conversion_worker.py +0 -0
- phasor_handler-3.1.0/phasor_handler/workers/convert_register_worker.py +214 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/histogram_worker.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/registration_worker.py +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/secondlevel_worker.py +195 -148
- {phasor_handler-2.3.0 → phasor_handler-3.1.0/phasor_handler.egg-info}/PKG-INFO +176 -136
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler.egg-info/SOURCES.txt +1 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler.egg-info/dependency_links.txt +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler.egg-info/entry_points.txt +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler.egg-info/requires.txt +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler.egg-info/top_level.txt +0 -0
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/pyproject.toml +1 -1
- {phasor_handler-2.3.0 → phasor_handler-3.1.0}/setup.cfg +4 -4
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,136 +1,176 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: phasor-handler
|
|
3
|
-
Version:
|
|
4
|
-
Summary: A PyQt6 GUI toolbox for processing two-photon phasor imaging data
|
|
5
|
-
Author-email: Josia Shemuel <joshemuel@users.noreply.github.com>
|
|
6
|
-
License: MIT License
|
|
7
|
-
|
|
8
|
-
Copyright (c) 2025 Josia Shemuel
|
|
9
|
-
|
|
10
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
-
in the Software without restriction, including without limitation the rights
|
|
13
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
-
furnished to do so, subject to the following conditions:
|
|
16
|
-
|
|
17
|
-
The above copyright notice and this permission notice shall be included in all
|
|
18
|
-
copies or substantial portions of the Software.
|
|
19
|
-
|
|
20
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
-
SOFTWARE.
|
|
27
|
-
Project-URL: Homepage, https://github.com/joshemuel/Phasor-Handler
|
|
28
|
-
Project-URL: Repository, https://github.com/joshemuel/Phasor-Handler
|
|
29
|
-
Project-URL: Issues, https://github.com/joshemuel/Phasor-Handler/issues
|
|
30
|
-
Keywords: two-photon,phasor,imaging,calcium,neuroscience,suite2p
|
|
31
|
-
Classifier: Development Status :: 4 - Beta
|
|
32
|
-
Classifier: Intended Audience :: Science/Research
|
|
33
|
-
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
34
|
-
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
35
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
-
Classifier: Programming Language :: Python :: 3
|
|
37
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
38
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
39
|
-
Classifier: Environment :: X11 Applications :: Qt
|
|
40
|
-
Requires-Python: <3.10,>=3.9.23
|
|
41
|
-
Description-Content-Type: text/markdown
|
|
42
|
-
License-File: LICENSE.md
|
|
43
|
-
Requires-Dist: PyQt6>=6.4.0
|
|
44
|
-
Requires-Dist: numpy<2.0.0,>=1.21.0
|
|
45
|
-
Requires-Dist: matplotlib>=3.5.0
|
|
46
|
-
Requires-Dist: tifffile>=2021.11.2
|
|
47
|
-
Requires-Dist: pyyaml>=6.0
|
|
48
|
-
Requires-Dist: suite2p>=0.14.0
|
|
49
|
-
Requires-Dist: pyqtdarktheme>=1.0.0
|
|
50
|
-
Requires-Dist: Pillow>=9.0.0
|
|
51
|
-
Requires-Dist: scikit-image>=0.19.0
|
|
52
|
-
Requires-Dist: scipy>=1.7.0
|
|
53
|
-
Requires-Dist: npTDMS>=1.2.0
|
|
54
|
-
Requires-Dist: pandas>=1.3.0
|
|
55
|
-
Provides-Extra: dev
|
|
56
|
-
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
57
|
-
Requires-Dist: black>=22.0.0; extra == "dev"
|
|
58
|
-
Requires-Dist: flake8>=4.0.0; extra == "dev"
|
|
59
|
-
Dynamic: license-file
|
|
60
|
-
|
|
61
|
-
# Phasor-Handler (Windows)
|
|
62
|
-
|
|
63
|
-
Phasor Handler is a toolbox for processing raw two-photon phasor imaging data:
|
|
64
|
-
It provides a PyQt6 GUI for viewing registered or raw stacks (Ch1/Ch2), z-projections (std/max/mean), drawing/storing ROIs, overlaying stimulated ROIs from metadata, and exporting ROI traces.
|
|
65
|
-
|
|
66
|
-
> ⚠️ **Platform:** Windows 10/11 only
|
|
67
|
-
>
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
## Features
|
|
72
|
-
|
|
73
|
-
- Load **registered TIFF** (`Ch1-reg.tif`, `Ch2-reg.tif`) or **raw NPY** fallbacks (`ImageData_Ch0_TP0000000.npy`, `ImageData_Ch1_TP0000000.npy`)
|
|
74
|
-
- Linear and non-linear motion-correct **TIFF images** using Suite2p
|
|
75
|
-
- Automated cell detection using Suite2p
|
|
76
|
-
- Channel switching (Ch1/Ch2) and **Composite (G/R)**
|
|
77
|
-
- **Z-projections**: standard deviation, max, mean
|
|
78
|
-
- **
|
|
79
|
-
- **
|
|
80
|
-
- **
|
|
81
|
-
- **
|
|
82
|
-
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: phasor-handler
|
|
3
|
+
Version: 3.1.0
|
|
4
|
+
Summary: A PyQt6 GUI toolbox for processing two-photon phasor imaging data
|
|
5
|
+
Author-email: Josia Shemuel <joshemuel@users.noreply.github.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 Josia Shemuel
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
Project-URL: Homepage, https://github.com/joshemuel/Phasor-Handler
|
|
28
|
+
Project-URL: Repository, https://github.com/joshemuel/Phasor-Handler
|
|
29
|
+
Project-URL: Issues, https://github.com/joshemuel/Phasor-Handler/issues
|
|
30
|
+
Keywords: two-photon,phasor,imaging,calcium,neuroscience,suite2p
|
|
31
|
+
Classifier: Development Status :: 4 - Beta
|
|
32
|
+
Classifier: Intended Audience :: Science/Research
|
|
33
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
34
|
+
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
38
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
39
|
+
Classifier: Environment :: X11 Applications :: Qt
|
|
40
|
+
Requires-Python: <3.10,>=3.9.23
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE.md
|
|
43
|
+
Requires-Dist: PyQt6>=6.4.0
|
|
44
|
+
Requires-Dist: numpy<2.0.0,>=1.21.0
|
|
45
|
+
Requires-Dist: matplotlib>=3.5.0
|
|
46
|
+
Requires-Dist: tifffile>=2021.11.2
|
|
47
|
+
Requires-Dist: pyyaml>=6.0
|
|
48
|
+
Requires-Dist: suite2p>=0.14.0
|
|
49
|
+
Requires-Dist: pyqtdarktheme>=1.0.0
|
|
50
|
+
Requires-Dist: Pillow>=9.0.0
|
|
51
|
+
Requires-Dist: scikit-image>=0.19.0
|
|
52
|
+
Requires-Dist: scipy>=1.7.0
|
|
53
|
+
Requires-Dist: npTDMS>=1.2.0
|
|
54
|
+
Requires-Dist: pandas>=1.3.0
|
|
55
|
+
Provides-Extra: dev
|
|
56
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
57
|
+
Requires-Dist: black>=22.0.0; extra == "dev"
|
|
58
|
+
Requires-Dist: flake8>=4.0.0; extra == "dev"
|
|
59
|
+
Dynamic: license-file
|
|
60
|
+
|
|
61
|
+
# Phasor-Handler (Windows)
|
|
62
|
+
|
|
63
|
+
Phasor Handler is a toolbox for processing raw two-photon phasor imaging data: **convert → register → explore → extract calcium traces**.
|
|
64
|
+
It provides a PyQt6 GUI for viewing registered or raw stacks (Ch1/Ch2), z-projections (std/max/mean), drawing/storing ROIs, overlaying stimulated ROIs from metadata, and exporting ROI traces.
|
|
65
|
+
|
|
66
|
+
> ⚠️ **Platform:** Windows 10/11 only
|
|
67
|
+
> 🚀 **Version 3.0** — Latest stable release
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Features
|
|
72
|
+
|
|
73
|
+
- Load **registered TIFF** (`Ch1-reg.tif`, `Ch2-reg.tif`) or **raw NPY** fallbacks (`ImageData_Ch0_TP0000000.npy`, `ImageData_Ch1_TP0000000.npy`)
|
|
74
|
+
- Linear and non-linear motion-correct **TIFF images** using Suite2p
|
|
75
|
+
- Automated cell detection using Suite2p
|
|
76
|
+
- Channel switching (Ch1/Ch2) and **Composite (G/R)**
|
|
77
|
+
- **Z-projections**: standard deviation, max, mean
|
|
78
|
+
- **Brightness & Contrast (BnC)**: adjust image display settings
|
|
79
|
+
- **ROI tools**: draw elliptical ROIs, **freehand drawing tool**, translate or rotate ROIs, **move multiple ROIs**, save/load as JSON, quick-select saved ROIs
|
|
80
|
+
- **Metadata viewer**: inspect experiment metadata directly in the application
|
|
81
|
+
- **Second-level analysis viewer**: explore and visualize second-level analysis results
|
|
82
|
+
- **Stimulus overlay**: show stimulated ROI locations from experiment metadata and add to the saved ROIs
|
|
83
|
+
- **Trace plotting**: configurable formula, custom y-limits, frame/time (s) x-axis
|
|
84
|
+
- **Export**: write per-ROI traces for all frames to `.txt` (tab-separated)
|
|
85
|
+
- Keyboard: `R` save/add ROI, `Delete` remove selected ROI, `Esc` clear selection, `Alt+S` load stimulated ROIs, `Right Click + drag` translate selected ROI, `Y` toggle right click to rotation mode
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Input data layout
|
|
90
|
+
|
|
91
|
+
For each dataset directory, Phasor Handler looks for any of:
|
|
92
|
+
|
|
93
|
+
- Ch1-reg.tif
|
|
94
|
+
- Ch2-reg. tif # optional
|
|
95
|
+
- ImageData_Ch0_TP0000000.npy # raw fallback for Ch1
|
|
96
|
+
- ImageData_Ch1_TP0000000.npy # optional raw fallback for Ch2
|
|
97
|
+
- experiment_summary.pkl # optional metadata (or .json)
|
|
98
|
+
|
|
99
|
+
Registered TIFFs are preferred when available; raw NPYs are used as fallback.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Installation
|
|
104
|
+
|
|
105
|
+
Phasor Handler is now available on **PyPI** and can be installed via pip or from source using Conda/Mamba.
|
|
106
|
+
|
|
107
|
+
### Option 1: Install via pip (Recommended)
|
|
108
|
+
|
|
109
|
+
The easiest way to install Phasor Handler is through pip:
|
|
110
|
+
|
|
111
|
+
```powershell
|
|
112
|
+
pip install phasor-handler
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
After installation, you can run the application:
|
|
116
|
+
|
|
117
|
+
```powershell
|
|
118
|
+
phasor-handler
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**PyPI Package:** [https://pypi.org/project/phasor-handler/](https://pypi.org/project/phasor-handler/)
|
|
122
|
+
|
|
123
|
+
### Option 2: Install from source (Windows, Conda)
|
|
124
|
+
|
|
125
|
+
This project provides an `environment.yml` for Windows. The environment is large (GUI, image I/O, napari/suite2p), so **mamba** is recommended, but `conda` works too.
|
|
126
|
+
|
|
127
|
+
#### 1) Install Conda/Mamba (if needed)
|
|
128
|
+
- Install **Miniconda** or **Mambaforge** on Windows.
|
|
129
|
+
- (Optional) Add mamba for faster solves:
|
|
130
|
+
```powershell
|
|
131
|
+
conda install -n base -c conda-forge mamba
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### 2) Get the code
|
|
135
|
+
- Clone the repo and change into it:
|
|
136
|
+
```powershell
|
|
137
|
+
git clone https://github.com/joshemuel/Phasor-Handler.git
|
|
138
|
+
cd Phasor-Handler
|
|
139
|
+
```
|
|
140
|
+
- Alternatively, you can download the entire project as a zip file, unzip it, then open that directory in **Miniconda**
|
|
141
|
+
|
|
142
|
+
#### 3) Create the environment
|
|
143
|
+
- Using mamba:
|
|
144
|
+
```powershell
|
|
145
|
+
mamba env create -f environment.yml
|
|
146
|
+
```
|
|
147
|
+
- Using conda:
|
|
148
|
+
```powershell
|
|
149
|
+
conda env create -f environment.yml
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### 4) Activate and run
|
|
153
|
+
- Before running the toolbox, activate the environment:
|
|
154
|
+
```powershell
|
|
155
|
+
conda activate suite2p
|
|
156
|
+
python app.py
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Update (Windows, Conda)
|
|
162
|
+
|
|
163
|
+
### If installed via pip:
|
|
164
|
+
```powershell
|
|
165
|
+
pip install --upgrade phasor-handler
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### If installed from source:
|
|
169
|
+
|
|
170
|
+
#### 1) Go to your local repo and pull the latest code from the branch you use
|
|
171
|
+
```powershell
|
|
172
|
+
cd Phasor-Handler
|
|
173
|
+
git pull --ff-only
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Phasor-Handler (Windows)
|
|
2
2
|
|
|
3
|
-
Phasor Handler is a toolbox for processing raw two-photon phasor imaging data:
|
|
3
|
+
Phasor Handler is a toolbox for processing raw two-photon phasor imaging data: **convert → register → explore → extract calcium traces**.
|
|
4
4
|
It provides a PyQt6 GUI for viewing registered or raw stacks (Ch1/Ch2), z-projections (std/max/mean), drawing/storing ROIs, overlaying stimulated ROIs from metadata, and exporting ROI traces.
|
|
5
5
|
|
|
6
6
|
> ⚠️ **Platform:** Windows 10/11 only
|
|
7
|
-
>
|
|
7
|
+
> 🚀 **Version 3.0** — Latest stable release
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -15,7 +15,10 @@ It provides a PyQt6 GUI for viewing registered or raw stacks (Ch1/Ch2), z-projec
|
|
|
15
15
|
- Automated cell detection using Suite2p
|
|
16
16
|
- Channel switching (Ch1/Ch2) and **Composite (G/R)**
|
|
17
17
|
- **Z-projections**: standard deviation, max, mean
|
|
18
|
-
- **
|
|
18
|
+
- **Brightness & Contrast (BnC)**: adjust image display settings
|
|
19
|
+
- **ROI tools**: draw elliptical ROIs, **freehand drawing tool**, translate or rotate ROIs, **move multiple ROIs**, save/load as JSON, quick-select saved ROIs
|
|
20
|
+
- **Metadata viewer**: inspect experiment metadata directly in the application
|
|
21
|
+
- **Second-level analysis viewer**: explore and visualize second-level analysis results
|
|
19
22
|
- **Stimulus overlay**: show stimulated ROI locations from experiment metadata and add to the saved ROIs
|
|
20
23
|
- **Trace plotting**: configurable formula, custom y-limits, frame/time (s) x-axis
|
|
21
24
|
- **Export**: write per-ROI traces for all frames to `.txt` (tab-separated)
|
|
@@ -25,10 +28,10 @@ It provides a PyQt6 GUI for viewing registered or raw stacks (Ch1/Ch2), z-projec
|
|
|
25
28
|
|
|
26
29
|
## Input data layout
|
|
27
30
|
|
|
28
|
-
For each dataset directory, Phasor Handler looks for any of:
|
|
31
|
+
For each dataset directory, Phasor Handler looks for any of:
|
|
29
32
|
|
|
30
33
|
- Ch1-reg.tif
|
|
31
|
-
- Ch2-reg.tif # optional
|
|
34
|
+
- Ch2-reg. tif # optional
|
|
32
35
|
- ImageData_Ch0_TP0000000.npy # raw fallback for Ch1
|
|
33
36
|
- ImageData_Ch1_TP0000000.npy # optional raw fallback for Ch2
|
|
34
37
|
- experiment_summary.pkl # optional metadata (or .json)
|
|
@@ -37,40 +40,77 @@ Registered TIFFs are preferred when available; raw NPYs are used as fallback.
|
|
|
37
40
|
|
|
38
41
|
---
|
|
39
42
|
|
|
40
|
-
## Installation
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
Phasor Handler is now available on **PyPI** and can be installed via pip or from source using Conda/Mamba.
|
|
46
|
+
|
|
47
|
+
### Option 1: Install via pip (Recommended)
|
|
48
|
+
|
|
49
|
+
The easiest way to install Phasor Handler is through pip:
|
|
50
|
+
|
|
51
|
+
```powershell
|
|
52
|
+
pip install phasor-handler
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
After installation, you can run the application:
|
|
56
|
+
|
|
57
|
+
```powershell
|
|
58
|
+
phasor-handler
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**PyPI Package:** [https://pypi.org/project/phasor-handler/](https://pypi.org/project/phasor-handler/)
|
|
62
|
+
|
|
63
|
+
### Option 2: Install from source (Windows, Conda)
|
|
41
64
|
|
|
42
65
|
This project provides an `environment.yml` for Windows. The environment is large (GUI, image I/O, napari/suite2p), so **mamba** is recommended, but `conda` works too.
|
|
43
66
|
|
|
44
|
-
|
|
67
|
+
#### 1) Install Conda/Mamba (if needed)
|
|
45
68
|
- Install **Miniconda** or **Mambaforge** on Windows.
|
|
46
69
|
- (Optional) Add mamba for faster solves:
|
|
47
70
|
```powershell
|
|
48
71
|
conda install -n base -c conda-forge mamba
|
|
72
|
+
```
|
|
49
73
|
|
|
50
|
-
|
|
51
|
-
- Clone the repo and change it
|
|
74
|
+
#### 2) Get the code
|
|
75
|
+
- Clone the repo and change into it:
|
|
52
76
|
```powershell
|
|
53
77
|
git clone https://github.com/joshemuel/Phasor-Handler.git
|
|
54
|
-
chdir Phasor-Handler
|
|
55
|
-
- Alternatively, you can download the entire project as a zip file, unzip it, then open that directory in **Miniconda**
|
|
56
78
|
cd Phasor-Handler
|
|
79
|
+
```
|
|
80
|
+
- Alternatively, you can download the entire project as a zip file, unzip it, then open that directory in **Miniconda**
|
|
57
81
|
|
|
58
|
-
|
|
82
|
+
#### 3) Create the environment
|
|
59
83
|
- Using mamba:
|
|
60
84
|
```powershell
|
|
61
85
|
mamba env create -f environment.yml
|
|
86
|
+
```
|
|
62
87
|
- Using conda:
|
|
63
88
|
```powershell
|
|
64
89
|
conda env create -f environment.yml
|
|
90
|
+
```
|
|
65
91
|
|
|
66
|
-
|
|
67
|
-
- Before running the toolbox, activate the environment
|
|
92
|
+
#### 4) Activate and run
|
|
93
|
+
- Before running the toolbox, activate the environment:
|
|
68
94
|
```powershell
|
|
69
95
|
conda activate suite2p
|
|
70
96
|
python app.py
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
71
101
|
## Update (Windows, Conda)
|
|
72
102
|
|
|
73
|
-
###
|
|
103
|
+
### If installed via pip:
|
|
74
104
|
```powershell
|
|
75
|
-
|
|
105
|
+
pip install --upgrade phasor-handler
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### If installed from source:
|
|
109
|
+
|
|
110
|
+
#### 1) Go to your local repo and pull the latest code from the branch you use
|
|
111
|
+
```powershell
|
|
112
|
+
cd Phasor-Handler
|
|
76
113
|
git pull --ff-only
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
File without changes
|
|
@@ -4,6 +4,6 @@ Phasor Handler - Two-Photon Phasor Imaging Data Processor
|
|
|
4
4
|
A PyQt6 GUI toolbox for processing two-photon phasor imaging data.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = "
|
|
7
|
+
__version__ = "3.1.0"
|
|
8
8
|
__author__ = "Josia Shemuel"
|
|
9
9
|
__all__ = ["app", "widgets", "workers", "models", "scripts", "tools", "themes"]
|
|
@@ -14,7 +14,7 @@ from PyQt6.QtCore import Qt
|
|
|
14
14
|
from PyQt6.QtCore import QThread
|
|
15
15
|
|
|
16
16
|
from .widgets import ConversionWidget, RegistrationWidget, AnalysisWidget, SecondLevelWidget
|
|
17
|
-
from .workers import RegistrationWorker, ConversionWorker
|
|
17
|
+
from .workers import RegistrationWorker, ConversionWorker, ConvertRegisterWorker
|
|
18
18
|
from .models.dir_manager import DirManager
|
|
19
19
|
from .themes import apply_dark_theme
|
|
20
20
|
import qdarktheme
|
|
@@ -109,26 +109,29 @@ class MainWindow(QMainWindow):
|
|
|
109
109
|
if hasattr(self, 'analysis_list_widget'):
|
|
110
110
|
self.analysis_list_widget.clear()
|
|
111
111
|
|
|
112
|
-
from PyQt6.QtWidgets import QListWidgetItem
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
item
|
|
117
|
-
item.
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
item
|
|
123
|
-
item.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
112
|
+
from PyQt6.QtWidgets import QListWidgetItem
|
|
113
|
+
# Conversion and Registration tabs keep insertion order
|
|
114
|
+
for full_path, display_name in self.dir_manager.get_display_names():
|
|
115
|
+
if hasattr(self, 'conv_list_widget'):
|
|
116
|
+
item = QListWidgetItem(display_name)
|
|
117
|
+
item.setToolTip(full_path)
|
|
118
|
+
item.setData(Qt.ItemDataRole.UserRole, full_path)
|
|
119
|
+
self.conv_list_widget.addItem(item)
|
|
120
|
+
if hasattr(self, 'reg_list_widget'):
|
|
121
|
+
try:
|
|
122
|
+
item = QListWidgetItem(display_name)
|
|
123
|
+
item.setToolTip(full_path)
|
|
124
|
+
item.setData(Qt.ItemDataRole.UserRole, full_path)
|
|
125
|
+
self.reg_list_widget.addItem(item)
|
|
126
|
+
except RuntimeError:
|
|
127
|
+
pass
|
|
128
|
+
# Analysis list is sorted by capture time
|
|
129
|
+
if hasattr(self, 'analysis_list_widget'):
|
|
130
|
+
for full_path, display_name in self.dir_manager.get_display_names(sort_by_time=True):
|
|
131
|
+
item = QListWidgetItem(display_name)
|
|
132
|
+
item.setToolTip(full_path)
|
|
133
|
+
item.setData(Qt.ItemDataRole.UserRole, full_path)
|
|
134
|
+
self.analysis_list_widget.addItem(item)
|
|
132
135
|
|
|
133
136
|
def on_tab_changed(self, idx):
|
|
134
137
|
# When switching to first level tab, refresh its directory list
|
|
@@ -145,8 +148,8 @@ class MainWindow(QMainWindow):
|
|
|
145
148
|
self.analysis_list_widget.blockSignals(True)
|
|
146
149
|
self.analysis_list_widget.clear()
|
|
147
150
|
|
|
148
|
-
from PyQt6.QtWidgets import QListWidgetItem
|
|
149
|
-
for full_path, display_name in self.dir_manager.get_display_names():
|
|
151
|
+
from PyQt6.QtWidgets import QListWidgetItem
|
|
152
|
+
for full_path, display_name in self.dir_manager.get_display_names(sort_by_time=True):
|
|
150
153
|
item = QListWidgetItem(display_name)
|
|
151
154
|
item.setToolTip(full_path)
|
|
152
155
|
item.setData(Qt.ItemDataRole.UserRole, full_path)
|
|
@@ -258,11 +261,82 @@ class MainWindow(QMainWindow):
|
|
|
258
261
|
del self._reg_worker
|
|
259
262
|
del self._reg_thread
|
|
260
263
|
|
|
261
|
-
self._reg_worker.finished.connect(_on_finished)
|
|
262
|
-
self._reg_worker.error.connect(lambda e: self.reg_log.append(f"ERROR: {e}"))
|
|
263
|
-
self._reg_thread.start()
|
|
264
|
-
|
|
265
|
-
def
|
|
264
|
+
self._reg_worker.finished.connect(_on_finished)
|
|
265
|
+
self._reg_worker.error.connect(lambda e: self.reg_log.append(f"ERROR: {e}"))
|
|
266
|
+
self._reg_thread.start()
|
|
267
|
+
|
|
268
|
+
def run_convert_and_register(self):
|
|
269
|
+
"""Run conversion followed by registration on all directories in one step."""
|
|
270
|
+
if not self.selected_dirs:
|
|
271
|
+
QMessageBox.warning(self, "No Directories",
|
|
272
|
+
"Please add at least one directory to the list before running.")
|
|
273
|
+
return
|
|
274
|
+
|
|
275
|
+
mode = self.mode_combo.currentText().lower()
|
|
276
|
+
|
|
277
|
+
# Gather registration parameters from the Registration tab
|
|
278
|
+
reg_params = {}
|
|
279
|
+
if hasattr(self, 'param_names') and hasattr(self, 'param_edits'):
|
|
280
|
+
for name, edit in zip(self.param_names, self.param_edits):
|
|
281
|
+
value = edit.text().strip()
|
|
282
|
+
if value:
|
|
283
|
+
reg_params[name] = value
|
|
284
|
+
|
|
285
|
+
combine = True
|
|
286
|
+
if hasattr(self, 'combine_checkbox'):
|
|
287
|
+
combine = self.combine_checkbox.isChecked()
|
|
288
|
+
|
|
289
|
+
# Disable the button while running
|
|
290
|
+
run_btn = None
|
|
291
|
+
for w in self.findChildren(QPushButton):
|
|
292
|
+
if w.text().startswith("Convert + Register"):
|
|
293
|
+
run_btn = w
|
|
294
|
+
break
|
|
295
|
+
if run_btn:
|
|
296
|
+
run_btn.setEnabled(False)
|
|
297
|
+
|
|
298
|
+
self.conv_log.clear()
|
|
299
|
+
if hasattr(self, 'reg_log'):
|
|
300
|
+
self.reg_log.clear()
|
|
301
|
+
|
|
302
|
+
# Create thread and worker
|
|
303
|
+
self._cr_thread = QThread()
|
|
304
|
+
self._cr_worker = ConvertRegisterWorker(
|
|
305
|
+
self.selected_dirs.copy(), mode, reg_params, combine)
|
|
306
|
+
self._cr_worker.moveToThread(self._cr_thread)
|
|
307
|
+
|
|
308
|
+
# Connect signals
|
|
309
|
+
self._cr_thread.started.connect(self._cr_worker.run)
|
|
310
|
+
def _cr_log(s):
|
|
311
|
+
self.conv_log.append(s)
|
|
312
|
+
if hasattr(self, 'reg_log'):
|
|
313
|
+
self.reg_log.append(s)
|
|
314
|
+
QApplication.processEvents()
|
|
315
|
+
self._cr_worker.log.connect(_cr_log)
|
|
316
|
+
|
|
317
|
+
def _on_finished():
|
|
318
|
+
if run_btn:
|
|
319
|
+
run_btn.setEnabled(True)
|
|
320
|
+
self._cr_thread.quit()
|
|
321
|
+
self._cr_thread.wait()
|
|
322
|
+
self._cr_worker.deleteLater()
|
|
323
|
+
del self._cr_worker
|
|
324
|
+
del self._cr_thread
|
|
325
|
+
|
|
326
|
+
def _on_error(err_msg):
|
|
327
|
+
self.conv_log.append(f"[ERROR] {err_msg}")
|
|
328
|
+
if hasattr(self, 'reg_log'):
|
|
329
|
+
self.reg_log.append(f"[ERROR] {err_msg}")
|
|
330
|
+
QMessageBox.critical(self, "Convert+Register Error",
|
|
331
|
+
f"An error occurred:\n{err_msg}")
|
|
332
|
+
|
|
333
|
+
self._cr_worker.finished.connect(_on_finished)
|
|
334
|
+
self._cr_worker.error.connect(_on_error)
|
|
335
|
+
|
|
336
|
+
# Start the thread
|
|
337
|
+
self._cr_thread.start()
|
|
338
|
+
|
|
339
|
+
def main():
|
|
266
340
|
app = QApplication(sys.argv)
|
|
267
341
|
try:
|
|
268
342
|
qdarktheme.setup_theme() # or your own apply_dark_theme()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|