PyOptik 2.0.7__tar.gz → 3.0.4__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 (134) hide show
  1. {pyoptik-2.0.7 → pyoptik-3.0.4}/.github/workflows/deploy_anaconda.yml +2 -2
  2. pyoptik-3.0.4/.github/workflows/tests.yml +29 -0
  3. {pyoptik-2.0.7 → pyoptik-3.0.4}/.gitignore +2 -0
  4. pyoptik-3.0.4/CHANGELOG.md +42 -0
  5. pyoptik-3.0.4/Makefile +60 -0
  6. pyoptik-3.0.4/PKG-INFO +429 -0
  7. {pyoptik-2.0.7 → pyoptik-3.0.4}/PyOptik/__init__.py +5 -2
  8. pyoptik-3.0.4/PyOptik/__main__.py +124 -0
  9. {pyoptik-2.0.7 → pyoptik-3.0.4}/PyOptik/_version.py +3 -3
  10. pyoptik-3.0.4/PyOptik/catalog.py +778 -0
  11. pyoptik-3.0.4/PyOptik/directories.py +81 -0
  12. {pyoptik-2.0.7 → pyoptik-3.0.4}/PyOptik/material/base_class.py +130 -12
  13. pyoptik-3.0.4/PyOptik/material/sellmeier_class.py +273 -0
  14. {pyoptik-2.0.7 → pyoptik-3.0.4}/PyOptik/material/tabulated_class.py +65 -20
  15. {pyoptik-2.0.7 → pyoptik-3.0.4}/PyOptik/utils.py +28 -19
  16. pyoptik-3.0.4/PyOptik.egg-info/PKG-INFO +429 -0
  17. pyoptik-3.0.4/PyOptik.egg-info/SOURCES.txt +71 -0
  18. pyoptik-3.0.4/PyOptik.egg-info/entry_points.txt +2 -0
  19. {pyoptik-2.0.7 → pyoptik-3.0.4}/PyOptik.egg-info/requires.txt +0 -1
  20. pyoptik-3.0.4/PyOptik.egg-info/scm_file_list.json +67 -0
  21. pyoptik-3.0.4/PyOptik.egg-info/scm_version.json +8 -0
  22. pyoptik-3.0.4/README.rst +370 -0
  23. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/group_properties/plot_group_properties.py +8 -9
  24. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/sellmeier/plot_bk7.py +3 -2
  25. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/sellmeier/plot_compare_glasses.py +8 -9
  26. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/sellmeier/plot_silica.py +3 -2
  27. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/sellmeier/plot_water.py +3 -2
  28. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/tabulated/plot_polyethylene.py +5 -4
  29. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/tabulated/plot_silicon_nk.py +6 -7
  30. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/tabulated/plot_silver.py +4 -3
  31. pyoptik-3.0.4/docs/images/logo.svg +1 -0
  32. pyoptik-3.0.4/docs/source/_static/favicon.png +0 -0
  33. pyoptik-3.0.4/docs/source/_static/logo.svg +1 -0
  34. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/source/code.rst +28 -15
  35. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/source/conf.py +4 -12
  36. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/source/examples.rst +0 -1
  37. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/source/index.rst +2 -2
  38. pyoptik-3.0.4/docs/source/references.rst +25 -0
  39. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/source/sg_execution_times.rst +15 -30
  40. {pyoptik-2.0.7 → pyoptik-3.0.4}/meta.yaml +9 -5
  41. {pyoptik-2.0.7 → pyoptik-3.0.4}/pyproject.toml +3 -2
  42. {pyoptik-2.0.7 → pyoptik-3.0.4}/pytest.ini +4 -0
  43. pyoptik-3.0.4/tests/conftest.py +23 -0
  44. pyoptik-3.0.4/tests/test_catalog.py +152 -0
  45. pyoptik-3.0.4/tests/test_docstrings.py +16 -0
  46. pyoptik-3.0.4/tests/test_main_cli.py +88 -0
  47. pyoptik-3.0.4/tests/test_material_models.py +114 -0
  48. pyoptik-3.0.4/tests/test_validation_and_logging.py +16 -0
  49. pyoptik-2.0.7/PKG-INFO +0 -427
  50. pyoptik-2.0.7/PyOptik/__main__.py +0 -37
  51. pyoptik-2.0.7/PyOptik/data/sellmeier/BAF10.yml +0 -59
  52. pyoptik-2.0.7/PyOptik/data/sellmeier/BAK1.yml +0 -63
  53. pyoptik-2.0.7/PyOptik/data/sellmeier/BK7.yml +0 -57
  54. pyoptik-2.0.7/PyOptik/data/sellmeier/SF5.yml +0 -57
  55. pyoptik-2.0.7/PyOptik/data/sellmeier/ZBLAN.yml +0 -14
  56. pyoptik-2.0.7/PyOptik/data/sellmeier/acetone.yml +0 -16
  57. pyoptik-2.0.7/PyOptik/data/sellmeier/air.yml +0 -18
  58. pyoptik-2.0.7/PyOptik/data/sellmeier/argon.yml +0 -21
  59. pyoptik-2.0.7/PyOptik/data/sellmeier/crown.yml +0 -61
  60. pyoptik-2.0.7/PyOptik/data/sellmeier/flint.yml +0 -60
  61. pyoptik-2.0.7/PyOptik/data/sellmeier/fused_silica.yml +0 -20
  62. pyoptik-2.0.7/PyOptik/data/sellmeier/germanium.yml +0 -18
  63. pyoptik-2.0.7/PyOptik/data/sellmeier/lithium_niobate.yml +0 -17
  64. pyoptik-2.0.7/PyOptik/data/sellmeier/polystyren.yml +0 -17
  65. pyoptik-2.0.7/PyOptik/data/sellmeier/soda_lime_glass.yml +0 -122
  66. pyoptik-2.0.7/PyOptik/data/sellmeier/water.yml +0 -16
  67. pyoptik-2.0.7/PyOptik/data/tabulated/aluminium.yml +0 -219
  68. pyoptik-2.0.7/PyOptik/data/tabulated/calcium.yml +0 -74
  69. pyoptik-2.0.7/PyOptik/data/tabulated/copper.yml +0 -62
  70. pyoptik-2.0.7/PyOptik/data/tabulated/gold.yml +0 -62
  71. pyoptik-2.0.7/PyOptik/data/tabulated/iron.yml +0 -74
  72. pyoptik-2.0.7/PyOptik/data/tabulated/nickel.yml +0 -62
  73. pyoptik-2.0.7/PyOptik/data/tabulated/polyetylene.yml +0 -34
  74. pyoptik-2.0.7/PyOptik/data/tabulated/silicon.yml +0 -59
  75. pyoptik-2.0.7/PyOptik/data/tabulated/silver.yml +0 -62
  76. pyoptik-2.0.7/PyOptik/data/tabulated/sodium.yml +0 -34
  77. pyoptik-2.0.7/PyOptik/data/tabulated/zinc.yml +0 -163
  78. pyoptik-2.0.7/PyOptik/directories.py +0 -53
  79. pyoptik-2.0.7/PyOptik/libraries/__init__.py +0 -0
  80. pyoptik-2.0.7/PyOptik/libraries/classics.yml +0 -30
  81. pyoptik-2.0.7/PyOptik/libraries/dielectrics.yml +0 -22
  82. pyoptik-2.0.7/PyOptik/libraries/metals.yml +0 -20
  83. pyoptik-2.0.7/PyOptik/libraries/minimal.yml +0 -9
  84. pyoptik-2.0.7/PyOptik/libraries/organics.yml +0 -11
  85. pyoptik-2.0.7/PyOptik/libraries/others.yml +0 -4
  86. pyoptik-2.0.7/PyOptik/libraries/polymers.yml +0 -9
  87. pyoptik-2.0.7/PyOptik/libraries/repertoire.yml +0 -59
  88. pyoptik-2.0.7/PyOptik/material/sellmeier_class.py +0 -197
  89. pyoptik-2.0.7/PyOptik/material_bank.py +0 -529
  90. pyoptik-2.0.7/PyOptik.egg-info/PKG-INFO +0 -427
  91. pyoptik-2.0.7/PyOptik.egg-info/SOURCES.txt +0 -108
  92. pyoptik-2.0.7/README.rst +0 -367
  93. pyoptik-2.0.7/development/dev_0.py +0 -9
  94. pyoptik-2.0.7/docs/examples/utils/README.rst +0 -6
  95. pyoptik-2.0.7/docs/examples/utils/__build_library.py +0 -30
  96. pyoptik-2.0.7/docs/examples/utils/__download_yml_file.py +0 -28
  97. pyoptik-2.0.7/docs/examples/utils/create_sellmeier_file.py +0 -29
  98. pyoptik-2.0.7/docs/examples/utils/create_tabulated_file.py +0 -37
  99. pyoptik-2.0.7/docs/examples/utils/search_materials.py +0 -23
  100. pyoptik-2.0.7/docs/images/logo.png +0 -0
  101. pyoptik-2.0.7/docs/source/references.rst +0 -4
  102. pyoptik-2.0.7/tests/__init__.py +0 -0
  103. pyoptik-2.0.7/tests/test_group_properties.py +0 -42
  104. pyoptik-2.0.7/tests/test_main_cli.py +0 -24
  105. pyoptik-2.0.7/tests/test_material_bank_extra.py +0 -47
  106. pyoptik-2.0.7/tests/test_sellmeier.py +0 -183
  107. pyoptik-2.0.7/tests/test_tabulated.py +0 -128
  108. pyoptik-2.0.7/tests/test_usual_materials.py +0 -51
  109. pyoptik-2.0.7/tests/test_utils.py +0 -165
  110. {pyoptik-2.0.7 → pyoptik-3.0.4}/.coveragerc +0 -0
  111. {pyoptik-2.0.7 → pyoptik-3.0.4}/.flake8 +0 -0
  112. {pyoptik-2.0.7 → pyoptik-3.0.4}/.github/dependabot.yml +0 -0
  113. {pyoptik-2.0.7 → pyoptik-3.0.4}/.github/workflows/deploy_PyPi.yml +0 -0
  114. {pyoptik-2.0.7 → pyoptik-3.0.4}/.github/workflows/deploy_coverage.yml +0 -0
  115. {pyoptik-2.0.7 → pyoptik-3.0.4}/.github/workflows/deploy_documentation.yml +0 -0
  116. {pyoptik-2.0.7 → pyoptik-3.0.4}/.pre-commit-config.yaml +0 -0
  117. {pyoptik-2.0.7 → pyoptik-3.0.4}/LICENSE +0 -0
  118. {pyoptik-2.0.7 → pyoptik-3.0.4}/PyOptik/material/__init__.py +0 -0
  119. {pyoptik-2.0.7 → pyoptik-3.0.4}/PyOptik/material_type.py +0 -0
  120. {pyoptik-2.0.7 → pyoptik-3.0.4}/PyOptik.egg-info/dependency_links.txt +0 -0
  121. {pyoptik-2.0.7 → pyoptik-3.0.4}/PyOptik.egg-info/top_level.txt +0 -0
  122. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/Makefile +0 -0
  123. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/README.rst +0 -0
  124. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/group_properties/README.rst +0 -0
  125. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/sellmeier/README.rst +0 -0
  126. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/examples/tabulated/README.rst +0 -0
  127. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/images/example_bk7.png +0 -0
  128. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/make.bat +0 -0
  129. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/source/_static/default.css +0 -0
  130. {pyoptik-2.0.7 → pyoptik-3.0.4}/docs/source/_static/thumbnail.png +0 -0
  131. {pyoptik-2.0.7 → pyoptik-3.0.4}/setup.cfg +0 -0
  132. {pyoptik-2.0.7/PyOptik/data → pyoptik-3.0.4/tests}/__init__.py +0 -0
  133. {pyoptik-2.0.7 → pyoptik-3.0.4}/tests/test_base_material_decorator.py +0 -0
  134. {pyoptik-2.0.7 → pyoptik-3.0.4}/tests/test_utils_extra.py +0 -0
@@ -14,8 +14,8 @@ jobs:
14
14
  linux:
15
15
  uses: MartinPdeS/MPSActions/.github/workflows/publish_compiled_package_to_anaconda.yml@master
16
16
  with:
17
- python_versions: '["3.11", "3.12", "3.13"]'
17
+ python_versions: '["3.13"]'
18
18
  apt_package: ""
19
- os_list: '["ubuntu-latest", "macos-latest", "windows-latest"]'
19
+ os_list: '["ubuntu-latest"]'
20
20
  secrets:
21
21
  ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_API_TOKEN }}
@@ -0,0 +1,29 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: ["master"]
6
+ pull_request:
7
+ branches: ["master"]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: ${{ matrix.python-version }}
22
+ cache: pip
23
+ - name: Install package and test dependencies
24
+ run: python -m pip install --upgrade pip && python -m pip install -e '.[testing]'
25
+ - name: Run offline test suite
26
+ env:
27
+ MPLBACKEND: Agg
28
+ MPLCONFIGDIR: ${{ runner.temp }}/matplotlib
29
+ run: python -m pytest -m 'not network' --cov=PyOptik --cov-report=term-missing
@@ -17,8 +17,10 @@
17
17
  !README.rst
18
18
  !notebook.ipynb
19
19
  !CMakeLists.txt
20
+ !Makefile
20
21
  !pytest.ini
21
22
  !.coveragerc
23
+ !CHANGELOG.md
22
24
 
23
25
  # But ignore docs/build inside docs and code
24
26
  docs/build/
@@ -0,0 +1,42 @@
1
+ # Changelog
2
+
3
+ All notable changes to PyOptik are documented in this file.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ - Support for all nine RefractiveIndex.INFO dispersion formula types.
13
+ - `MaterialCatalog.search()` with hierarchy, source, reference, and local
14
+ availability filters.
15
+ - `MaterialPage.provenance()` for serializable material-source records.
16
+ - `MaterialCatalog.verify_integrity()` for SHA-256 verification of cached
17
+ material data.
18
+ - `compute_group_delay_wavelength_slope()` for the explicit wavelength-space
19
+ derivative, `dτ_g/dλ`.
20
+ - Numerical regression, unit-equivalence, catalog-search, and cache-integrity
21
+ test coverage.
22
+ - A new PyOptik prism logo and documentation favicon.
23
+
24
+ ### Changed
25
+
26
+ - `compute_group_delay_dispersion()` now returns conventional frequency-domain
27
+ GDD, `dτ_g/dω`, with time-squared units.
28
+ - Material plots use a consistent built-in Matplotlib layout and typography.
29
+ - Public catalog and group-delay APIs use expanded NumPy-style docstrings.
30
+
31
+ ### Fixed
32
+
33
+ - Formula type 6 now accumulates every gas-dispersion term instead of
34
+ overwriting earlier terms.
35
+
36
+ ### Removed
37
+
38
+ - The `MPSPlots` runtime dependency and its use in examples and material
39
+ plotting helpers.
40
+ - Retired logo assets.
41
+
42
+ [Unreleased]: https://github.com/MartinPdeS/PyOptik/compare/v3.0.0...HEAD
pyoptik-3.0.4/Makefile ADDED
@@ -0,0 +1,60 @@
1
+ PYTHON ?= python3.11
2
+ BUILD_DIR ?= build
3
+ DIST_DIR ?= dist
4
+ DOCS_DIR ?= docs
5
+ DOCS_BUILD_DIR ?= $(DOCS_DIR)/build
6
+
7
+ .PHONY: help quality test docs build install uninstall quick rebuild editable \
8
+ setup download-all clean
9
+
10
+ help:
11
+ @echo "PyOptik development targets:"
12
+ @echo " make quality Run static checks"
13
+ @echo " make test Run the offline test suite"
14
+ @echo " make docs Build the documentation with warnings as errors"
15
+ @echo " make build Build source and wheel distributions"
16
+ @echo " make install Install the package"
17
+ @echo " make editable Install the package in editable mode"
18
+ @echo " make setup Download the complete material snapshot"
19
+ @echo " make download-all Download the complete upstream catalog"
20
+ @echo " make quick Run quality checks, tests, and build"
21
+ @echo " make rebuild Clean, then run the quick workflow"
22
+ @echo " make clean Remove generated build and test artifacts"
23
+
24
+ quality:
25
+ $(PYTHON) -m flake8 PyOptik tests
26
+
27
+ test:
28
+ MPLBACKEND=Agg MPLCONFIGDIR=$${TMPDIR:-/tmp}/pyoptik-matplotlib \
29
+ $(PYTHON) -m pytest -m 'not network'
30
+
31
+ docs:
32
+ MPLBACKEND=Agg MPLCONFIGDIR=$${TMPDIR:-/tmp}/pyoptik-matplotlib \
33
+ $(PYTHON) -m sphinx -b html -W --keep-going \
34
+ $(DOCS_DIR)/source $(DOCS_BUILD_DIR)/html
35
+
36
+ build:
37
+ $(PYTHON) -m build --outdir $(DIST_DIR)
38
+
39
+ install:
40
+ $(PYTHON) -m pip install .
41
+
42
+ uninstall:
43
+ $(PYTHON) -m pip uninstall -y PyOptik
44
+
45
+ quick: quality test build
46
+
47
+ rebuild: clean quick
48
+
49
+ editable:
50
+ $(PYTHON) -m pip install --no-build-isolation -e .
51
+
52
+ setup:
53
+ $(PYTHON) -m PyOptik setup $(ARGS)
54
+
55
+ download-all:
56
+ $(PYTHON) -m PyOptik download-all $(ARGS)
57
+
58
+ clean:
59
+ rm -rf $(BUILD_DIR) $(DIST_DIR) $(DOCS_BUILD_DIR) \
60
+ .pytest_cache htmlcov .coverage
pyoptik-3.0.4/PKG-INFO ADDED
@@ -0,0 +1,429 @@
1
+ Metadata-Version: 2.4
2
+ Name: PyOptik
3
+ Version: 3.0.4
4
+ Summary: A package for refractive index values.
5
+ Author-email: Martin Poinsinet de Sivry-Houle <martin.poinsinet.de.sivry@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2020 Martin de Sivry
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Keywords: refractive index,optics
29
+ Classifier: Programming Language :: Python
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: Programming Language :: Python :: Implementation :: CPython
32
+ Classifier: Development Status :: 4 - Beta
33
+ Classifier: Topic :: Scientific/Engineering :: Physics
34
+ Classifier: Intended Audience :: Science/Research
35
+ Requires-Python: >=3.10
36
+ Description-Content-Type: text/x-rst
37
+ License-File: LICENSE
38
+ Requires-Dist: pint~=0.24
39
+ Requires-Dist: numpy
40
+ Requires-Dist: matplotlib~=3.8
41
+ Requires-Dist: requests~=2.31
42
+ Requires-Dist: pyyaml~=6.0
43
+ Requires-Dist: tabulate~=0.9
44
+ Requires-Dist: TypedUnit
45
+ Provides-Extra: testing
46
+ Requires-Dist: pytest<9.0,>=7.4; extra == "testing"
47
+ Requires-Dist: pytest-cov<6,>=2; extra == "testing"
48
+ Requires-Dist: pytest-json-report~=1.5; extra == "testing"
49
+ Requires-Dist: coverage~=7.6; extra == "testing"
50
+ Provides-Extra: documentation
51
+ Requires-Dist: numpydoc==1.6.0; extra == "documentation"
52
+ Requires-Dist: sphinx>=5.1.1; extra == "documentation"
53
+ Requires-Dist: sphinx-gallery==0.15.0; extra == "documentation"
54
+ Requires-Dist: sphinx-rtd-theme==2.0.0; extra == "documentation"
55
+ Requires-Dist: pydata-sphinx-theme==0.14.1; extra == "documentation"
56
+ Provides-Extra: dev
57
+ Requires-Dist: flake8==7.1.1; extra == "dev"
58
+ Dynamic: license-file
59
+
60
+ |logo|
61
+
62
+ .. list-table::
63
+ :widths: 35 65
64
+ :header-rows: 1
65
+
66
+ * - Badge
67
+ - Status
68
+ * - Python versions
69
+ - |python|
70
+ * - Documentation
71
+ - |docs|
72
+ * - Continuous integration
73
+ - |ci/cd|
74
+ * - Test coverage
75
+ - |coverage|
76
+ * - PyPI package
77
+ - |PyPi|
78
+ * - PyPI downloads
79
+ - |PyPi_download|
80
+ * - Anaconda package
81
+ - |anaconda|
82
+ * - Anaconda downloads
83
+ - |anaconda_download|
84
+
85
+ PyOptik
86
+ =======
87
+
88
+ **PyOptik** is a Python library for evaluating optical material properties.
89
+ It provides unit-aware refractive-index calculations, dispersion models,
90
+ tabulated optical constants, group-delay properties, plotting helpers, and a
91
+ catalog interface for the hierarchical `RefractiveIndex.INFO
92
+ <https://refractiveindex.info>`_ database.
93
+
94
+ The library is designed for optical design, photonics simulations,
95
+ electromagnetic modeling, and experimental data analysis.
96
+
97
+ Features
98
+ --------
99
+
100
+ * Sellmeier and other dispersion-formula models.
101
+ * Tabulated complex refractive index data, ``n + i k``.
102
+ * Unit-aware wavelength calculations through ``TypedUnit`` and Pint.
103
+ * Group index, group velocity, group delay, and group-delay dispersion.
104
+ * NumPy-compatible scalar and array evaluation.
105
+ * Plotting helpers for dispersion and absorption data.
106
+ * Hierarchical catalog access using upstream ``shelf / book / page`` identity.
107
+ * Explicit upstream page selection using ``shelf/book/page`` identifiers.
108
+ * Downloadable custom and upstream material data with local caching.
109
+
110
+ Installation
111
+ ------------
112
+
113
+ Install the latest release from PyPI:
114
+
115
+ .. code-block:: bash
116
+
117
+ python -m pip install PyOptik
118
+
119
+ The package is also available through Anaconda:
120
+
121
+ .. code-block:: bash
122
+
123
+ conda install -c martinpdes pyoptik
124
+
125
+ Verify the installation with the same interpreter that will run your code:
126
+
127
+ .. code-block:: bash
128
+
129
+ python -c "import PyOptik; print(PyOptik.__version__)"
130
+
131
+ Material data is not bundled with PyOptik. Install the package first, then
132
+ download the upstream snapshot when it is needed:
133
+
134
+ .. code-block:: bash
135
+
136
+ pyoptik setup
137
+
138
+ or from Python:
139
+
140
+ .. code-block:: python
141
+
142
+ from PyOptik import download_snapshot
143
+
144
+ catalog = download_snapshot()
145
+
146
+ First calculation
147
+ -----------------
148
+
149
+ Wavelengths should carry units. This avoids ambiguity between metres,
150
+ micrometres, and nanometres.
151
+
152
+ .. code-block:: python
153
+
154
+ from TypedUnit import ureg
155
+ from PyOptik import MaterialCatalog
156
+
157
+ catalog = MaterialCatalog.from_snapshot()
158
+ bk7 = catalog.get("specs/SCHOTT-optical/P-BK7").load()
159
+ index = bk7.compute_refractive_index(550 * ureg.nanometer)
160
+
161
+ print(index)
162
+
163
+ For backward compatibility, bare numeric wavelengths are interpreted as
164
+ metres. Unit-bearing quantities are recommended for new code.
165
+
166
+ Material models
167
+ ---------------
168
+
169
+ Sellmeier materials evaluate a dispersion formula:
170
+
171
+ .. code-block:: python
172
+
173
+ from TypedUnit import ureg
174
+ from PyOptik import MaterialCatalog
175
+
176
+ catalog = MaterialCatalog.from_snapshot()
177
+ silica = catalog.get("main/SiO2/Malitson").load()
178
+ wavelengths = [800, 1310, 1550] * ureg.nanometer
179
+ index = silica.compute_refractive_index(wavelengths)
180
+
181
+ Tabulated materials interpolate complex optical constants:
182
+
183
+ .. code-block:: python
184
+
185
+ from PyOptik import MaterialCatalog
186
+
187
+ catalog = MaterialCatalog.from_snapshot()
188
+ silicon = catalog.get("main/Si/Aspnes").load()
189
+ index = silicon.compute_refractive_index(1.55 * ureg.micrometer)
190
+
191
+ The real part is the refractive index ``n`` and the imaginary part is the
192
+ extinction coefficient ``k``.
193
+
194
+ Validity ranges
195
+ ~~~~~~~~~~~~~~~
196
+
197
+ Material data is only valid over the wavelength range supplied by its source.
198
+ Out-of-range behavior can be selected explicitly:
199
+
200
+ .. code-block:: python
201
+
202
+ wavelength = 300 * ureg.nanometer
203
+
204
+ # Default: issue a warning and evaluate.
205
+ index = bk7.compute_refractive_index(wavelength, out_of_range="warn")
206
+
207
+ # Fail fast for production calculations.
208
+ index = bk7.compute_refractive_index(wavelength, out_of_range="raise")
209
+
210
+ # Evaluate at the nearest validity boundary.
211
+ index = bk7.compute_refractive_index(wavelength, out_of_range="clip")
212
+
213
+ Group and pulse properties
214
+ --------------------------
215
+
216
+ Every material model provides group-related quantities:
217
+
218
+ .. code-block:: python
219
+
220
+ wavelength = 1550 * ureg.nanometer
221
+
222
+ group_index = silica.compute_group_index(wavelength)
223
+ group_velocity = silica.compute_group_velocity(wavelength)
224
+ group_delay = silica.compute_group_delay(
225
+ wavelength,
226
+ length=10 * ureg.centimeter,
227
+ )
228
+ group_delay_dispersion = silica.compute_group_delay_dispersion(wavelength)
229
+
230
+ # The wavelength-space slope is available separately.
231
+ group_delay_wavelength_slope = silica.compute_group_delay_wavelength_slope(wavelength)
232
+
233
+ These methods accept scalar or array wavelengths and return unit-aware values.
234
+ ``compute_group_delay_dispersion`` is the conventional frequency-domain GDD,
235
+ ``dτ_g/dω`` (typically expressed in fs²); use
236
+ ``compute_group_delay_wavelength_slope`` for ``dτ_g/dλ``.
237
+
238
+ Plotting
239
+ --------
240
+
241
+ Material models include simple dispersion plots:
242
+
243
+ .. code-block:: python
244
+
245
+ from PyOptik import MaterialCatalog
246
+
247
+ catalog = MaterialCatalog.from_snapshot()
248
+ catalog.get("specs/SCHOTT-optical/P-BK7").load().plot()
249
+ catalog.get("main/Au/Johnson").load().plot()
250
+
251
+ For non-interactive environments such as CI or servers, select a headless
252
+ Matplotlib backend before importing plotting code:
253
+
254
+ .. code-block:: python
255
+
256
+ import matplotlib
257
+ matplotlib.use("Agg")
258
+
259
+ Hierarchical material catalog
260
+ -----------------------------
261
+
262
+ RefractiveIndex.INFO organizes data by **shelf**, **book**, and **page**.
263
+ PyOptik preserves this identity so that materials from different sources do
264
+ not collide simply because they share a short name.
265
+
266
+ Load the upstream catalog index:
267
+
268
+ .. code-block:: python
269
+
270
+ from PyOptik import MaterialCatalog
271
+
272
+ catalog = MaterialCatalog.from_upstream()
273
+
274
+ print(catalog.shelves())
275
+ print(catalog.books(shelf="specs"))
276
+
277
+ Download a complete source collection, such as an optical-glass book:
278
+
279
+ .. code-block:: python
280
+
281
+ catalog.download(
282
+ shelf="specs",
283
+ book="SCHOTT-optical",
284
+ )
285
+
286
+ Download the complete optical catalog, including tabulated and formula-based
287
+ materials, with resumable progress tracking:
288
+
289
+ .. code-block:: python
290
+
291
+ catalog.download_all()
292
+
293
+ Each page is stored once and recorded in ``manifest.json`` with its source URL,
294
+ local path, status, timestamp, and SHA-256 checksum. Re-running the command
295
+ uses cached files, so interrupted downloads can resume safely.
296
+
297
+ Access a page by its canonical identifier and load its material model:
298
+
299
+ .. code-block:: python
300
+
301
+ page = catalog.get("specs/SCHOTT-optical/N-BK7")
302
+ bk7 = page.load()
303
+
304
+ # Search by ID, descriptive name, or source URL; retain only cached pages.
305
+ for page in catalog.search("BK7", shelf="specs", available=True):
306
+ print(page.provenance())
307
+
308
+ Material data is cached in a user data directory. Set
309
+ ``PYOPTIK_DATA_DIR`` to choose a different location.
310
+
311
+ The command-line interface provides the canonical catalog workflow:
312
+
313
+ .. code-block:: bash
314
+
315
+ pyoptik setup
316
+ python -m PyOptik download-all --data-root ./refractiveindex-data
317
+ python -m PyOptik download-all --source pages --workers 8
318
+
319
+ After installation, the equivalent console command is ``pyoptik
320
+ download-all --data-root ./refractiveindex-data``.
321
+
322
+ For a beginner-friendly first-time setup, use:
323
+
324
+ .. code-block:: bash
325
+
326
+ pyoptik setup
327
+
328
+ This downloads the complete upstream snapshot, preserves the original
329
+ hierarchy, and can be safely run again. Use ``pyoptik setup --force`` to
330
+ refresh the local snapshot.
331
+
332
+ The same setup is available from Python:
333
+
334
+ .. code-block:: python
335
+
336
+ from PyOptik import download_snapshot
337
+
338
+ catalog = download_snapshot()
339
+ silver = catalog.get("main/Ag/Johnson").load()
340
+
341
+ The default ``download-all`` command downloads one upstream snapshot and
342
+ extracts every material page locally, preserving its ``shelf/book/page``
343
+ hierarchy. This avoids thousands of individual HTTP requests. Existing
344
+ snapshots are reused; pass ``--force`` to refresh the snapshot. The
345
+ ``--source pages`` fallback downloads individual pages and supports bounded
346
+ parallelism with ``--workers``. ``--fail-fast`` stops after the first failed
347
+ page, while ``--verbose`` enables detailed diagnostics.
348
+
349
+ Common issues
350
+ -------------
351
+
352
+ * Attach units to wavelengths whenever possible.
353
+ * Use ``out_of_range="raise"`` when extrapolation would invalidate a result.
354
+ * Use the canonical catalog identifier when provenance or source selection
355
+ matters.
356
+ * Use ``MPLBACKEND=Agg`` for documentation builds, CI, and remote servers.
357
+ * If a material cannot be found, run ``pyoptik setup`` or call
358
+ ``download_snapshot()`` before loading its canonical page.
359
+
360
+ Development and testing
361
+ -----------------------
362
+
363
+ Clone the repository and install development dependencies:
364
+
365
+ .. code-block:: bash
366
+
367
+ git clone https://github.com/MartinPdeS/PyOptik.git
368
+ cd PyOptik
369
+ python -m pip install -e ".[testing,documentation,dev]"
370
+
371
+ Run the offline test suite:
372
+
373
+ .. code-block:: bash
374
+
375
+ MPLBACKEND=Agg pytest -m "not network"
376
+
377
+ Build the documentation:
378
+
379
+ .. code-block:: bash
380
+
381
+ MPLBACKEND=Agg sphinx-build -b html -W docs/source docs/build/html
382
+
383
+ Network-dependent tests are marked with ``network`` and are excluded from
384
+ normal CI runs.
385
+
386
+ Documentation and references
387
+ ----------------------------
388
+
389
+ * `Online documentation <https://martinpdes.github.io/PyOptik/>`_
390
+ * `RefractiveIndex.INFO database <https://github.com/polyanskiy/refractiveindex.info-database>`_
391
+ * `PyOptik source repository <https://github.com/MartinPdeS/PyOptik>`_
392
+
393
+ The material data is sourced from RefractiveIndex.INFO. Refer to each
394
+ material page for its original scientific or manufacturer reference.
395
+
396
+ .. |python| image:: https://img.shields.io/pypi/pyversions/pyoptik.svg
397
+ :alt: Supported Python versions
398
+ :target: https://pypi.org/project/pyoptik/
399
+
400
+ .. |logo| image:: https://github.com/MartinPdeS/PyOptik/raw/master/docs/images/logo.svg
401
+ :alt: PyOptik logo
402
+
403
+ .. |docs| image:: https://github.com/martinpdes/pyoptik/actions/workflows/deploy_documentation.yml/badge.svg
404
+ :target: https://martinpdes.github.io/PyOptik/
405
+ :alt: Documentation status
406
+
407
+ .. |ci/cd| image:: https://github.com/martinpdes/pyoptik/actions/workflows/tests.yml/badge.svg
408
+ :target: https://github.com/MartinPdeS/PyOptik/actions/workflows/tests.yml
409
+ :alt: Continuous integration status
410
+
411
+ .. |coverage| image:: https://raw.githubusercontent.com/MartinPdeS/PyOptik/python-coverage-comment-action-data/badge.svg
412
+ :alt: Test coverage
413
+ :target: https://htmlpreview.github.io/?https://github.com/MartinPdeS/PyOptik/blob/python-coverage-comment-action-data/htmlcov/index.html
414
+
415
+ .. |PyPi| image:: https://badge.fury.io/py/pyoptik.svg
416
+ :alt: PyPI version
417
+ :target: https://pypi.org/project/pyoptik/
418
+
419
+ .. |PyPi_download| image:: https://img.shields.io/pypi/dm/pyoptik.svg
420
+ :alt: PyPI downloads
421
+ :target: https://pypistats.org/packages/pyoptik
422
+
423
+ .. |anaconda| image:: https://anaconda.org/martinpdes/pyoptik/badges/version.svg
424
+ :alt: Anaconda version
425
+ :target: https://anaconda.org/martinpdes/pyoptik
426
+
427
+ .. |anaconda_download| image:: https://anaconda.org/martinpdes/pyoptik/badges/downloads.svg
428
+ :alt: Anaconda downloads
429
+ :target: https://anaconda.org/martinpdes/pyoptik
@@ -4,14 +4,17 @@ try:
4
4
  except ImportError:
5
5
  __version__ = "0.0.0"
6
6
 
7
+ import logging
8
+
9
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
10
+
7
11
 
8
- from .material_bank import MaterialBank
9
12
  from .material_type import MaterialType
13
+ from .catalog import MaterialCatalog, MaterialId, MaterialPage, download_snapshot
10
14
 
11
15
  from .material import TabulatedMaterial
12
16
  from .material import SellmeierMaterial
13
17
  from .material import base_class
14
18
 
15
- Material = MaterialBank # For retro-compatibility
16
19
 
17
20
  TIMEOUT = 10 # Default timeout for requests in seconds