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.
Files changed (49) hide show
  1. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/CONTRIBUTING.md +0 -0
  2. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/LICENSE.md +0 -0
  3. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/MANIFEST.in +0 -0
  4. {phasor_handler-2.3.0/phasor_handler.egg-info → phasor_handler-3.1.0}/PKG-INFO +176 -136
  5. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/README.md +56 -16
  6. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/environment.yml +0 -0
  7. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/__init__.py +1 -1
  8. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/app.py +102 -28
  9. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/img/icons/chevron-down.svg +0 -0
  10. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/img/icons/chevron-up.svg +0 -0
  11. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/img/logo.ico +0 -0
  12. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/models/dir_manager.py +148 -100
  13. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/scripts/contrast.py +0 -0
  14. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/scripts/convert.py +0 -0
  15. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/scripts/meta_reader.py +0 -0
  16. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/scripts/plot.py +0 -0
  17. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/scripts/register.py +0 -0
  18. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/themes/__init__.py +0 -0
  19. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/themes/dark_theme.py +0 -0
  20. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/tools/__init__.py +0 -0
  21. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/tools/check_stylesheet.py +0 -0
  22. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/tools/misc.py +0 -0
  23. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/__init__.py +0 -0
  24. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/__init__.py +0 -0
  25. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/bnc.py +0 -0
  26. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/circle_roi.py +15 -4
  27. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/image_view.py +0 -0
  28. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/meta_info.py +0 -0
  29. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/roi_list.py +39 -18
  30. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/components/trace_plot.py +212 -56
  31. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/analysis/view.py +4 -3
  32. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/conversion/view.py +22 -12
  33. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/registration/view.py +0 -0
  34. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/widgets/secondlevel/view.py +117 -36
  35. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/__init__.py +5 -4
  36. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/analysis_worker.py +0 -0
  37. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/conversion_worker.py +0 -0
  38. phasor_handler-3.1.0/phasor_handler/workers/convert_register_worker.py +214 -0
  39. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/histogram_worker.py +0 -0
  40. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/registration_worker.py +0 -0
  41. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler/workers/secondlevel_worker.py +195 -148
  42. {phasor_handler-2.3.0 → phasor_handler-3.1.0/phasor_handler.egg-info}/PKG-INFO +176 -136
  43. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler.egg-info/SOURCES.txt +1 -0
  44. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler.egg-info/dependency_links.txt +0 -0
  45. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler.egg-info/entry_points.txt +0 -0
  46. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler.egg-info/requires.txt +0 -0
  47. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/phasor_handler.egg-info/top_level.txt +0 -0
  48. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/pyproject.toml +1 -1
  49. {phasor_handler-2.3.0 → phasor_handler-3.1.0}/setup.cfg +4 -4
@@ -1,136 +1,176 @@
1
- Metadata-Version: 2.4
2
- Name: phasor-handler
3
- Version: 2.3.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
- > 🧪 Status: actively developed (Brightness & Contrast dialog is WIP)
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
- - **ROI tools**: draw elliptical ROIs, translate or rotate ROIs, save/load as JSON, quick-select saved ROIs
79
- - **Stimulus overlay**: show stimulated ROI locations from experiment metadata and add to the saved ROIs
80
- - **Trace plotting**: configurable formula, custom y-limits, frame/time (s) x-axis
81
- - **Export**: write per-ROI traces for all frames to `.txt` (tab-separated)
82
- - 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
83
-
84
- ---
85
-
86
- ## Input data layout
87
-
88
- For each dataset directory, Phasor Handler looks for any of:
89
-
90
- - Ch1-reg.tif
91
- - Ch2-reg.tif # optional
92
- - ImageData_Ch0_TP0000000.npy # raw fallback for Ch1
93
- - ImageData_Ch1_TP0000000.npy # optional raw fallback for Ch2
94
- - experiment_summary.pkl # optional metadata (or .json)
95
-
96
- Registered TIFFs are preferred when available; raw NPYs are used as fallback.
97
-
98
- ---
99
-
100
- ## Installation (Windows, Conda)
101
-
102
- 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.
103
-
104
- ### 1) Install Conda/Mamba (if needed)
105
- - Install **Miniconda** or **Mambaforge** on Windows.
106
- - (Optional) Add mamba for faster solves:
107
- ```powershell
108
- conda install -n base -c conda-forge mamba
109
-
110
- ### 2) Get the code
111
- - Clone the repo and change it into
112
- ```powershell
113
- git clone https://github.com/joshemuel/Phasor-Handler.git
114
- chdir Phasor-Handler
115
- - Alternatively, you can download the entire project as a zip file, unzip it, then open that directory in **Miniconda**
116
- cd Phasor-Handler
117
-
118
- ### 3) Create the environment
119
- - Using mamba:
120
- ```powershell
121
- mamba env create -f environment.yml
122
- - Using conda:
123
- ```powershell
124
- conda env create -f environment.yml
125
-
126
- # 4) Activate and run
127
- - Before running the toolbox, activate the environment
128
- ```powershell
129
- conda activate suite2p
130
- python app.py
131
- ## Update (Windows, Conda)
132
-
133
- ### 1) Go to your local repo and pull the latest code from the branch you use
134
- ```powershell
135
- chdir Phasor-Handler
136
- git pull --ff-only
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: **convert → register → explore → extract calcium traces**.
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
- > 🧪 Status: actively developed (Brightness & Contrast dialog is WIP)
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
- - **ROI tools**: draw elliptical ROIs, translate or rotate ROIs, save/load as JSON, quick-select saved ROIs
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 (Windows, Conda)
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
- ### 1) Install Conda/Mamba (if needed)
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
- ### 2) Get the code
51
- - Clone the repo and change it into
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
- ### 3) Create the environment
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
- # 4) Activate and run
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
- ### 1) Go to your local repo and pull the latest code from the branch you use
103
+ ### If installed via pip:
74
104
  ```powershell
75
- chdir Phasor-Handler
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
+ ---
@@ -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__ = "2.3.0"
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
- for full_path, display_name in self.dir_manager.get_display_names():
114
- if hasattr(self, 'conv_list_widget'):
115
- item = QListWidgetItem(display_name)
116
- item.setToolTip(full_path)
117
- item.setData(Qt.ItemDataRole.UserRole, full_path)
118
- self.conv_list_widget.addItem(item)
119
- if hasattr(self, 'reg_list_widget'):
120
- try:
121
- item = QListWidgetItem(display_name)
122
- item.setToolTip(full_path)
123
- item.setData(Qt.ItemDataRole.UserRole, full_path)
124
- self.reg_list_widget.addItem(item)
125
- except RuntimeError:
126
- pass
127
- if hasattr(self, 'analysis_list_widget'):
128
- item = QListWidgetItem(display_name)
129
- item.setToolTip(full_path)
130
- item.setData(Qt.ItemDataRole.UserRole, full_path)
131
- self.analysis_list_widget.addItem(item)
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 main():
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()