phasorpy 0.11__tar.gz → 0.12__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.
- {phasorpy-0.11/src/phasorpy.egg-info → phasorpy-0.12}/PKG-INFO +3 -2
- {phasorpy-0.11 → phasorpy-0.12}/docs/_static/switcher.json +8 -3
- phasorpy-0.12/docs/about.rst +83 -0
- phasorpy-0.12/docs/acknowledgments.rst +3 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/conf.py +0 -4
- {phasorpy-0.11 → phasorpy-0.12}/docs/contributing.rst +28 -4
- {phasorpy-0.11 → phasorpy-0.12}/docs/index.rst +5 -5
- {phasorpy-0.11 → phasorpy-0.12}/docs/phasor_approach.rst +27 -0
- {phasorpy-0.11 → phasorpy-0.12}/pyproject.toml +13 -8
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/__init__.py +1 -1
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/_phasorpy.pyx +84 -6
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/cli.py +123 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/component.py +1 -1
- phasorpy-0.12/src/phasorpy/experimental.py +264 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/io/__init__.py +11 -6
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/io/_other.py +292 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/lifetime.py +1 -1
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/phasor.py +1 -1
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/plot/__init__.py +3 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/plot/_phasorplot.py +8 -1
- phasorpy-0.12/src/phasorpy/plot/_spectral_plots.py +734 -0
- {phasorpy-0.11 → phasorpy-0.12/src/phasorpy.egg-info}/PKG-INFO +3 -2
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy.egg-info/SOURCES.txt +3 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy.egg-info/requires.txt +2 -1
- {phasorpy-0.11 → phasorpy-0.12}/tests/conftest.py +4 -4
- {phasorpy-0.11 → phasorpy-0.12}/tests/io/test_flimlabs.py +8 -10
- {phasorpy-0.11 → phasorpy-0.12}/tests/io/test_leica.py +4 -8
- {phasorpy-0.11 → phasorpy-0.12}/tests/io/test_ometiff.py +12 -13
- phasorpy-0.12/tests/io/test_other.py +729 -0
- {phasorpy-0.11 → phasorpy-0.12}/tests/io/test_simfcs.py +13 -17
- {phasorpy-0.11 → phasorpy-0.12}/tests/plot/test_functions.py +20 -18
- {phasorpy-0.11 → phasorpy-0.12}/tests/plot/test_lifetime_plots.py +6 -10
- {phasorpy-0.11 → phasorpy-0.12}/tests/plot/test_phasorplot.py +22 -24
- {phasorpy-0.11 → phasorpy-0.12}/tests/plot/test_phasorplot_fret.py +2 -6
- phasorpy-0.12/tests/plot/test_spectral_plots.py +242 -0
- {phasorpy-0.11 → phasorpy-0.12}/tests/test__phasorpy.py +42 -35
- {phasorpy-0.11 → phasorpy-0.12}/tests/test__typing.py +1 -5
- {phasorpy-0.11 → phasorpy-0.12}/tests/test__utils.py +20 -23
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_cli.py +32 -7
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_cluster.py +19 -12
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_color.py +2 -6
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_component.py +68 -63
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_cursor.py +53 -26
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_datasets.py +10 -14
- phasorpy-0.12/tests/test_experimental.py +114 -0
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_filter.py +65 -50
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_lifetime.py +100 -70
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_nan.py +28 -32
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_phasor.py +88 -66
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_phasorpy.py +1 -5
- {phasorpy-0.11 → phasorpy-0.12}/tests/test_utils.py +3 -7
- {phasorpy-0.11 → phasorpy-0.12}/tools/build_manylinux.cmd +1 -1
- {phasorpy-0.11 → phasorpy-0.12}/tools/build_manylinux.sh +1 -1
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/api/phasorpy_io.py +2 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/misc/phasorpy_apps.py +43 -6
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/phasorpy_lifetime_geometry.py +17 -16
- phasorpy-0.11/docs/acknowledgments.rst +0 -42
- phasorpy-0.11/src/phasorpy/experimental.py +0 -146
- phasorpy-0.11/tests/io/test_other.py +0 -362
- phasorpy-0.11/tests/test_experimental.py +0 -37
- {phasorpy-0.11 → phasorpy-0.12}/LICENSE.txt +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/MANIFEST.in +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/README.md +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/_static/categorical.png +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/_static/custom-icons.js +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/_static/favicon.ico +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/_static/phasorpy_logo.png +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/_static/phasorpy_logo.svg +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/_static/srgb_spectrum.png +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/_phasorpy.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/_utils.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/cli.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/cluster.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/color.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/component.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/cursor.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/datasets.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/experimental.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/filter.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/index.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/io.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/lifetime.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/phasor.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/phasorpy.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/plot.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/api/utils.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/code_of_conduct.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/docs/license.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/setup.cfg +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/setup.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/__main__.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/_typing.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/_utils.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/cluster.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/color.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/conftest.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/cursor.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/datasets.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/filter.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/io/_flimlabs.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/io/_leica.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/io/_ometiff.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/io/_simfcs.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/plot/_functions.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/plot/_lifetime_plots.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/plot/_phasorplot_fret.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/py.typed +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy/utils.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy.egg-info/dependency_links.txt +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy.egg-info/entry_points.txt +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy.egg-info/not-zip-safe +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/src/phasorpy.egg-info/top_level.txt +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tests/io/_conftest.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tools/sha256.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/README.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/api/README.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/api/phasorpy_component.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/api/phasorpy_cursor.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/api/phasorpy_filter.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/api/phasorpy_fret.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/api/phasorpy_lifetime_to_signal.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/api/phasorpy_multi_harmonic.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/api/phasorpy_pca.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/api/phasorpy_phasor_from_lifetime.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/api/phasorpy_phasorplot.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/applications/README.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/applications/phasorpy_component_fit.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/applications/phasorpy_fret_efficiency.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/applications/phasorpy_multidimensional.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/applications/phasorpy_nadh_concentration.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/applications/phasorpy_nadh_fraction.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/misc/README.rst +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/misc/phasorpy_logo.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/misc/phasorpy_phasor_from_signal.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/phasorpy_introduction.py +0 -0
- {phasorpy-0.11 → phasorpy-0.12}/tutorials/phasorpy_lfd_workshop.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: phasorpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12
|
|
4
4
|
Summary: Analysis of luminescence lifetime and hyperspectral images using the phasor approach
|
|
5
5
|
Author: PhasorPy Contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -37,11 +37,12 @@ Requires-Dist: tqdm
|
|
|
37
37
|
Provides-Extra: all
|
|
38
38
|
Requires-Dist: czifile>=2026.4.11; extra == "all"
|
|
39
39
|
Requires-Dist: fbdfile>=2025.9.18; extra == "all"
|
|
40
|
-
Requires-Dist: lfdfiles>=2026.
|
|
40
|
+
Requires-Dist: lfdfiles>=2026.6.24; extra == "all"
|
|
41
41
|
Requires-Dist: liffile>=2025.2.10; extra == "all"
|
|
42
42
|
Requires-Dist: ptufile>=2024.9.14; extra == "all"
|
|
43
43
|
Requires-Dist: sdtfile>=2024.5.24; extra == "all"
|
|
44
44
|
Requires-Dist: pawflim>=1.0.4; extra == "all"
|
|
45
|
+
Requires-Dist: brighteyes-mcs-reader>=0.1.0; extra == "all"
|
|
45
46
|
Requires-Dist: imagecodecs==2026.6.6; (sys_platform == "darwin" and platform_machine == "x86_64") and extra == "all"
|
|
46
47
|
Dynamic: license-file
|
|
47
48
|
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
3
|
"name": "dev",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.13",
|
|
5
5
|
"url": "https://www.phasorpy.org/docs/dev/"
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
|
-
"name": "0.
|
|
9
|
-
"version": "0.
|
|
8
|
+
"name": "0.12 (stable)",
|
|
9
|
+
"version": "0.12",
|
|
10
10
|
"url": "https://www.phasorpy.org/docs/stable/",
|
|
11
11
|
"preferred": true
|
|
12
12
|
},
|
|
13
|
+
{
|
|
14
|
+
"name": "0.11",
|
|
15
|
+
"version": "0.11",
|
|
16
|
+
"url": "https://www.phasorpy.org/docs/v0.11/"
|
|
17
|
+
},
|
|
13
18
|
{
|
|
14
19
|
"name": "0.10",
|
|
15
20
|
"version": "0.10",
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
About PhasorPy
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
The PhasorPy project's mission is to advance and democratize phasor analysis
|
|
5
|
+
through the open-source PhasorPy library.
|
|
6
|
+
|
|
7
|
+
.. _funding:
|
|
8
|
+
|
|
9
|
+
Founding and funding
|
|
10
|
+
--------------------
|
|
11
|
+
|
|
12
|
+
The PhasorPy project was established in 2023 by the
|
|
13
|
+
`Advanced Bioimaging Unit <https://www.uba.uy>`_
|
|
14
|
+
at the University of the Republic and Institut Pasteur de Montevideo, and the
|
|
15
|
+
`Laboratory for Fluorescence Dynamics <https://www.lfd.uci.edu>`_
|
|
16
|
+
at the University of California, Irvine.
|
|
17
|
+
|
|
18
|
+
The project was supported by the
|
|
19
|
+
`Essential Open Source Software for Science (EOSS)
|
|
20
|
+
<https://chanzuckerberg.com/eoss/>`_ program at
|
|
21
|
+
`Chan Zuckerberg Initiative <https://chanzuckerberg.com/>`_
|
|
22
|
+
(grant number 2022-252604; 2022-2024).
|
|
23
|
+
|
|
24
|
+
Project goals
|
|
25
|
+
-------------
|
|
26
|
+
|
|
27
|
+
The original goals were to create an open-source Python library based on
|
|
28
|
+
sound software engineering principles, establish a community of users
|
|
29
|
+
and developers, and reimplement core phasor-based functionality of the
|
|
30
|
+
discontinued closed-source
|
|
31
|
+
`Globals for Images - SimFCS <https://www.lfd.uci.edu/globals/>`_
|
|
32
|
+
software by Enrico Gratton.
|
|
33
|
+
|
|
34
|
+
The current goals are to improve community sustainability and to advance the
|
|
35
|
+
PhasorPy library toward a stable, extensible platform that supports
|
|
36
|
+
large-scale automated workflows, AI-assisted analysis, and robust integration
|
|
37
|
+
with the scientific Python ecosystem, while continuing to serve as a reliable
|
|
38
|
+
base for graphical applications and training resources.
|
|
39
|
+
|
|
40
|
+
.. _governance:
|
|
41
|
+
|
|
42
|
+
.. _contributors:
|
|
43
|
+
|
|
44
|
+
Governance and contributors
|
|
45
|
+
---------------------------
|
|
46
|
+
|
|
47
|
+
PhasorPy is developed collaboratively by
|
|
48
|
+
`contributors to the PhasorPy repository
|
|
49
|
+
<https://github.com/phasorpy/phasorpy/graphs/contributors?all=1>`_
|
|
50
|
+
and governed by
|
|
51
|
+
`members of the PhasorPy organization
|
|
52
|
+
<https://github.com/orgs/phasorpy/people>`_.
|
|
53
|
+
|
|
54
|
+
Technical direction is developed through open discussion and
|
|
55
|
+
consensus-building in issues, pull requests, and community meetings.
|
|
56
|
+
Members of the PhasorPy organization make final technical and release
|
|
57
|
+
decisions.
|
|
58
|
+
|
|
59
|
+
Infrastructure hosting, funded activities, and institutional partnerships are
|
|
60
|
+
coordinated through the `Advanced Bioimaging Unit <https://www.uba.uy>`__.
|
|
61
|
+
|
|
62
|
+
See the :doc:`Contributing guide <contributing>` to get involved.
|
|
63
|
+
|
|
64
|
+
Acknowledgments
|
|
65
|
+
---------------
|
|
66
|
+
|
|
67
|
+
We thank the PhasorPy user community for feedback, bug reports, feature
|
|
68
|
+
suggestions, and data files that have helped improve the library.
|
|
69
|
+
|
|
70
|
+
We acknowledge the open-source scientific Python ecosystem that PhasorPy
|
|
71
|
+
builds on, including Python, NumPy, SciPy, Matplotlib, and scikit-learn,
|
|
72
|
+
the microscopy file-format stack (including tifffile, ptufile, and related
|
|
73
|
+
tools), and the documentation toolchain based on Sphinx and Sphinx-Gallery.
|
|
74
|
+
|
|
75
|
+
We also acknowledge GitHub for providing a platform for collaborative
|
|
76
|
+
development and hosting documentation, PyPI and conda-forge for package
|
|
77
|
+
distribution, and Zenodo for hosting sample data.
|
|
78
|
+
|
|
79
|
+
Citation
|
|
80
|
+
--------
|
|
81
|
+
|
|
82
|
+
If PhasorPy contributes to research that leads to a publication, please cite
|
|
83
|
+
`doi: 10.5281/zenodo.13862586 <https://doi.org/10.5281/zenodo.13862586>`_.
|
|
@@ -47,7 +47,6 @@ extensions = [
|
|
|
47
47
|
# don't enable intersphinx since tutorials are getting littered with links
|
|
48
48
|
# 'sphinx.ext.intersphinx',
|
|
49
49
|
# 'numpydoc',
|
|
50
|
-
'sphinx_inline_tabs',
|
|
51
50
|
'sphinx_copybutton',
|
|
52
51
|
'sphinx_click',
|
|
53
52
|
'sphinx_issues',
|
|
@@ -148,9 +147,6 @@ sphinx_gallery_conf = {
|
|
|
148
147
|
# 'backreferences_dir': None,
|
|
149
148
|
}
|
|
150
149
|
|
|
151
|
-
# TODO: remove MathJax 3 link once scroll bar issue is resolved
|
|
152
|
-
mathjax_path = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'
|
|
153
|
-
|
|
154
150
|
|
|
155
151
|
class TutorialOrder:
|
|
156
152
|
"""Order tutorials in gallery subsections."""
|
|
@@ -61,9 +61,9 @@ and include the following items in the bug report:
|
|
|
61
61
|
output of::
|
|
62
62
|
|
|
63
63
|
$ python -m phasorpy versions
|
|
64
|
-
Python-3.14.
|
|
65
|
-
phasorpy-0.
|
|
66
|
-
numpy-2.
|
|
64
|
+
Python-3.14.6
|
|
65
|
+
phasorpy-0.11
|
|
66
|
+
numpy-2.5.1
|
|
67
67
|
...
|
|
68
68
|
|
|
69
69
|
Contribute code or documentation
|
|
@@ -88,6 +88,30 @@ The PhasorPy project loosely follows the
|
|
|
88
88
|
`pyOpenSci <https://www.pyopensci.org/python-package-guide/>`_
|
|
89
89
|
development guidelines.
|
|
90
90
|
|
|
91
|
+
The PhasorPy project follows and adapts the `SciPy AI policy
|
|
92
|
+
<https://scipy.github.io/devdocs/dev/conduct/ai_policy.html>`_.
|
|
93
|
+
|
|
94
|
+
Copyright
|
|
95
|
+
.........
|
|
96
|
+
|
|
97
|
+
All code in PhasorPy is released under the :doc:`license`.
|
|
98
|
+
Contributors license their code under the same license when submitting it
|
|
99
|
+
to PhasorPy's version control repository.
|
|
100
|
+
That means contributors must have the right to submit the code to PhasorPy
|
|
101
|
+
and must comply with the terms of any MIT-compatible open-source license
|
|
102
|
+
associated with submitted code.
|
|
103
|
+
|
|
104
|
+
Accountability
|
|
105
|
+
..............
|
|
106
|
+
|
|
107
|
+
Contributors are responsible for all code submitted to the PhasorPy repository.
|
|
108
|
+
They must understand it and be able to explain it, regardless of whether it
|
|
109
|
+
was manually written or AI-generated.
|
|
110
|
+
|
|
111
|
+
Contributors must disclose whether AI has been used to assist in the
|
|
112
|
+
development of code or documentation. If so, specify the tool(s) used,
|
|
113
|
+
how they were used, and which code or text is AI-generated.
|
|
114
|
+
|
|
91
115
|
Fork the repository
|
|
92
116
|
...................
|
|
93
117
|
|
|
@@ -195,7 +219,7 @@ must conform to certain styles, which can be checked and applied with
|
|
|
195
219
|
|
|
196
220
|
$ python -m pre_commit run --all-files
|
|
197
221
|
|
|
198
|
-
|
|
222
|
+
Tests and user-facing classes and functions must use
|
|
199
223
|
`type hints <https://peps.python.org/pep-0484/>`_
|
|
200
224
|
and pass verification with the
|
|
201
225
|
`MyPy <https://mypy.readthedocs.io>`_
|
|
@@ -19,14 +19,14 @@ classes of the library.
|
|
|
19
19
|
The :doc:`release/index` list recent bug fixes, feature enhancements,
|
|
20
20
|
documentation, and maintenance changes.
|
|
21
21
|
|
|
22
|
-
The :doc:`contributing
|
|
23
|
-
submit fixes, and improve the documentation.
|
|
22
|
+
The :doc:`Contributing guide <contributing>` explains how to get support,
|
|
23
|
+
report bugs, submit fixes, and improve the documentation.
|
|
24
24
|
|
|
25
25
|
The :doc:`code_of_conduct` applies to everyone participating in the
|
|
26
26
|
PhasorPy community.
|
|
27
27
|
|
|
28
|
-
The :doc:`
|
|
29
|
-
|
|
28
|
+
The :doc:`About <about>` page describes the project's history, goals,
|
|
29
|
+
funding, and governance.
|
|
30
30
|
|
|
31
31
|
The PhasorPy library and documentation are released under the permissive
|
|
32
32
|
:doc:`license`.
|
|
@@ -62,8 +62,8 @@ Contents
|
|
|
62
62
|
api/index
|
|
63
63
|
release/index
|
|
64
64
|
contributing
|
|
65
|
-
acknowledgments
|
|
66
65
|
license
|
|
66
|
+
about
|
|
67
67
|
|
|
68
68
|
Indices and tables
|
|
69
69
|
------------------
|
|
@@ -148,6 +148,7 @@ luminescence time-resolved or spectral images:
|
|
|
148
148
|
|
|
149
149
|
* - **Library**
|
|
150
150
|
- :ref:`PhasorPy <phasorpy>`,
|
|
151
|
+
:ref:`PyFLI <pyfli>`,
|
|
151
152
|
:ref:`tttrlib <tttrlib>`,
|
|
152
153
|
:ref:`FLIMLib <flimlib>`:sup:`2`,
|
|
153
154
|
:ref:`BrightEyes <brighteyes>`:sup:`2`,
|
|
@@ -156,10 +157,12 @@ luminescence time-resolved or spectral images:
|
|
|
156
157
|
* - **Desktop**
|
|
157
158
|
- :ref:`SimFCS <simfcs>`:sup:`3,4`,
|
|
158
159
|
:ref:`FLIM Playground <flim_playground>`:sup:`1`,
|
|
160
|
+
:ref:`FLIMKit <flimkit>`:sup:`1`,
|
|
159
161
|
:ref:`FLUTE <flute>`,
|
|
160
162
|
:ref:`FLIMPA <flimpa>`,
|
|
161
163
|
:ref:`GSLab <gslab>`,
|
|
162
164
|
:ref:`AlliGator <alligator>`,
|
|
165
|
+
:ref:`Spectral Phasors Analysis <spectral_phasors_analysis>`:sup:`2`,
|
|
163
166
|
:ref:`HySP <hysp>`:sup:`3,4`,
|
|
164
167
|
:ref:`FlimFast <flimfast>`:sup:`3,4`
|
|
165
168
|
* - **Napari**
|
|
@@ -316,6 +319,22 @@ Details:
|
|
|
316
319
|
The software is written in Python, is web deployable, and is distributed
|
|
317
320
|
under the MIT license.
|
|
318
321
|
|
|
322
|
+
-
|
|
323
|
+
.. _flimkit:
|
|
324
|
+
|
|
325
|
+
`FLIMKit <https://github.com/alex1075/FLIMKit>`__
|
|
326
|
+
is an open-source Python toolkit focused on PTU-based FLIM data. It includes
|
|
327
|
+
a phasor analysis workflow and is distributed under the MIT license.
|
|
328
|
+
|
|
329
|
+
-
|
|
330
|
+
.. _pyfli:
|
|
331
|
+
|
|
332
|
+
`PyFLI <https://github.com/vkp217/pyfli-pkg>`__
|
|
333
|
+
is an open-source Python platform for Fluorescence Lifetime Imaging
|
|
334
|
+
(FLI) data simulation, processing and visualization, including phasor
|
|
335
|
+
analysis.
|
|
336
|
+
The library is distributed under the CC BY-NC-ND 4.0 license.
|
|
337
|
+
|
|
319
338
|
-
|
|
320
339
|
.. _flim_tools:
|
|
321
340
|
|
|
@@ -333,6 +352,14 @@ Details:
|
|
|
333
352
|
and correcting phasor coordinates. The library is distributed under the
|
|
334
353
|
BSD license.
|
|
335
354
|
|
|
355
|
+
-
|
|
356
|
+
.. _spectral_phasors_analysis:
|
|
357
|
+
|
|
358
|
+
`Spectral Phasors Analysis <https://github.com/DBP008/spectral-phasors-analysis>`__
|
|
359
|
+
is a Python application to explore spectral phasors through simulations and
|
|
360
|
+
analyze experimental data. The software is distributed under the AGPL-3.0
|
|
361
|
+
license.
|
|
362
|
+
|
|
336
363
|
-
|
|
337
364
|
.. _phasor_analysis:
|
|
338
365
|
|
|
@@ -60,11 +60,12 @@ all = [
|
|
|
60
60
|
# sync with [dependency-groups.optional]
|
|
61
61
|
"czifile>=2026.4.11",
|
|
62
62
|
"fbdfile>=2025.9.18",
|
|
63
|
-
"lfdfiles>=2026.
|
|
63
|
+
"lfdfiles>=2026.6.24",
|
|
64
64
|
"liffile>=2025.2.10",
|
|
65
65
|
"ptufile>=2024.9.14",
|
|
66
66
|
"sdtfile>=2024.5.24",
|
|
67
67
|
"pawflim>=1.0.4",
|
|
68
|
+
"brighteyes-mcs-reader>=0.1.0",
|
|
68
69
|
"imagecodecs==2026.6.6; sys_platform == 'darwin' and platform_machine == 'x86_64'",
|
|
69
70
|
# "mkl-fft>=2.1.1",
|
|
70
71
|
]
|
|
@@ -87,11 +88,12 @@ optional = [
|
|
|
87
88
|
# optional runtime dependencies; sync with [project.optional-dependencies]
|
|
88
89
|
"czifile>=2026.4.11",
|
|
89
90
|
"fbdfile>=2025.9.18",
|
|
90
|
-
"lfdfiles>=2026.
|
|
91
|
+
"lfdfiles>=2026.6.24",
|
|
91
92
|
"liffile>=2025.2.10",
|
|
92
93
|
"ptufile>=2024.9.14",
|
|
93
94
|
"sdtfile>=2024.5.24",
|
|
94
95
|
"pawflim>=1.0.4",
|
|
96
|
+
"brighteyes-mcs-reader>=0.1.0",
|
|
95
97
|
"imagecodecs==2026.6.6; sys_platform == 'darwin' and platform_machine == 'x86_64'",
|
|
96
98
|
]
|
|
97
99
|
minimal = [
|
|
@@ -106,11 +108,12 @@ minimal = [
|
|
|
106
108
|
# optional
|
|
107
109
|
"czifile==2026.4.11; python_version == \"3.12\"",
|
|
108
110
|
"fbdfile==2025.9.18; python_version == \"3.12\"",
|
|
109
|
-
"lfdfiles==2026.
|
|
111
|
+
"lfdfiles==2026.6.24; python_version == \"3.12\"",
|
|
110
112
|
"liffile==2025.2.10; python_version == \"3.12\"",
|
|
111
113
|
"ptufile==2024.9.14; python_version == \"3.12\"",
|
|
112
114
|
"sdtfile==2024.5.24; python_version == \"3.12\"",
|
|
113
115
|
"pawflim==1.0.4; python_version == \"3.12\"",
|
|
116
|
+
"brighteyes-mcs-reader==0.1.0; python_version == \"3.12\""
|
|
114
117
|
]
|
|
115
118
|
build = [
|
|
116
119
|
# build requirements
|
|
@@ -140,7 +143,6 @@ docs = [
|
|
|
140
143
|
"sphinx",
|
|
141
144
|
"sphinx-copybutton",
|
|
142
145
|
"sphinx-design",
|
|
143
|
-
"sphinx-inline-tabs",
|
|
144
146
|
"sphinx-issues",
|
|
145
147
|
"sphinx_click",
|
|
146
148
|
"sphinx_gallery",
|
|
@@ -260,7 +262,7 @@ typing-modules = ["_typing"]
|
|
|
260
262
|
"__init__.py" = ["F401", "F403"]
|
|
261
263
|
"conftest.py" = ["ARG001"]
|
|
262
264
|
"setup.py" = ["T201"]
|
|
263
|
-
"tests/*" = ["
|
|
265
|
+
"tests/*" = ["INP001", "PT011", "SLF001", "TC001"]
|
|
264
266
|
"tools/*" = ["ANN", "INP001", "T201"]
|
|
265
267
|
"tutorials/*" = ["ANN", "D", "E402", "INP001", "T201", "S101", "ERA001"]
|
|
266
268
|
"docs/conf.py" = ["A001", "ANN204", "D102", "E402", "INP001", "RUF012"]
|
|
@@ -332,7 +334,7 @@ ND2 = "ND2"
|
|
|
332
334
|
OIF = "OIF"
|
|
333
335
|
|
|
334
336
|
[tool.mypy]
|
|
335
|
-
packages = ["phasorpy"]
|
|
337
|
+
packages = ["phasorpy", "tests"]
|
|
336
338
|
mypy_path = "$MYPY_CONFIG_FILE_DIR/src"
|
|
337
339
|
plugins = []
|
|
338
340
|
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
|
|
@@ -341,11 +343,13 @@ warn_unreachable = true
|
|
|
341
343
|
|
|
342
344
|
[[tool.mypy.overrides]]
|
|
343
345
|
module = [
|
|
346
|
+
"_conftest",
|
|
344
347
|
"phasorpy._phasorpy",
|
|
345
348
|
"pooch.*",
|
|
346
349
|
"scipy.*",
|
|
347
350
|
"mkl_fft.*",
|
|
348
351
|
"sklearn.*",
|
|
352
|
+
"h5py.*",
|
|
349
353
|
]
|
|
350
354
|
ignore_missing_imports = true
|
|
351
355
|
|
|
@@ -403,21 +407,22 @@ norecursedirs = [
|
|
|
403
407
|
|
|
404
408
|
[tool.cibuildwheel]
|
|
405
409
|
skip = [
|
|
406
|
-
"cp38*",
|
|
407
410
|
"cp39*",
|
|
408
411
|
"cp310*",
|
|
409
412
|
"cp311*",
|
|
410
413
|
"cp313*",
|
|
411
414
|
"cp314-*",
|
|
415
|
+
"cp315*",
|
|
412
416
|
"*musllinux*",
|
|
413
417
|
"*i686*",
|
|
414
418
|
"*ppc64le*",
|
|
415
419
|
"*s390x*",
|
|
416
420
|
]
|
|
417
421
|
test-command = "pytest {project}/tests"
|
|
418
|
-
test-skip = ["cp314t*"]
|
|
422
|
+
test-skip = ["cp314t*", "cp315t*"]
|
|
419
423
|
test-requires = [
|
|
420
424
|
# sync with [dependency-groups.optional]
|
|
425
|
+
"brighteyes-mcs-reader",
|
|
421
426
|
"czifile>=2026.4.11",
|
|
422
427
|
"fbdfile",
|
|
423
428
|
"lfdfiles",
|
|
@@ -413,6 +413,7 @@ def _gaussian_signal(
|
|
|
413
413
|
float_t[::1] signal,
|
|
414
414
|
const double mean,
|
|
415
415
|
const double stdev,
|
|
416
|
+
ssize_t folds = -1
|
|
416
417
|
):
|
|
417
418
|
"""Return normal distribution, wrapped around at borders.
|
|
418
419
|
|
|
@@ -420,21 +421,28 @@ def _gaussian_signal(
|
|
|
420
421
|
----------
|
|
421
422
|
signal : memoryview of `float32` or `float64`
|
|
422
423
|
Writable buffer where calculated signal samples are stored.
|
|
424
|
+
Must be initialized.
|
|
423
425
|
mean : float
|
|
424
426
|
Mean of normal distribution.
|
|
425
427
|
stdev : float
|
|
426
428
|
Standard deviation of normal distribution.
|
|
429
|
+
folds : int, optional, default=-1
|
|
430
|
+
Number of times to wrap around distribution at borders.
|
|
431
|
+
If negative (default), it is automatically calculated based on
|
|
432
|
+
`stdev` and the size of `signal` (number of samples).
|
|
427
433
|
|
|
428
434
|
"""
|
|
429
435
|
cdef:
|
|
430
436
|
ssize_t samples = signal.shape[0]
|
|
431
|
-
ssize_t folds = 1 # TODO: calculate from stddev and samples
|
|
432
437
|
ssize_t i
|
|
433
438
|
double t, c
|
|
434
439
|
|
|
435
440
|
if samples < 1:
|
|
436
441
|
return
|
|
437
442
|
|
|
443
|
+
if folds < 0:
|
|
444
|
+
folds = <ssize_t> (-floor(-6.0 * stdev / <double> samples))
|
|
445
|
+
|
|
438
446
|
with nogil:
|
|
439
447
|
if isnan(mean) or isnan(stdev) or stdev <= 0.0:
|
|
440
448
|
for i in range(samples):
|
|
@@ -2748,7 +2756,7 @@ def _median_filter_2d(
|
|
|
2748
2756
|
ssize_t rows = image.shape[0]
|
|
2749
2757
|
ssize_t cols = image.shape[1]
|
|
2750
2758
|
ssize_t k = kernel_size // 2
|
|
2751
|
-
ssize_t i, j,
|
|
2759
|
+
ssize_t i, j, _r, di, dj, ki, kj, valid_count
|
|
2752
2760
|
float_t element
|
|
2753
2761
|
float_t* kernel
|
|
2754
2762
|
|
|
@@ -2766,7 +2774,7 @@ def _median_filter_2d(
|
|
|
2766
2774
|
with gil:
|
|
2767
2775
|
raise MemoryError('failed to allocate kernel')
|
|
2768
2776
|
|
|
2769
|
-
for
|
|
2777
|
+
for _r in range(repeat):
|
|
2770
2778
|
for i in prange(rows):
|
|
2771
2779
|
for j in range(cols):
|
|
2772
2780
|
if isnan(image[i, j]):
|
|
@@ -2846,7 +2854,7 @@ def _flimlabs_mean(
|
|
|
2846
2854
|
cdef:
|
|
2847
2855
|
float_t[::] mean_
|
|
2848
2856
|
list channels, pixels
|
|
2849
|
-
ssize_t c, i,
|
|
2857
|
+
ssize_t c, i, _h, count
|
|
2850
2858
|
double sum
|
|
2851
2859
|
|
|
2852
2860
|
if channel < 0:
|
|
@@ -2856,7 +2864,7 @@ def _flimlabs_mean(
|
|
|
2856
2864
|
i = 0
|
|
2857
2865
|
for pixels in channels:
|
|
2858
2866
|
sum = 0.0
|
|
2859
|
-
for
|
|
2867
|
+
for _h, count in pixels:
|
|
2860
2868
|
sum += <double> count
|
|
2861
2869
|
mean_[i] = <float_t> (sum / 256.0)
|
|
2862
2870
|
i += 1
|
|
@@ -2866,7 +2874,77 @@ def _flimlabs_mean(
|
|
|
2866
2874
|
mean_ = mean[0]
|
|
2867
2875
|
for pixels in data[channel]:
|
|
2868
2876
|
sum = 0.0
|
|
2869
|
-
for
|
|
2877
|
+
for _h, count in pixels:
|
|
2870
2878
|
sum += <double> count
|
|
2871
2879
|
mean_[i] = <float_t> (sum / 256.0)
|
|
2872
2880
|
i += 1
|
|
2881
|
+
|
|
2882
|
+
|
|
2883
|
+
###############################################################################
|
|
2884
|
+
# Synthesize spectra
|
|
2885
|
+
|
|
2886
|
+
|
|
2887
|
+
@cython.ufunc
|
|
2888
|
+
cdef float_t _signal_from_dho(
|
|
2889
|
+
float_t wavelength,
|
|
2890
|
+
float_t origin,
|
|
2891
|
+
float_t sigma,
|
|
2892
|
+
float_t hr_factor,
|
|
2893
|
+
float_t vib_frequency,
|
|
2894
|
+
float_t scale,
|
|
2895
|
+
float_t offset,
|
|
2896
|
+
int absorption,
|
|
2897
|
+
) noexcept nogil:
|
|
2898
|
+
"""Return DHO model intensity for emission or absorption.
|
|
2899
|
+
|
|
2900
|
+
Using the area-normalized Displaced Harmonic Oscillator (DHO) model.
|
|
2901
|
+
|
|
2902
|
+
"""
|
|
2903
|
+
cdef:
|
|
2904
|
+
double wavenumber, gaussian, nu_0, nu_n, poisson_factor
|
|
2905
|
+
double intensity_nu = 0.0
|
|
2906
|
+
double weight = 1.0 # w[0] = hr_factor^0 / 0! = 1
|
|
2907
|
+
double sign = 1.0 if absorption else -1.0
|
|
2908
|
+
ssize_t max_n = 6 # N=5 in math notation; error <1% for S<=1.65
|
|
2909
|
+
ssize_t n
|
|
2910
|
+
|
|
2911
|
+
if (
|
|
2912
|
+
wavelength <= 0.0
|
|
2913
|
+
or origin <= 0.0
|
|
2914
|
+
or sigma <= 0.0
|
|
2915
|
+
or hr_factor < 0.0
|
|
2916
|
+
or vib_frequency < 0.0
|
|
2917
|
+
):
|
|
2918
|
+
return <float_t> NAN
|
|
2919
|
+
|
|
2920
|
+
# convert to wavenumber domain (cm^-1)
|
|
2921
|
+
wavenumber = 1e7 / wavelength
|
|
2922
|
+
nu_0 = 1e7 / origin # 0->0 electronic origin
|
|
2923
|
+
|
|
2924
|
+
# Poisson PMF normalization factor exp(-S); sum of weights over all n is ~1
|
|
2925
|
+
poisson_factor = exp(-hr_factor)
|
|
2926
|
+
|
|
2927
|
+
for n in range(max_n):
|
|
2928
|
+
if n > 0:
|
|
2929
|
+
weight = weight * hr_factor / n # Iterative w[n] = hr_factor^n/n!
|
|
2930
|
+
|
|
2931
|
+
# In emission, vibronic sidebands go to lower energy
|
|
2932
|
+
# (red-shifted) -> subtract frequency
|
|
2933
|
+
# In absorption, sidebands go to HIGHER energy
|
|
2934
|
+
# (blue-shifted) -> add frequency
|
|
2935
|
+
nu_n = nu_0 + sign * n * vib_frequency
|
|
2936
|
+
|
|
2937
|
+
gaussian = exp(
|
|
2938
|
+
-((wavenumber - nu_n) * (wavenumber - nu_n))
|
|
2939
|
+
/ (2.0 * sigma * sigma)
|
|
2940
|
+
)
|
|
2941
|
+
|
|
2942
|
+
intensity_nu += weight * poisson_factor * gaussian
|
|
2943
|
+
|
|
2944
|
+
# normalize the Gaussian peak heights in wavenumber space,
|
|
2945
|
+
# transform coordinates to wavelength space via the Jacobian: 1e7/lambda^2,
|
|
2946
|
+
# and apply affine transformation
|
|
2947
|
+
return <float_t> (
|
|
2948
|
+
(intensity_nu / (sigma * sqrt(2.0 * M_PI)))
|
|
2949
|
+
* (1e7 / (wavelength * wavelength))
|
|
2950
|
+
) * scale + offset
|
|
@@ -156,6 +156,129 @@ def lifetime(
|
|
|
156
156
|
plot.show()
|
|
157
157
|
|
|
158
158
|
|
|
159
|
+
@main.command(help='Start interactive spectral plots.')
|
|
160
|
+
@click.argument(
|
|
161
|
+
'number_spectra',
|
|
162
|
+
default=1,
|
|
163
|
+
type=click.IntRange(1, 4),
|
|
164
|
+
required=False,
|
|
165
|
+
)
|
|
166
|
+
@click.option(
|
|
167
|
+
'-o',
|
|
168
|
+
'--origin',
|
|
169
|
+
type=float,
|
|
170
|
+
multiple=True,
|
|
171
|
+
required=False,
|
|
172
|
+
help='Origin wavelength.',
|
|
173
|
+
)
|
|
174
|
+
@click.option(
|
|
175
|
+
'-s',
|
|
176
|
+
'--sigma',
|
|
177
|
+
type=float,
|
|
178
|
+
multiple=True,
|
|
179
|
+
required=False,
|
|
180
|
+
help='Spectral broadening factor.',
|
|
181
|
+
)
|
|
182
|
+
@click.option(
|
|
183
|
+
'-a',
|
|
184
|
+
'--fraction',
|
|
185
|
+
type=float,
|
|
186
|
+
multiple=True,
|
|
187
|
+
required=False,
|
|
188
|
+
help='Fractional intensity of component.',
|
|
189
|
+
)
|
|
190
|
+
@click.option(
|
|
191
|
+
'--hr-factor',
|
|
192
|
+
type=float,
|
|
193
|
+
default=0.4,
|
|
194
|
+
show_default=True,
|
|
195
|
+
help='Huang-Rhys factor.',
|
|
196
|
+
)
|
|
197
|
+
@click.option(
|
|
198
|
+
'--vib-frequency',
|
|
199
|
+
type=float,
|
|
200
|
+
default=1200.0,
|
|
201
|
+
show_default=True,
|
|
202
|
+
help='Vibrational frequency.',
|
|
203
|
+
)
|
|
204
|
+
@click.option(
|
|
205
|
+
'--wavelength-min',
|
|
206
|
+
type=float,
|
|
207
|
+
default=450.0,
|
|
208
|
+
show_default=True,
|
|
209
|
+
help='Minimum wavelength to display.',
|
|
210
|
+
)
|
|
211
|
+
@click.option(
|
|
212
|
+
'--wavelength-max',
|
|
213
|
+
type=float,
|
|
214
|
+
default=650.0,
|
|
215
|
+
show_default=True,
|
|
216
|
+
help='Maximum wavelength to display.',
|
|
217
|
+
)
|
|
218
|
+
@click.option(
|
|
219
|
+
'--samples',
|
|
220
|
+
type=int,
|
|
221
|
+
default=128,
|
|
222
|
+
show_default=True,
|
|
223
|
+
help='Number of wavelength samples.',
|
|
224
|
+
)
|
|
225
|
+
@click.option(
|
|
226
|
+
'--dho',
|
|
227
|
+
default=False,
|
|
228
|
+
is_flag=True,
|
|
229
|
+
type=click.BOOL,
|
|
230
|
+
help='Use Displaced Harmonic Oscillator model.',
|
|
231
|
+
)
|
|
232
|
+
@click.option(
|
|
233
|
+
'--hide',
|
|
234
|
+
default=False,
|
|
235
|
+
is_flag=True,
|
|
236
|
+
type=click.BOOL,
|
|
237
|
+
help='Do not show interactive plot.',
|
|
238
|
+
)
|
|
239
|
+
def spectral(
|
|
240
|
+
*,
|
|
241
|
+
number_spectra: int,
|
|
242
|
+
origin: tuple[float, ...],
|
|
243
|
+
sigma: tuple[float, ...],
|
|
244
|
+
fraction: tuple[float, ...],
|
|
245
|
+
hr_factor: float,
|
|
246
|
+
vib_frequency: float,
|
|
247
|
+
wavelength_min: float,
|
|
248
|
+
wavelength_max: float,
|
|
249
|
+
samples: int,
|
|
250
|
+
dho: bool,
|
|
251
|
+
hide: bool,
|
|
252
|
+
) -> None:
|
|
253
|
+
"""Start interactive spectral plots."""
|
|
254
|
+
from .plot import SpectralPlots
|
|
255
|
+
|
|
256
|
+
_default_origins = {
|
|
257
|
+
1: (518.0,),
|
|
258
|
+
2: (490.0, 570.0),
|
|
259
|
+
3: (480.0, 530.0, 590.0),
|
|
260
|
+
4: (470.0, 510.0, 560.0, 620.0),
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if not origin:
|
|
264
|
+
n = min(number_spectra, 2 if dho else 4)
|
|
265
|
+
origin = _default_origins[n]
|
|
266
|
+
|
|
267
|
+
plot = SpectralPlots(
|
|
268
|
+
origin,
|
|
269
|
+
sigma or None,
|
|
270
|
+
fraction if len(fraction) > 0 else None,
|
|
271
|
+
hr_factor=hr_factor,
|
|
272
|
+
vib_frequency=vib_frequency,
|
|
273
|
+
wavelength_range=(wavelength_min, wavelength_max),
|
|
274
|
+
samples=samples,
|
|
275
|
+
dho=dho,
|
|
276
|
+
interactive=True,
|
|
277
|
+
)
|
|
278
|
+
if not hide:
|
|
279
|
+
plot.show()
|
|
280
|
+
|
|
281
|
+
|
|
159
282
|
if __name__ == '__main__':
|
|
160
283
|
import sys
|
|
161
284
|
|