PyFiberModes 0.12.0__tar.gz → 0.13.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 (143) hide show
  1. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/.zenodo.json +1 -1
  2. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/CHANGELOG.md +16 -1
  3. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PKG-INFO +12 -6
  4. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/__future__.py +81 -12
  5. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/__init__.py +2 -0
  6. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/_version.py +2 -2
  7. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/analysis.py +113 -4
  8. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/coordinates.py +5 -2
  9. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/factory.py +10 -3
  10. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber.py +272 -155
  11. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/field.py +257 -87
  12. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fundamentals.py +4 -5
  13. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/loader.py +1 -2
  14. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/mode.py +39 -4
  15. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/mode_instances.py +1 -2
  16. pyfibermodes-0.13.0/PyFiberModes/optimization.py +173 -0
  17. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/propagation.py +96 -3
  18. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/solver/__init__.py +2 -0
  19. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/solver/base_solver.py +100 -35
  20. pyfibermodes-0.13.0/PyFiberModes/solver/mlsif/__init__.py +3 -0
  21. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/solver/mlsif/neff.py +236 -110
  22. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/solver/ssif/__init__.py +2 -0
  23. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/solver/ssif/cutoff.py +63 -4
  24. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/solver/ssif/neff.py +225 -158
  25. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/solver/tlsif/__init__.py +2 -0
  26. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/solver/tlsif/cutoff.py +167 -66
  27. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/source.py +16 -2
  28. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/stepindex.py +10 -7
  29. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes.egg-info/PKG-INFO +12 -6
  30. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes.egg-info/SOURCES.txt +22 -0
  31. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes.egg-info/requires.txt +6 -5
  32. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/README.rst +5 -0
  33. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/conda.recipe/meta.yaml +1 -2
  34. pyfibermodes-0.13.0/docs/examples/analysis/README.rst +6 -0
  35. pyfibermodes-0.13.0/docs/examples/analysis/plot_coupled_mode_exchange.py +22 -0
  36. pyfibermodes-0.13.0/docs/examples/analysis/plot_structured_wavelength_sweep.py +27 -0
  37. pyfibermodes-0.13.0/docs/examples/benchmarks/README.rst +7 -0
  38. pyfibermodes-0.13.0/docs/examples/benchmarks/plot_field_grid_scaling.py +28 -0
  39. pyfibermodes-0.13.0/docs/examples/fields/README.rst +7 -0
  40. pyfibermodes-0.13.0/docs/examples/fields/plot_vector_components.py +24 -0
  41. pyfibermodes-0.13.0/docs/examples/validation/README.rst +7 -0
  42. pyfibermodes-0.13.0/docs/examples/validation/plot_effective_index_bounds.py +25 -0
  43. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/source/_static/default.css +21 -1
  44. pyfibermodes-0.13.0/docs/source/_static/favicon.png +0 -0
  45. pyfibermodes-0.13.0/docs/source/_static/logo.png +0 -0
  46. pyfibermodes-0.13.0/docs/source/_static/thumbnail.png +0 -0
  47. pyfibermodes-0.13.0/docs/source/code/analysis.rst +14 -0
  48. pyfibermodes-0.13.0/docs/source/code/fibers.rst +15 -0
  49. pyfibermodes-0.13.0/docs/source/code/fields.rst +11 -0
  50. pyfibermodes-0.13.0/docs/source/code/fundamentals.rst +14 -0
  51. pyfibermodes-0.13.0/docs/source/code.rst +42 -0
  52. pyfibermodes-0.13.0/docs/source/conf.py +193 -0
  53. pyfibermodes-0.13.0/docs/source/examples.rst +73 -0
  54. pyfibermodes-0.13.0/docs/source/getting_started.rst +34 -0
  55. pyfibermodes-0.13.0/docs/source/index.rst +22 -0
  56. pyfibermodes-0.13.0/docs/source/performance.rst +20 -0
  57. pyfibermodes-0.13.0/docs/source/references.rst +12 -0
  58. pyfibermodes-0.13.0/docs/source/theory.rst +34 -0
  59. pyfibermodes-0.13.0/docs/source/troubleshooting.rst +33 -0
  60. pyfibermodes-0.13.0/docs/source/workflows.rst +35 -0
  61. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/pyproject.toml +7 -6
  62. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/test_architecture.py +17 -0
  63. pyfibermodes-0.13.0/tests/test_docstrings.py +34 -0
  64. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/test_field.py +36 -0
  65. pyfibermodes-0.12.0/PyFiberModes/optimization.py +0 -86
  66. pyfibermodes-0.12.0/PyFiberModes/solver/mlsif/__init__.py +0 -1
  67. pyfibermodes-0.12.0/docs/source/_static/thumbnail.png +0 -0
  68. pyfibermodes-0.12.0/docs/source/code.rst +0 -55
  69. pyfibermodes-0.12.0/docs/source/conf.py +0 -177
  70. pyfibermodes-0.12.0/docs/source/examples.rst +0 -14
  71. pyfibermodes-0.12.0/docs/source/index.rst +0 -14
  72. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/.coveragerc +0 -0
  73. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/.github/dependabot.yml +0 -0
  74. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/.github/workflows/deploy_PyPi.yml +0 -0
  75. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/.github/workflows/deploy_anaconda.yml +0 -0
  76. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/.github/workflows/deploy_coverage.yml +0 -0
  77. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/.github/workflows/deploy_documentation.yml +0 -0
  78. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/.github/workflows/quality.yml +0 -0
  79. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/.github/workflows/tests.yml +0 -0
  80. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/.gitignore +0 -0
  81. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/CITATION.cff +0 -0
  82. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/CONTRIBUTING.md +0 -0
  83. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/LICENSE +0 -0
  84. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/MANIFEST.in +0 -0
  85. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/Makefile +0 -0
  86. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/directories.py +0 -0
  87. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/1550BHP.yaml +0 -0
  88. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/DCF13.yaml +0 -0
  89. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/DCF1300S_20.yaml +0 -0
  90. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/DCF1300S_26.yaml +0 -0
  91. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/DCF1300S_33.yaml +0 -0
  92. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/DCF1300S_42.yaml +0 -0
  93. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/F2028M12.yaml +0 -0
  94. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/F2028M21.yaml +0 -0
  95. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/F2028M24.yaml +0 -0
  96. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/F2058G1.yaml +0 -0
  97. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/F2058L1.yaml +0 -0
  98. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/HI1060.yaml +0 -0
  99. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/HP630.yaml +0 -0
  100. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/SM1950.yaml +0 -0
  101. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/SMF28.yaml +0 -0
  102. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/fluorine_doped_1%_capillary.yaml +0 -0
  103. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/fluorine_doped_2%_capillary.yaml +0 -0
  104. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/test_fiber.yaml +0 -0
  105. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes/fiber_files/test_multimode_fiber.yaml +0 -0
  106. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes.egg-info/dependency_links.txt +0 -0
  107. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/PyFiberModes.egg-info/top_level.txt +0 -0
  108. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/Makefile +0 -0
  109. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/DCF/README.rst +0 -0
  110. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/DCF/plot_DCF_fields.py +0 -0
  111. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/README.rst +0 -0
  112. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/SMF28/README.rst +0 -0
  113. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/SMF28/plot_smf28.py +0 -0
  114. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/SMF28/plot_smf28_dispersion_vs_wavelength.py +0 -0
  115. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/SMF28/plot_smf28_group_index_vs_wavelength.py +0 -0
  116. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/basic/README.rst +0 -0
  117. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/basic/plot_U_vs_V.py +0 -0
  118. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/basic/plot_comparison_solvers.py +0 -0
  119. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/basic/plot_dispersion.py +0 -0
  120. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/basic/plot_effective_index.py +0 -0
  121. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/basic/plot_fiber_LP_modes.py +0 -0
  122. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/basic/plot_group_index.py +0 -0
  123. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/basic/plot_mode_field.py +0 -0
  124. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/basic/plot_mode_field_1.py +0 -0
  125. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/basic/plot_mode_field_2.py +0 -0
  126. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/examples/basic/plot_neff_tapered_fiber.py +0 -0
  127. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/docs/make.bat +0 -0
  128. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/pytest.ini +0 -0
  129. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/setup.cfg +0 -0
  130. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/__init__.py +0 -0
  131. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/helpers.py +0 -0
  132. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/test_advanced_features.py +0 -0
  133. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/test_api.py +0 -0
  134. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/test_coordinates.py +0 -0
  135. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/test_fiber.py +0 -0
  136. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/test_file_loading.py +0 -0
  137. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/test_release_tools.py +0 -0
  138. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/test_ssif.py +0 -0
  139. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/test_tlsif.py +0 -0
  140. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tests/test_validation.py +0 -0
  141. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tools/check_release.py +0 -0
  142. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tools/next_release_version.py +0 -0
  143. {pyfibermodes-0.12.0 → pyfibermodes-0.13.0}/tools/release_tag.py +0 -0
@@ -9,7 +9,7 @@
9
9
  "license": "MIT",
10
10
  "upload_type": "software",
11
11
  "access_right": "open",
12
- "version": "0.12.0",
12
+ "version": "0.13.0",
13
13
  "publication_date": "2026-09-22",
14
14
  "keywords": [
15
15
  "optical fibers",
@@ -6,6 +6,20 @@ use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.13.0] - 2026-09-22
10
+
11
+ ### Changed
12
+
13
+ - Replaced MPSPlots styling and colormaps with native Matplotlib equivalents,
14
+ removing MPSPlots from all runtime and documentation dependencies.
15
+ - Field maps now share one radial solver pass across all electric and magnetic
16
+ components and cache interpolated, azimuthal, and batched component arrays.
17
+ - Added NumPyDoc documentation across modules, public APIs, data models, and
18
+ numerical solver helpers, with structural coverage enforced by tests.
19
+ - Reorganized the documentation into learning, theory, workflow, performance,
20
+ troubleshooting, gallery, and task-oriented API sections; added four new
21
+ example series and a unified logo and favicon identity.
22
+
9
23
  ## [0.12.0] - 2026-09-22
10
24
 
11
25
  ### Changed
@@ -41,7 +55,8 @@ use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
41
55
 
42
56
  - Established the current tagged baseline for subsequent documented releases.
43
57
 
44
- [Unreleased]: https://github.com/MartinPdeS/PyFiberModes/compare/v0.12.0...HEAD
58
+ [Unreleased]: https://github.com/MartinPdeS/PyFiberModes/compare/v0.13.0...HEAD
59
+ [0.13.0]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.13.0
45
60
  [0.12.0]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.12.0
46
61
  [0.11.0]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.11.0
47
62
  [0.10.0]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.10.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyFiberModes
3
- Version: 0.12.0
3
+ Version: 0.13.0
4
4
  Summary: A package for light propagation in fiber optics.
5
5
  Author-email: Martin Poinsinet de Sivry-Houle <martin.poinsinet.de.sivry@gmail.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -697,28 +697,34 @@ Requires-Python: >=3.10
697
697
  Description-Content-Type: text/x-rst
698
698
  License-File: LICENSE
699
699
  Requires-Dist: PyOptik<3,>=2
700
- Requires-Dist: MPSPlots
701
700
  Requires-Dist: PyFinitDiff
701
+ Requires-Dist: matplotlib>=3.8
702
702
  Requires-Dist: pyyaml
703
703
  Requires-Dist: numpy
704
704
  Requires-Dist: scipy
705
705
  Provides-Extra: testing
706
- Requires-Dist: pytest<9.0,>=7.4; extra == "testing"
706
+ Requires-Dist: pytest<10.0,>=7.4; extra == "testing"
707
707
  Requires-Dist: pytest-cov<8,>=2; extra == "testing"
708
708
  Requires-Dist: pytest-json-report~=1.5; extra == "testing"
709
709
  Requires-Dist: coverage~=7.6; extra == "testing"
710
710
  Requires-Dist: ruff<1,>=0.8; extra == "testing"
711
711
  Requires-Dist: tomli<3,>=2; python_version < "3.11" and extra == "testing"
712
712
  Provides-Extra: documentation
713
- Requires-Dist: numpydoc==1.9.0; extra == "documentation"
713
+ Requires-Dist: numpydoc==1.10.0; extra == "documentation"
714
714
  Requires-Dist: sphinx>=5.1.1; extra == "documentation"
715
- Requires-Dist: sphinx-gallery==0.19.0; extra == "documentation"
715
+ Requires-Dist: sphinx-gallery==0.21.0; extra == "documentation"
716
+ Requires-Dist: sphinx-design<1,>=0.6; extra == "documentation"
716
717
  Requires-Dist: sphinx-rtd-theme==3.1.0; extra == "documentation"
717
- Requires-Dist: pydata-sphinx-theme==0.14.1; extra == "documentation"
718
+ Requires-Dist: pydata-sphinx-theme==0.17.1; extra == "documentation"
718
719
  Provides-Extra: dev
719
720
  Requires-Dist: ruff<1,>=0.8; extra == "dev"
720
721
  Dynamic: license-file
721
722
 
723
+ .. image:: https://raw.githubusercontent.com/MartinPdeS/PyFiberModes/master/docs/source/_static/logo.png
724
+ :width: 620
725
+ :align: center
726
+ :alt: PyFiberModes logo
727
+
722
728
  .. list-table::
723
729
  :widths: 35 65
724
730
  :header-rows: 1
@@ -1,5 +1,4 @@
1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
1
+ """Experimental field-normalization helpers retained for future APIs."""
3
2
 
4
3
  import numpy
5
4
 
@@ -7,20 +6,28 @@ from PyFiberModes import Mode
7
6
 
8
7
 
9
8
  def get_normalized_LP_coupling(fiber, mode_0: Mode, mode_1: Mode) -> float:
10
- r"""
11
- Gets the normalized coupling between two supermodes as defined in Equation 7.39 Jacques Bures.
9
+ r"""Calculate normalized coupling between two LP supermodes.
12
10
 
13
- .. math::
11
+ Parameters
12
+ ----------
13
+ fiber : Fiber
14
+ Fiber providing propagation constants and interface fields.
15
+ mode_0, mode_1 : Mode
16
+ Linearly polarized modes to couple.
14
17
 
15
- \tilde{C_{ij}} = \frac{0.5 k_0^2}{(\beta_0 - \beta_1) \sqrt{\beta_0 * \beta_1}} \sum_i r_i^2 \psi_0(r_i) * \psi_1(r_i)
18
+ Returns
19
+ -------
20
+ float
21
+ Normalized coupling coefficient.
16
22
 
17
- :param mode_0: The mode 0
18
- :type mode_0: Mode
19
- :param mode_1: The mode 1
20
- :type mode_1: Mode
23
+ Notes
24
+ -----
25
+ The calculation follows Equation 7.39 of Jacques Bures,
26
+ *Optical Fiber Theory*:
21
27
 
22
- :returns: The normalized coupling.
23
- :rtype: float
28
+ .. math::
29
+
30
+ \tilde{C_{ij}} = \frac{0.5 k_0^2}{(\beta_0 - \beta_1) \sqrt{\beta_0 * \beta_1}} \sum_i r_i^2 \psi_0(r_i) * \psi_1(r_i)
24
31
  """
25
32
  assert mode_0.family == 'LP' and mode_1.family == 'LP', "The normalized coupling equation are only valid for scalar [LP] modes"
26
33
 
@@ -56,6 +63,20 @@ def get_normalized_LP_coupling(fiber, mode_0: Mode, mode_1: Mode) -> float:
56
63
 
57
64
 
58
65
  def get_LP_mode_norm(fiber, mode: Mode) -> float:
66
+ """Calculate the radial normalization integral of an LP mode.
67
+
68
+ Parameters
69
+ ----------
70
+ fiber : Fiber
71
+ Fiber providing radial fields and outer radius.
72
+ mode : Mode
73
+ Linearly polarized mode to normalize.
74
+
75
+ Returns
76
+ -------
77
+ float
78
+ Scalar radial-field norm.
79
+ """
59
80
  radius_list = numpy.linspace(0, 2 * fiber.radius, 100)
60
81
 
61
82
  amplitudes = get_LP_mode_radial_field(
@@ -70,6 +91,24 @@ def get_LP_mode_norm(fiber, mode: Mode) -> float:
70
91
 
71
92
 
72
93
  def get_LP_mode_radial_normalized_field(fiber, mode: Mode, radius_list: numpy.ndarray = None) -> float:
94
+ """Sample and normalize the scalar radial field of an LP mode.
95
+
96
+ Parameters
97
+ ----------
98
+ fiber : Fiber
99
+ Fiber providing radial fields.
100
+ mode : Mode
101
+ Linearly polarized mode to sample.
102
+ radius_list : numpy.ndarray, optional
103
+ Radial sampling positions in meters.
104
+
105
+ Returns
106
+ -------
107
+ normalized_field : numpy.ndarray
108
+ Unit-normalized scalar field samples.
109
+ radius_list : numpy.ndarray
110
+ Radial positions associated with the samples.
111
+ """
73
112
  if radius_list is None:
74
113
  radius_list = numpy.linspace(0, 2 * fiber.radius, 200)
75
114
 
@@ -85,6 +124,22 @@ def get_LP_mode_radial_normalized_field(fiber, mode: Mode, radius_list: numpy.nd
85
124
 
86
125
 
87
126
  def get_LP_mode_radial_field(fiber, mode: Mode, radius_list: numpy.ndarray) -> float:
127
+ """Sample the scalar radial electric field of an LP mode.
128
+
129
+ Parameters
130
+ ----------
131
+ fiber : Fiber
132
+ Fiber providing radial fields.
133
+ mode : Mode
134
+ Linearly polarized mode to sample.
135
+ radius_list : numpy.ndarray
136
+ Radial sampling positions in meters.
137
+
138
+ Returns
139
+ -------
140
+ numpy.ndarray
141
+ Radial electric-field amplitude at each position.
142
+ """
88
143
  amplitudes = numpy.empty(radius_list.size)
89
144
 
90
145
  for idx, rho in enumerate(radius_list):
@@ -95,6 +150,20 @@ def get_LP_mode_radial_field(fiber, mode: Mode, radius_list: numpy.ndarray) -> f
95
150
 
96
151
 
97
152
  def get_scalar_field_norm(rho_list: numpy.ndarray, field: numpy.ndarray) -> float:
153
+ r"""Integrate the cylindrical norm of a scalar radial field.
154
+
155
+ Parameters
156
+ ----------
157
+ rho_list : numpy.ndarray
158
+ Uniform radial sampling positions.
159
+ field : numpy.ndarray
160
+ Scalar field amplitude at each radial position.
161
+
162
+ Returns
163
+ -------
164
+ float
165
+ Value of :math:`2\pi\int |E(\rho)|^2\rho\,d\rho`.
166
+ """
98
167
  rho_list = numpy.asarray(rho_list)
99
168
  field = numpy.asarray(field)
100
169
  dr = rho_list[1] - rho_list[0]
@@ -1,3 +1,5 @@
1
+ """Public API for circular optical-fiber mode analysis."""
2
+
1
3
  from PyFiberModes.mode import Mode, Family # noqa: F401
2
4
  from PyFiberModes.mode_instances import * # noqa: F403
3
5
  from PyFiberModes.factory import FiberFactory
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.12.0'
22
- __version_tuple__ = version_tuple = (0, 12, 0)
21
+ __version__ = version = '0.13.0'
22
+ __version_tuple__ = version_tuple = (0, 13, 0)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -11,10 +11,21 @@ from PyFiberModes.mode import Mode
11
11
 
12
12
  @dataclass(frozen=True)
13
13
  class ModeSweepResult:
14
- """Dense, dependency-free result returned by :func:`sweep_modes`.
14
+ """Store modal quantities evaluated over a parameter sweep.
15
15
 
16
16
  Rows correspond to ``parameters`` and columns to ``modes``. Missing or
17
17
  unguided solutions are represented by NaN.
18
+
19
+ Parameters
20
+ ----------
21
+ parameter_name : str
22
+ Name of the swept parameter.
23
+ parameters : numpy.ndarray
24
+ One-dimensional parameter values.
25
+ modes : tuple of Mode
26
+ Modes represented by the columns of every value array.
27
+ values : dict of str to numpy.ndarray
28
+ Modal metrics shaped ``(n_parameters, n_modes)``.
18
29
  """
19
30
 
20
31
  parameter_name: str
@@ -23,13 +34,44 @@ class ModeSweepResult:
23
34
  values: dict[str, np.ndarray]
24
35
 
25
36
  def __getitem__(self, metric: str) -> np.ndarray:
37
+ """Return the array associated with a metric name.
38
+
39
+ Parameters
40
+ ----------
41
+ metric : str
42
+ Metric key stored in :attr:`values`.
43
+
44
+ Returns
45
+ -------
46
+ numpy.ndarray
47
+ Metric values shaped ``(n_parameters, n_modes)``.
48
+ """
26
49
  return self.values[metric]
27
50
 
28
51
  def for_mode(self, mode: Mode) -> dict[str, np.ndarray]:
52
+ """Extract every metric for one mode.
53
+
54
+ Parameters
55
+ ----------
56
+ mode : Mode
57
+ Mode whose column is requested.
58
+
59
+ Returns
60
+ -------
61
+ dict of str to numpy.ndarray
62
+ Mapping from metric names to one-dimensional sweep values.
63
+ """
29
64
  index = self.modes.index(mode)
30
65
  return {name: value[:, index] for name, value in self.values.items()}
31
66
 
32
67
  def as_records(self) -> list[dict]:
68
+ """Convert the dense result into row-oriented records.
69
+
70
+ Returns
71
+ -------
72
+ list of dict
73
+ One record for every parameter and mode combination.
74
+ """
33
75
  return [
34
76
  {self.parameter_name: float(parameter), "mode": mode, **{
35
77
  name: float(array[i, j]) for name, array in self.values.items()
@@ -42,7 +84,22 @@ class ModeSweepResult:
42
84
  def candidate_modes(
43
85
  families: Sequence[str] = ("LP",), max_nu: int = 6, max_m: int = 6
44
86
  ) -> tuple[Mode, ...]:
45
- """Generate deterministic candidate modes for automatic discovery."""
87
+ """Generate a deterministic bounded set of mode candidates.
88
+
89
+ Parameters
90
+ ----------
91
+ families : sequence of str, optional
92
+ Mode families to enumerate.
93
+ max_nu : int, optional
94
+ Largest azimuthal order to include.
95
+ max_m : int, optional
96
+ Largest radial order to include.
97
+
98
+ Returns
99
+ -------
100
+ tuple of Mode
101
+ Candidates ordered by family, azimuthal order, and radial order.
102
+ """
46
103
  modes = []
47
104
  for family in families:
48
105
  nus = (0,) if family in ("TE", "TM") else range(max_nu + 1)
@@ -54,7 +111,25 @@ def candidate_modes(
54
111
 
55
112
 
56
113
  def find_modes(fiber, families=("LP",), max_nu=6, max_m=6) -> tuple[Mode, ...]:
57
- """Return all guided modes among a bounded set of candidates."""
114
+ """Find guided modes supported by a fiber.
115
+
116
+ Parameters
117
+ ----------
118
+ fiber : Fiber
119
+ Fiber on which effective indices are evaluated.
120
+ families : sequence of str, optional
121
+ Mode families to search.
122
+ max_nu : int, optional
123
+ Largest azimuthal order to test.
124
+ max_m : int, optional
125
+ Largest radial order to test.
126
+
127
+ Returns
128
+ -------
129
+ tuple of Mode
130
+ Candidates with finite effective indices between the cladding and
131
+ maximum material indices.
132
+ """
58
133
  found = []
59
134
  for mode in candidate_modes(families, max_nu, max_m):
60
135
  try:
@@ -79,7 +154,40 @@ def sweep_modes(
79
154
  max_nu=6,
80
155
  max_m=6,
81
156
  ) -> ModeSweepResult:
82
- """Track modes over wavelength or any parameter handled by ``setter``."""
157
+ """Evaluate modal metrics over wavelength or another scalar parameter.
158
+
159
+ Parameters
160
+ ----------
161
+ fiber : Fiber
162
+ Fiber used as the immutable sweep template.
163
+ parameters : iterable of float
164
+ Ordered parameter values.
165
+ modes : sequence of Mode, optional
166
+ Modes to evaluate. When omitted, modes are discovered automatically.
167
+ parameter_name : str, optional
168
+ Name recorded in the returned result.
169
+ setter : callable, optional
170
+ Function accepting ``(fiber, value)`` for non-wavelength sweeps.
171
+ metrics : sequence of str, optional
172
+ Suffixes of ``Fiber.get_<metric>`` methods to evaluate.
173
+ families : sequence of str, optional
174
+ Families used during automatic discovery.
175
+ max_nu : int, optional
176
+ Maximum discovered azimuthal order.
177
+ max_m : int, optional
178
+ Maximum discovered radial order.
179
+
180
+ Returns
181
+ -------
182
+ ModeSweepResult
183
+ Dense arrays for each requested metric.
184
+
185
+ Raises
186
+ ------
187
+ ValueError
188
+ If ``parameters`` is empty or not one-dimensional, or when a custom
189
+ parameter is requested without a setter.
190
+ """
83
191
  parameters = np.asarray(tuple(parameters), dtype=float)
84
192
  if parameters.ndim != 1 or not len(parameters):
85
193
  raise ValueError("parameters must be a non-empty one-dimensional sequence")
@@ -89,6 +197,7 @@ def sweep_modes(
89
197
  raise ValueError("a setter is required for non-wavelength sweeps")
90
198
 
91
199
  def setter(current_fiber, value):
200
+ """Update wavelength for the default sweep behavior."""
92
201
  current_fiber.update_wavelength(value)
93
202
  if modes is None:
94
203
  discovered = []
@@ -1,3 +1,5 @@
1
+ """Cartesian and cylindrical sampling-grid definitions."""
2
+
1
3
  import numpy as np
2
4
  from dataclasses import dataclass
3
5
  from typing import Tuple
@@ -8,7 +10,7 @@ class CylindricalCoordinates:
8
10
  """
9
11
  Represents a set of points in cylindrical coordinates.
10
12
 
11
- Attributes
13
+ Parameters
12
14
  ----------
13
15
  rho : np.ndarray
14
16
  Radial distance from the z-axis.
@@ -51,7 +53,7 @@ class CartesianCoordinates:
51
53
  """
52
54
  Represents a set of points in cartesian coordinates.
53
55
 
54
- Attributes
56
+ Parameters
55
57
  ----------
56
58
  x : np.ndarray
57
59
  x-coordinates (must be a 1D array).
@@ -71,6 +73,7 @@ class CartesianCoordinates:
71
73
  is_3D: bool = False
72
74
 
73
75
  def __post_init__(self) -> None:
76
+ """Convert all coordinate arrays to floating-point arrays."""
74
77
  self.x = self.x.astype(float)
75
78
  self.y = self.y.astype(float)
76
79
  self.z = self.z.astype(float)
@@ -1,5 +1,4 @@
1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
1
+ """Factories for constructing parameterized multilayer fibers."""
3
2
 
4
3
  from itertools import product
5
4
  from dataclasses import dataclass, field
@@ -12,7 +11,7 @@ class ProxyLayer:
12
11
  """
13
12
  Represents a layer configuration in a fiber, with name, radius, and refractive index.
14
13
 
15
- Attributes
14
+ Parameters
16
15
  ----------
17
16
  name : str
18
17
  Name of the layer.
@@ -26,6 +25,7 @@ class ProxyLayer:
26
25
  index: list = field(default_factory=list)
27
26
 
28
27
  def __post_init__(self):
28
+ """Normalize scalar layer parameters into one-dimensional arrays."""
29
29
  self.name = [self.name]
30
30
  self.radius = np.atleast_1d(self.radius)
31
31
  self.index = np.atleast_1d(self.index)
@@ -64,6 +64,13 @@ class FiberFactory:
64
64
  """
65
65
 
66
66
  def __init__(self, wavelength: float):
67
+ """Initialize an empty fiber-configuration factory.
68
+
69
+ Parameters
70
+ ----------
71
+ wavelength : float
72
+ Vacuum wavelength in meters for generated fibers.
73
+ """
67
74
  self.layers_list = []
68
75
  self.neff_solver = None
69
76
  self.cutoff_solver = None