phasorpy 0.11__tar.gz → 0.13__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 (145) hide show
  1. {phasorpy-0.11/src/phasorpy.egg-info → phasorpy-0.13}/PKG-INFO +7 -6
  2. {phasorpy-0.11 → phasorpy-0.13}/docs/_static/switcher.json +13 -8
  3. phasorpy-0.13/docs/about.rst +83 -0
  4. phasorpy-0.13/docs/acknowledgments.rst +3 -0
  5. {phasorpy-0.11 → phasorpy-0.13}/docs/conf.py +32 -6
  6. {phasorpy-0.11 → phasorpy-0.13}/docs/contributing.rst +28 -4
  7. {phasorpy-0.11 → phasorpy-0.13}/docs/index.rst +5 -5
  8. {phasorpy-0.11 → phasorpy-0.13}/docs/phasor_approach.rst +27 -0
  9. {phasorpy-0.11 → phasorpy-0.13}/pyproject.toml +50 -44
  10. {phasorpy-0.11 → phasorpy-0.13}/setup.py +40 -13
  11. phasorpy-0.13/src/phasorpy/__init__.py +13 -0
  12. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/__main__.py +4 -0
  13. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/_phasorpy.pyx +123 -20
  14. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/_typing.py +4 -0
  15. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/_utils.py +31 -13
  16. phasorpy-0.13/src/phasorpy/cli.py +313 -0
  17. phasorpy-0.13/src/phasorpy/cluster.py +430 -0
  18. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/color.py +33 -8
  19. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/component.py +35 -17
  20. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/conftest.py +4 -0
  21. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/cursor.py +7 -1
  22. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/datasets.py +47 -41
  23. phasorpy-0.13/src/phasorpy/experimental.py +270 -0
  24. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/filter.py +44 -23
  25. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/io/__init__.py +15 -6
  26. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/io/_flimlabs.py +22 -10
  27. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/io/_leica.py +17 -6
  28. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/io/_ometiff.py +12 -17
  29. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/io/_other.py +336 -18
  30. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/io/_simfcs.py +36 -10
  31. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/lifetime.py +42 -27
  32. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/phasor.py +33 -15
  33. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/plot/__init__.py +7 -0
  34. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/plot/_functions.py +30 -18
  35. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/plot/_lifetime_plots.py +91 -2
  36. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/plot/_phasorplot.py +94 -49
  37. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/plot/_phasorplot_fret.py +8 -4
  38. phasorpy-0.13/src/phasorpy/plot/_spectral_plots.py +745 -0
  39. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/utils.py +16 -10
  40. {phasorpy-0.11 → phasorpy-0.13/src/phasorpy.egg-info}/PKG-INFO +7 -6
  41. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy.egg-info/SOURCES.txt +4 -0
  42. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy.egg-info/requires.txt +6 -6
  43. {phasorpy-0.11 → phasorpy-0.13}/tests/conftest.py +8 -4
  44. {phasorpy-0.11 → phasorpy-0.13}/tests/io/_conftest.py +4 -0
  45. {phasorpy-0.11 → phasorpy-0.13}/tests/io/test_flimlabs.py +12 -10
  46. {phasorpy-0.11 → phasorpy-0.13}/tests/io/test_leica.py +8 -8
  47. {phasorpy-0.11 → phasorpy-0.13}/tests/io/test_ometiff.py +17 -14
  48. phasorpy-0.13/tests/io/test_other.py +745 -0
  49. {phasorpy-0.11 → phasorpy-0.13}/tests/io/test_simfcs.py +27 -17
  50. {phasorpy-0.11 → phasorpy-0.13}/tests/plot/test_functions.py +61 -16
  51. phasorpy-0.13/tests/plot/test_lifetime_plots.py +196 -0
  52. {phasorpy-0.11 → phasorpy-0.13}/tests/plot/test_phasorplot.py +122 -22
  53. {phasorpy-0.11 → phasorpy-0.13}/tests/plot/test_phasorplot_fret.py +25 -6
  54. phasorpy-0.13/tests/plot/test_spectral_plots.py +275 -0
  55. {phasorpy-0.11 → phasorpy-0.13}/tests/test__phasorpy.py +94 -36
  56. phasorpy-0.13/tests/test__typing.py +10 -0
  57. {phasorpy-0.11 → phasorpy-0.13}/tests/test__utils.py +37 -23
  58. phasorpy-0.13/tests/test_cli.py +113 -0
  59. phasorpy-0.13/tests/test_cluster.py +372 -0
  60. {phasorpy-0.11 → phasorpy-0.13}/tests/test_color.py +21 -6
  61. {phasorpy-0.11 → phasorpy-0.13}/tests/test_component.py +124 -63
  62. {phasorpy-0.11 → phasorpy-0.13}/tests/test_cursor.py +57 -26
  63. {phasorpy-0.11 → phasorpy-0.13}/tests/test_datasets.py +34 -15
  64. phasorpy-0.13/tests/test_experimental.py +118 -0
  65. {phasorpy-0.11 → phasorpy-0.13}/tests/test_filter.py +156 -50
  66. {phasorpy-0.11 → phasorpy-0.13}/tests/test_lifetime.py +179 -72
  67. {phasorpy-0.11 → phasorpy-0.13}/tests/test_nan.py +44 -33
  68. {phasorpy-0.11 → phasorpy-0.13}/tests/test_phasor.py +161 -68
  69. phasorpy-0.13/tests/test_phasorpy.py +12 -0
  70. {phasorpy-0.11 → phasorpy-0.13}/tests/test_utils.py +7 -7
  71. {phasorpy-0.11 → phasorpy-0.13}/tools/build_manylinux.cmd +1 -1
  72. {phasorpy-0.11 → phasorpy-0.13}/tools/build_manylinux.sh +1 -1
  73. {phasorpy-0.11 → phasorpy-0.13}/tools/sha256.py +4 -0
  74. phasorpy-0.13/tutorials/api/phasorpy_cluster.py +212 -0
  75. {phasorpy-0.11 → phasorpy-0.13}/tutorials/api/phasorpy_component.py +4 -0
  76. {phasorpy-0.11 → phasorpy-0.13}/tutorials/api/phasorpy_cursor.py +4 -0
  77. {phasorpy-0.11 → phasorpy-0.13}/tutorials/api/phasorpy_filter.py +4 -0
  78. {phasorpy-0.11 → phasorpy-0.13}/tutorials/api/phasorpy_fret.py +4 -0
  79. {phasorpy-0.11 → phasorpy-0.13}/tutorials/api/phasorpy_io.py +10 -4
  80. {phasorpy-0.11 → phasorpy-0.13}/tutorials/api/phasorpy_lifetime_to_signal.py +6 -2
  81. {phasorpy-0.11 → phasorpy-0.13}/tutorials/api/phasorpy_multi_harmonic.py +5 -0
  82. {phasorpy-0.11 → phasorpy-0.13}/tutorials/api/phasorpy_pca.py +4 -0
  83. {phasorpy-0.11 → phasorpy-0.13}/tutorials/api/phasorpy_phasor_from_lifetime.py +4 -0
  84. {phasorpy-0.11 → phasorpy-0.13}/tutorials/api/phasorpy_phasorplot.py +7 -3
  85. {phasorpy-0.11 → phasorpy-0.13}/tutorials/applications/phasorpy_component_fit.py +4 -0
  86. {phasorpy-0.11 → phasorpy-0.13}/tutorials/applications/phasorpy_fret_efficiency.py +27 -9
  87. {phasorpy-0.11 → phasorpy-0.13}/tutorials/applications/phasorpy_multidimensional.py +4 -0
  88. {phasorpy-0.11 → phasorpy-0.13}/tutorials/applications/phasorpy_nadh_concentration.py +4 -0
  89. {phasorpy-0.11 → phasorpy-0.13}/tutorials/applications/phasorpy_nadh_fraction.py +21 -12
  90. {phasorpy-0.11 → phasorpy-0.13}/tutorials/misc/phasorpy_apps.py +47 -6
  91. {phasorpy-0.11 → phasorpy-0.13}/tutorials/misc/phasorpy_logo.py +4 -0
  92. {phasorpy-0.11 → phasorpy-0.13}/tutorials/misc/phasorpy_phasor_from_signal.py +41 -34
  93. {phasorpy-0.11 → phasorpy-0.13}/tutorials/phasorpy_introduction.py +18 -6
  94. {phasorpy-0.11 → phasorpy-0.13}/tutorials/phasorpy_lfd_workshop.py +4 -0
  95. {phasorpy-0.11 → phasorpy-0.13}/tutorials/phasorpy_lifetime_geometry.py +26 -48
  96. phasorpy-0.11/docs/acknowledgments.rst +0 -42
  97. phasorpy-0.11/src/phasorpy/__init__.py +0 -9
  98. phasorpy-0.11/src/phasorpy/cli.py +0 -162
  99. phasorpy-0.11/src/phasorpy/cluster.py +0 -227
  100. phasorpy-0.11/src/phasorpy/experimental.py +0 -146
  101. phasorpy-0.11/tests/io/test_other.py +0 -362
  102. phasorpy-0.11/tests/plot/test_lifetime_plots.py +0 -105
  103. phasorpy-0.11/tests/test__typing.py +0 -10
  104. phasorpy-0.11/tests/test_cli.py +0 -63
  105. phasorpy-0.11/tests/test_cluster.py +0 -110
  106. phasorpy-0.11/tests/test_experimental.py +0 -37
  107. phasorpy-0.11/tests/test_phasorpy.py +0 -12
  108. {phasorpy-0.11 → phasorpy-0.13}/LICENSE.txt +0 -0
  109. {phasorpy-0.11 → phasorpy-0.13}/MANIFEST.in +0 -0
  110. {phasorpy-0.11 → phasorpy-0.13}/README.md +0 -0
  111. {phasorpy-0.11 → phasorpy-0.13}/docs/_static/categorical.png +0 -0
  112. {phasorpy-0.11 → phasorpy-0.13}/docs/_static/custom-icons.js +0 -0
  113. {phasorpy-0.11 → phasorpy-0.13}/docs/_static/favicon.ico +0 -0
  114. {phasorpy-0.11 → phasorpy-0.13}/docs/_static/phasorpy_logo.png +0 -0
  115. {phasorpy-0.11 → phasorpy-0.13}/docs/_static/phasorpy_logo.svg +0 -0
  116. {phasorpy-0.11 → phasorpy-0.13}/docs/_static/srgb_spectrum.png +0 -0
  117. {phasorpy-0.11 → phasorpy-0.13}/docs/api/_phasorpy.rst +0 -0
  118. {phasorpy-0.11 → phasorpy-0.13}/docs/api/_utils.rst +0 -0
  119. {phasorpy-0.11 → phasorpy-0.13}/docs/api/cli.rst +0 -0
  120. {phasorpy-0.11 → phasorpy-0.13}/docs/api/cluster.rst +0 -0
  121. {phasorpy-0.11 → phasorpy-0.13}/docs/api/color.rst +0 -0
  122. {phasorpy-0.11 → phasorpy-0.13}/docs/api/component.rst +0 -0
  123. {phasorpy-0.11 → phasorpy-0.13}/docs/api/cursor.rst +0 -0
  124. {phasorpy-0.11 → phasorpy-0.13}/docs/api/datasets.rst +0 -0
  125. {phasorpy-0.11 → phasorpy-0.13}/docs/api/experimental.rst +0 -0
  126. {phasorpy-0.11 → phasorpy-0.13}/docs/api/filter.rst +0 -0
  127. {phasorpy-0.11 → phasorpy-0.13}/docs/api/index.rst +0 -0
  128. {phasorpy-0.11 → phasorpy-0.13}/docs/api/io.rst +0 -0
  129. {phasorpy-0.11 → phasorpy-0.13}/docs/api/lifetime.rst +0 -0
  130. {phasorpy-0.11 → phasorpy-0.13}/docs/api/phasor.rst +0 -0
  131. {phasorpy-0.11 → phasorpy-0.13}/docs/api/phasorpy.rst +0 -0
  132. {phasorpy-0.11 → phasorpy-0.13}/docs/api/plot.rst +0 -0
  133. {phasorpy-0.11 → phasorpy-0.13}/docs/api/utils.rst +0 -0
  134. {phasorpy-0.11 → phasorpy-0.13}/docs/code_of_conduct.rst +0 -0
  135. {phasorpy-0.11 → phasorpy-0.13}/docs/license.rst +0 -0
  136. {phasorpy-0.11 → phasorpy-0.13}/setup.cfg +0 -0
  137. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy/py.typed +0 -0
  138. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy.egg-info/dependency_links.txt +0 -0
  139. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy.egg-info/entry_points.txt +0 -0
  140. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy.egg-info/not-zip-safe +0 -0
  141. {phasorpy-0.11 → phasorpy-0.13}/src/phasorpy.egg-info/top_level.txt +0 -0
  142. {phasorpy-0.11 → phasorpy-0.13}/tutorials/README.rst +0 -0
  143. {phasorpy-0.11 → phasorpy-0.13}/tutorials/api/README.rst +0 -0
  144. {phasorpy-0.11 → phasorpy-0.13}/tutorials/applications/README.rst +0 -0
  145. {phasorpy-0.11 → phasorpy-0.13}/tutorials/misc/README.rst +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: phasorpy
3
- Version: 0.11
3
+ Version: 0.13
4
4
  Summary: Analysis of luminescence lifetime and hyperspectral images using the phasor approach
5
5
  Author: PhasorPy Contributors
6
6
  License-Expression: MIT
@@ -21,14 +21,15 @@ Classifier: Programming Language :: Python :: 3 :: Only
21
21
  Classifier: Programming Language :: Python :: 3.12
22
22
  Classifier: Programming Language :: Python :: 3.13
23
23
  Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Programming Language :: Python :: 3.15
24
25
  Requires-Python: >=3.12
25
26
  Description-Content-Type: text/markdown
26
27
  License-File: LICENSE.txt
27
28
  Requires-Dist: numpy>=2.1.0
28
- Requires-Dist: matplotlib>=3.9.0
29
- Requires-Dist: pandas>=2.3.0
29
+ Requires-Dist: matplotlib>=3.10.3
30
+ Requires-Dist: pandas>=2.3.2
30
31
  Requires-Dist: scikit-learn>=1.5.0
31
- Requires-Dist: scipy>=1.14.0
32
+ Requires-Dist: scipy>=1.14.1
32
33
  Requires-Dist: tifffile>=2026.5.2
33
34
  Requires-Dist: xarray>=2024.6.0
34
35
  Requires-Dist: click
@@ -37,12 +38,12 @@ Requires-Dist: tqdm
37
38
  Provides-Extra: all
38
39
  Requires-Dist: czifile>=2026.4.11; extra == "all"
39
40
  Requires-Dist: fbdfile>=2025.9.18; extra == "all"
40
- Requires-Dist: lfdfiles>=2026.4.30; extra == "all"
41
+ Requires-Dist: lfdfiles>=2026.6.24; extra == "all"
41
42
  Requires-Dist: liffile>=2025.2.10; extra == "all"
42
43
  Requires-Dist: ptufile>=2024.9.14; extra == "all"
43
44
  Requires-Dist: sdtfile>=2024.5.24; extra == "all"
44
45
  Requires-Dist: pawflim>=1.0.4; extra == "all"
45
- Requires-Dist: imagecodecs==2026.6.6; (sys_platform == "darwin" and platform_machine == "x86_64") and extra == "all"
46
+ Requires-Dist: brighteyes-mcs-reader>=0.1.0; python_version < "3.15" and extra == "all"
46
47
  Dynamic: license-file
47
48
 
48
49
  # <img src="https://www.phasorpy.org/_static/phasorpy_logo.svg" alt="&#x25CB;" width="48" height="48" align="left"/> PhasorPy
@@ -1,23 +1,28 @@
1
1
  [
2
2
  {
3
3
  "name": "dev",
4
- "version": "0.12",
4
+ "version": "0.14",
5
5
  "url": "https://www.phasorpy.org/docs/dev/"
6
6
  },
7
7
  {
8
- "name": "0.11 (stable)",
9
- "version": "0.11",
8
+ "name": "0.13 (stable)",
9
+ "version": "0.13",
10
10
  "url": "https://www.phasorpy.org/docs/stable/",
11
11
  "preferred": true
12
12
  },
13
+ {
14
+ "name": "0.12",
15
+ "version": "0.12",
16
+ "url": "https://www.phasorpy.org/docs/v0.12/"
17
+ },
18
+ {
19
+ "name": "0.11",
20
+ "version": "0.11",
21
+ "url": "https://www.phasorpy.org/docs/v0.11/"
22
+ },
13
23
  {
14
24
  "name": "0.10",
15
25
  "version": "0.10",
16
26
  "url": "https://www.phasorpy.org/docs/v0.10/"
17
- },
18
- {
19
- "name": "0.9",
20
- "version": "0.9",
21
- "url": "https://www.phasorpy.org/docs/v0.9/"
22
27
  }
23
28
  ]
@@ -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>`_.
@@ -0,0 +1,3 @@
1
+ :orphan:
2
+
3
+ See :doc:`about`
@@ -1,3 +1,7 @@
1
+ # Copyright (c) PhasorPy Contributors
2
+ # SPDX-License-Identifier: MIT
3
+ # See LICENSE.txt file in the project root for details.
4
+
1
5
  """Sphinx build configuration file.
2
6
 
3
7
  https://www.sphinx-doc.org/en/master/usage/configuration.html
@@ -13,6 +17,8 @@ sys.path.insert(0, os.path.dirname(__file__))
13
17
 
14
18
  # remove the examples header from HTML tutorials
15
19
  import sphinx_gallery.gen_rst
20
+ from docutils import nodes
21
+ from sphinx.application import Sphinx
16
22
  from sphinx_gallery.sorting import ExplicitOrder
17
23
 
18
24
  sphinx_gallery.gen_rst.EXAMPLE_HEADER = (
@@ -47,7 +53,6 @@ extensions = [
47
53
  # don't enable intersphinx since tutorials are getting littered with links
48
54
  # 'sphinx.ext.intersphinx',
49
55
  # 'numpydoc',
50
- 'sphinx_inline_tabs',
51
56
  'sphinx_copybutton',
52
57
  'sphinx_click',
53
58
  'sphinx_issues',
@@ -148,9 +153,6 @@ sphinx_gallery_conf = {
148
153
  # 'backreferences_dir': None,
149
154
  }
150
155
 
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
156
 
155
157
  class TutorialOrder:
156
158
  """Order tutorials in gallery subsections."""
@@ -174,6 +176,7 @@ class TutorialOrder:
174
176
  'multi_harmonic',
175
177
  'phasorplot',
176
178
  'cursor',
179
+ 'cluster',
177
180
  'component',
178
181
  'pca',
179
182
  # misc
@@ -210,6 +213,29 @@ intersphinx_mapping = {
210
213
  # do not show typehints
211
214
  autodoc_typehints = 'none'
212
215
 
216
+ # redirect links to defunct websites, for example, to the Web Archive
217
+ link_redirects = {
218
+ 'https://www.lfd.uci.edu': (
219
+ 'https://web.archive.org/web/20260926221331/https://www.lfd.uci.edu'
220
+ ),
221
+ }
222
+
223
+
224
+ def redirect_links(app: Sphinx, doctree: nodes.document) -> None:
225
+ """Replace URL prefixes in links according to link_redirects."""
226
+ del app
227
+ for node in doctree.findall(nodes.reference):
228
+ refuri = node.get('refuri', '')
229
+ for old, new in link_redirects.items():
230
+ if refuri.startswith(old):
231
+ node['refuri'] = new + refuri[len(old) :]
232
+ break
233
+
234
+
235
+ def setup(app: Sphinx) -> None:
236
+ """Set up Sphinx app with link redirection."""
237
+ app.connect('doctree-read', redirect_links)
238
+
213
239
 
214
240
  def linkcode_resolve(domain: str, info: dict[str, str]) -> str | None:
215
241
  """Return GitHub URL for Python object."""
@@ -235,8 +261,8 @@ def linkcode_resolve(domain: str, info: dict[str, str]) -> str | None:
235
261
  except AttributeError:
236
262
  return None
237
263
 
238
- if inspect.isfunction(obj):
239
- obj = inspect.unwrap(obj)
264
+ if inspect.isfunction(obj): # type: ignore[unreachable]
265
+ obj = inspect.unwrap(obj) # type: ignore[unreachable]
240
266
  try:
241
267
  fn = inspect.getsourcefile(obj)
242
268
  except TypeError:
@@ -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.1
65
- phasorpy-0.8
66
- numpy-2.3.5
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
- User-facing classes and functions must use
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` explains how to get support, report bugs,
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:`acknowledgments` list individuals and organizations that
29
- contributed to the development of PhasorPy.
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
  ------------------
@@ -150,16 +150,19 @@ luminescence time-resolved or spectral images:
150
150
  - :ref:`PhasorPy <phasorpy>`,
151
151
  :ref:`tttrlib <tttrlib>`,
152
152
  :ref:`FLIMLib <flimlib>`:sup:`2`,
153
+ :ref:`PyFLI <pyfli>`:sup:`2`,
153
154
  :ref:`BrightEyes <brighteyes>`:sup:`2`,
154
155
  :ref:`FLIM_tools <flim_tools>`:sup:`2,4`,
155
156
  :ref:`Cell-analysis-tools <cell_analysis_tools>`:sup:`2,4`
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 AGPL-3.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
 
@@ -1,8 +1,8 @@
1
1
  [build-system]
2
2
  requires = [
3
- "setuptools>=68",
3
+ "setuptools>=77",
4
4
  "numpy>=2.1.0",
5
- "cython>=3.2.4",
5
+ "cython>=3.2.9",
6
6
  ]
7
7
  build-backend = "setuptools.build_meta"
8
8
 
@@ -15,11 +15,11 @@ dependencies = [
15
15
  # sync with [dependency-groups.run]
16
16
  # https://scientific-python.org/specs/spec-0000/
17
17
  "numpy>=2.1.0",
18
- "matplotlib>=3.9.0",
19
- "pandas>=2.3.0",
18
+ "matplotlib>=3.10.3",
19
+ "pandas>=2.3.2",
20
20
  # "scikit-image>=0.24.0",
21
21
  "scikit-learn>=1.5.0",
22
- "scipy>=1.14.0",
22
+ "scipy>=1.14.1",
23
23
  "tifffile>=2026.5.2",
24
24
  "xarray>=2024.6.0",
25
25
  "click",
@@ -39,6 +39,7 @@ classifiers = [
39
39
  "Programming Language :: Python :: 3.12",
40
40
  "Programming Language :: Python :: 3.13",
41
41
  "Programming Language :: Python :: 3.14",
42
+ "Programming Language :: Python :: 3.15",
42
43
  ]
43
44
  authors = [{ name = "PhasorPy Contributors" }]
44
45
  license = "MIT"
@@ -60,12 +61,13 @@ all = [
60
61
  # sync with [dependency-groups.optional]
61
62
  "czifile>=2026.4.11",
62
63
  "fbdfile>=2025.9.18",
63
- "lfdfiles>=2026.4.30",
64
+ "lfdfiles>=2026.6.24",
64
65
  "liffile>=2025.2.10",
65
66
  "ptufile>=2024.9.14",
66
67
  "sdtfile>=2024.5.24",
67
68
  "pawflim>=1.0.4",
68
- "imagecodecs==2026.6.6; sys_platform == 'darwin' and platform_machine == 'x86_64'",
69
+ "brighteyes-mcs-reader>=0.1.0; python_version < '3.15'",
70
+ # "imagecodecs==2026.6.6; sys_platform == 'darwin' and platform_machine == 'x86_64'",
69
71
  # "mkl-fft>=2.1.1",
70
72
  ]
71
73
 
@@ -73,10 +75,10 @@ all = [
73
75
  run = [
74
76
  # runtime dependencies; sync with [project.dependencies]
75
77
  "numpy>=2.1.0",
76
- "matplotlib>=3.10.0",
77
- "pandas>=2.3.0",
78
+ "matplotlib>=3.10.3",
79
+ "pandas>=2.3.2",
78
80
  "scikit-learn>=1.5.0",
79
- "scipy>=1.14.0",
81
+ "scipy>=1.14.1",
80
82
  "tifffile>=2026.5.2",
81
83
  "xarray>=2024.6.0",
82
84
  "click",
@@ -87,12 +89,13 @@ optional = [
87
89
  # optional runtime dependencies; sync with [project.optional-dependencies]
88
90
  "czifile>=2026.4.11",
89
91
  "fbdfile>=2025.9.18",
90
- "lfdfiles>=2026.4.30",
92
+ "lfdfiles>=2026.6.24",
91
93
  "liffile>=2025.2.10",
92
94
  "ptufile>=2024.9.14",
93
95
  "sdtfile>=2024.5.24",
94
96
  "pawflim>=1.0.4",
95
- "imagecodecs==2026.6.6; sys_platform == 'darwin' and platform_machine == 'x86_64'",
97
+ "brighteyes-mcs-reader>=0.1.0; python_version < '3.15'",
98
+ # "imagecodecs==2026.6.6; sys_platform == 'darwin' and platform_machine == 'x86_64'",
96
99
  ]
97
100
  minimal = [
98
101
  # minimal runtime versions for testing against oldest supported versions
@@ -106,15 +109,16 @@ minimal = [
106
109
  # optional
107
110
  "czifile==2026.4.11; python_version == \"3.12\"",
108
111
  "fbdfile==2025.9.18; python_version == \"3.12\"",
109
- "lfdfiles==2026.4.30; python_version == \"3.12\"",
112
+ "lfdfiles==2026.6.24; python_version == \"3.12\"",
110
113
  "liffile==2025.2.10; python_version == \"3.12\"",
111
114
  "ptufile==2024.9.14; python_version == \"3.12\"",
112
115
  "sdtfile==2024.5.24; python_version == \"3.12\"",
113
116
  "pawflim==1.0.4; python_version == \"3.12\"",
117
+ "brighteyes-mcs-reader==0.1.0; python_version == \"3.12\""
114
118
  ]
115
119
  build = [
116
120
  # build requirements
117
- "cython>=3.2.4",
121
+ "cython>=3.2.9",
118
122
  "numpy>=2.1.0",
119
123
  "abi3audit",
120
124
  "build",
@@ -140,7 +144,6 @@ docs = [
140
144
  "sphinx",
141
145
  "sphinx-copybutton",
142
146
  "sphinx-design",
143
- "sphinx-inline-tabs",
144
147
  "sphinx-issues",
145
148
  "sphinx_click",
146
149
  "sphinx_gallery",
@@ -148,7 +151,7 @@ docs = [
148
151
  lint = [
149
152
  # static code analysis requirements
150
153
  "autoflake",
151
- "black",
154
+ "black>=26.10.1",
152
155
  "blackdoc",
153
156
  # "codespell",
154
157
  "cython_lint",
@@ -260,9 +263,9 @@ typing-modules = ["_typing"]
260
263
  "__init__.py" = ["F401", "F403"]
261
264
  "conftest.py" = ["ARG001"]
262
265
  "setup.py" = ["T201"]
263
- "tests/*" = ["ANN", "D", "INP001", "PT011", "SLF001", "S101"]
266
+ "tests/*" = ["INP001", "PT011", "SLF001", "TC001", "PLR0917"]
264
267
  "tools/*" = ["ANN", "INP001", "T201"]
265
- "tutorials/*" = ["ANN", "D", "E402", "INP001", "T201", "S101", "ERA001"]
268
+ "tutorials/*" = ["ANN", "D", "E402", "INP001", "T201", "PLR0917"]
266
269
  "docs/conf.py" = ["A001", "ANN204", "D102", "E402", "INP001", "RUF012"]
267
270
 
268
271
  [tool.ruff.format]
@@ -271,6 +274,9 @@ quote-style = "single"
271
274
  [tool.ruff.lint.flake8-quotes]
272
275
  inline-quotes = "single"
273
276
 
277
+ [tool.ruff.lint.flake8-copyright]
278
+ notice-rgx = "(#\\s*Copyright\\s*\\(c\\)\\s*PhasorPy\\s*Contributors)"
279
+
274
280
  [tool.ruff.lint.pydocstyle]
275
281
  convention = "numpy"
276
282
 
@@ -305,7 +311,7 @@ disable = [
305
311
 
306
312
  [tool.black]
307
313
  line-length = 79
308
- target-version = ["py312", "py313", "py314"]
314
+ target-version = ["py312", "py313", "py314", "py315"]
309
315
  skip-string-normalization = true
310
316
 
311
317
  [tool.isort]
@@ -332,7 +338,7 @@ ND2 = "ND2"
332
338
  OIF = "OIF"
333
339
 
334
340
  [tool.mypy]
335
- packages = ["phasorpy"]
341
+ packages = ["phasorpy", "tests"]
336
342
  mypy_path = "$MYPY_CONFIG_FILE_DIR/src"
337
343
  plugins = []
338
344
  enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
@@ -341,14 +347,24 @@ warn_unreachable = true
341
347
 
342
348
  [[tool.mypy.overrides]]
343
349
  module = [
350
+ "_conftest",
344
351
  "phasorpy._phasorpy",
352
+ "setuptools.*",
353
+ "sphinx_gallery.*",
345
354
  "pooch.*",
346
355
  "scipy.*",
347
356
  "mkl_fft.*",
348
357
  "sklearn.*",
358
+ "h5py.*",
349
359
  ]
350
360
  ignore_missing_imports = true
351
361
 
362
+ [[tool.mypy.overrides]]
363
+ # PyQt6 6.12 stubs contain syntax errors that block mypy
364
+ module = ["PyQt6.*"]
365
+ follow_imports = "skip"
366
+ follow_imports_for_stubs = true
367
+
352
368
  [tool.coverage.run]
353
369
  plugins = ["Cython.Coverage"]
354
370
  omit = ["conftest.py", "__main__.py"]
@@ -388,7 +404,6 @@ norecursedirs = [
388
404
  ".pytest_cache",
389
405
  ".ruff_cache",
390
406
  ".vscode",
391
- "htmlcov",
392
407
  "adhoc",
393
408
  "build",
394
409
  "docs/_build",
@@ -402,29 +417,20 @@ norecursedirs = [
402
417
  ]
403
418
 
404
419
  [tool.cibuildwheel]
405
- skip = [
406
- "cp38*",
407
- "cp39*",
408
- "cp310*",
409
- "cp311*",
410
- "cp313*",
411
- "cp314-*",
412
- "*musllinux*",
413
- "*i686*",
414
- "*ppc64le*",
415
- "*s390x*",
416
- ]
420
+ build = ["cp312-*", "cp314t-*", "cp315t-*"]
421
+ skip = ["*musllinux*", "*i686*", "*ppc64le*", "*s390x*"]
417
422
  test-command = "pytest {project}/tests"
418
- test-skip = ["cp314t*"]
423
+ test-skip = ["cp3*t*"]
419
424
  test-requires = [
420
425
  # sync with [dependency-groups.optional]
426
+ "brighteyes-mcs-reader>=0.1.0; python_version < '3.15'",
421
427
  "czifile>=2026.4.11",
422
- "fbdfile",
423
- "lfdfiles",
424
- "liffile",
425
- "ptufile",
426
- "sdtfile",
427
- "pawflim",
428
+ "fbdfile>=2025.9.18",
429
+ "lfdfiles>=2026.6.24",
430
+ "liffile>=2025.2.10",
431
+ "ptufile>=2024.9.14",
432
+ "sdtfile>=2024.5.24",
433
+ "pawflim>=1.0.4",
428
434
  # sync with [dependency-groups.test]
429
435
  "coverage",
430
436
  "cython", # for Cython.Coverage plugin
@@ -434,10 +440,10 @@ test-requires = [
434
440
  "pytest-runner",
435
441
  ]
436
442
 
437
- [[tool.cibuildwheel.overrides]]
438
- select = "*-macosx_x86_64"
439
- inherit.test-requires = "append"
440
- test-requires = ["imagecodecs==2026.6.6"]
443
+ # [[tool.cibuildwheel.overrides]]
444
+ # select = "*-macosx_x86_64"
445
+ # inherit.test-requires = "append"
446
+ # test-requires = ["imagecodecs==2026.6.6"]
441
447
 
442
448
  [tool.cibuildwheel.test-environment]
443
449
  PHASORPY_DATA_ON_GITHUB = "1"