PyOptik 3.0.5__tar.gz → 3.2.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.
- {pyoptik-3.0.5 → pyoptik-3.2.0}/.github/workflows/deploy_PyPi.yml +3 -7
- {pyoptik-3.0.5 → pyoptik-3.2.0}/.github/workflows/deploy_anaconda.yml +6 -6
- {pyoptik-3.0.5 → pyoptik-3.2.0}/.github/workflows/deploy_coverage.yml +2 -1
- {pyoptik-3.0.5 → pyoptik-3.2.0}/.github/workflows/deploy_documentation.yml +2 -2
- pyoptik-3.2.0/.github/workflows/quality.yml +18 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/.github/workflows/tests.yml +2 -2
- {pyoptik-3.0.5 → pyoptik-3.2.0}/.gitignore +5 -0
- pyoptik-3.2.0/CHANGELOG.md +84 -0
- pyoptik-3.2.0/CONTRIBUTING.md +10 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/Makefile +14 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PKG-INFO +126 -1
- pyoptik-3.2.0/PyOptik/__init__.py +32 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik/__main__.py +11 -1
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik/_version.py +3 -3
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik/catalog.py +4 -5
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik/directories.py +1 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik/material/__init__.py +1 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik/material/base_class.py +7 -1
- pyoptik-3.2.0/PyOptik/material/dataset.py +204 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik/material/sellmeier_class.py +64 -33
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik/material/tabulated_class.py +93 -39
- pyoptik-3.2.0/PyOptik/thin_film.py +279 -0
- pyoptik-3.2.0/PyOptik/tui.py +105 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik/utils.py +1 -1
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik.egg-info/PKG-INFO +126 -1
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik.egg-info/SOURCES.txt +26 -2
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik.egg-info/requires.txt +3 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik.egg-info/scm_file_list.json +26 -2
- pyoptik-3.2.0/PyOptik.egg-info/scm_version.json +8 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/README.rst +123 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0/conda.recipe}/meta.yaml +1 -1
- pyoptik-3.2.0/docs/examples/catalog/README.rst +6 -0
- pyoptik-3.2.0/docs/examples/catalog/plot_catalog_search.py +48 -0
- pyoptik-3.2.0/docs/examples/custom_materials/README.rst +6 -0
- pyoptik-3.2.0/docs/examples/custom_materials/plot_measured_material.py +54 -0
- pyoptik-3.2.0/docs/examples/interfaces/README.rst +6 -0
- pyoptik-3.2.0/docs/examples/interfaces/plot_fresnel_angles.py +42 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/sellmeier/plot_water.py +0 -1
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/tabulated/plot_silver.py +0 -1
- pyoptik-3.2.0/docs/examples/thin_films/README.rst +6 -0
- pyoptik-3.2.0/docs/examples/thin_films/plot_antireflection_coating.py +46 -0
- pyoptik-3.2.0/docs/examples/thin_films/plot_bragg_mirror.py +50 -0
- pyoptik-3.2.0/docs/source/catalog_browser.rst +41 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/source/code.rst +58 -23
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/source/conf.py +7 -1
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/source/conventions.rst +17 -2
- pyoptik-3.2.0/docs/source/custom_materials.rst +101 -0
- pyoptik-3.2.0/docs/source/examples.rst +19 -0
- pyoptik-3.2.0/docs/source/getting_started.rst +66 -0
- pyoptik-3.2.0/docs/source/index.rst +70 -0
- pyoptik-3.2.0/docs/source/materials_and_catalog.rst +64 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/source/sg_execution_times.rst +27 -12
- pyoptik-3.2.0/docs/source/thin_films.rst +108 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/pyproject.toml +4 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/tests/conftest.py +2 -2
- {pyoptik-3.0.5 → pyoptik-3.2.0}/tests/test_base_material_decorator.py +1 -0
- pyoptik-3.2.0/tests/test_datasets_and_custom_materials.py +106 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/tests/test_main_cli.py +13 -0
- pyoptik-3.2.0/tests/test_thin_film.py +124 -0
- pyoptik-3.2.0/tests/test_tui.py +11 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/tests/test_utils_extra.py +2 -1
- pyoptik-3.2.0/tools/next_release_version.py +13 -0
- pyoptik-3.2.0/tools/release_tag.py +15 -0
- pyoptik-3.0.5/CHANGELOG.md +0 -47
- pyoptik-3.0.5/PyOptik/__init__.py +0 -20
- pyoptik-3.0.5/PyOptik.egg-info/scm_version.json +0 -8
- pyoptik-3.0.5/docs/source/examples.rst +0 -14
- pyoptik-3.0.5/docs/source/index.rst +0 -13
- {pyoptik-3.0.5 → pyoptik-3.2.0}/.coveragerc +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/.flake8 +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/.github/dependabot.yml +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/.pre-commit-config.yaml +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/LICENSE +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik/material_type.py +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik.egg-info/dependency_links.txt +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik.egg-info/entry_points.txt +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/PyOptik.egg-info/top_level.txt +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/Makefile +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/README.rst +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/group_properties/README.rst +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/group_properties/plot_group_properties.py +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/sellmeier/README.rst +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/sellmeier/plot_bk7.py +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/sellmeier/plot_compare_glasses.py +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/sellmeier/plot_silica.py +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/tabulated/README.rst +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/tabulated/plot_polyethylene.py +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/examples/tabulated/plot_silicon_nk.py +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/images/example_bk7.png +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/images/logo.svg +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/make.bat +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/source/_static/default.css +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/source/_static/favicon.png +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/source/_static/logo.svg +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/source/_static/thumbnail.png +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/docs/source/references.rst +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/pytest.ini +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/setup.cfg +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/tests/__init__.py +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/tests/test_catalog.py +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/tests/test_docstrings.py +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/tests/test_material_models.py +0 -0
- {pyoptik-3.0.5 → pyoptik-3.2.0}/tests/test_validation_and_logging.py +0 -0
|
@@ -2,18 +2,14 @@ name: Deploy to PyPi
|
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
|
-
|
|
6
|
-
tags:
|
|
7
|
-
- '*'
|
|
8
|
-
pull_request:
|
|
9
|
-
branches: [ "master" ]
|
|
5
|
+
tags: [ "v*" ]
|
|
10
6
|
|
|
11
7
|
permissions:
|
|
12
|
-
|
|
8
|
+
contents: read
|
|
13
9
|
|
|
14
10
|
jobs:
|
|
15
11
|
pure_package:
|
|
16
|
-
uses: MartinPdeS/MPSActions/.github/workflows/publish_pure_package_to_PyPi.yml@
|
|
12
|
+
uses: MartinPdeS/MPSActions/.github/workflows/publish_pure_package_to_PyPi.yml@v5
|
|
17
13
|
with:
|
|
18
14
|
python-version: "3.11"
|
|
19
15
|
secrets:
|
|
@@ -2,20 +2,20 @@ name: Deploy Conda Packages
|
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
|
-
|
|
6
|
-
tags: '*'
|
|
7
|
-
pull_request:
|
|
8
|
-
branches: [ "master" ]
|
|
5
|
+
tags: [ "v*" ]
|
|
9
6
|
|
|
10
7
|
permissions:
|
|
11
|
-
|
|
8
|
+
contents: read
|
|
12
9
|
|
|
13
10
|
jobs:
|
|
14
11
|
linux:
|
|
15
|
-
uses: MartinPdeS/MPSActions/.github/workflows/publish_compiled_package_to_anaconda.yml@
|
|
12
|
+
uses: MartinPdeS/MPSActions/.github/workflows/publish_compiled_package_to_anaconda.yml@v5
|
|
16
13
|
with:
|
|
17
14
|
python_versions: '["3.13"]'
|
|
18
15
|
apt_package: ""
|
|
19
16
|
os_list: '["ubuntu-latest"]'
|
|
17
|
+
package_name: pyoptik
|
|
18
|
+
recipe_path: conda.recipe
|
|
19
|
+
test_import: PyOptik
|
|
20
20
|
secrets:
|
|
21
21
|
ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_API_TOKEN }}
|
|
@@ -17,9 +17,10 @@ permissions:
|
|
|
17
17
|
|
|
18
18
|
jobs:
|
|
19
19
|
ManyLinux_x86_64:
|
|
20
|
-
uses: MartinPdeS/MPSActions/.github/workflows/publish_coverage.yml@
|
|
20
|
+
uses: MartinPdeS/MPSActions/.github/workflows/publish_coverage.yml@v5
|
|
21
21
|
with:
|
|
22
22
|
python-version: "3.11"
|
|
23
23
|
apt-package: xvfb
|
|
24
|
+
coverage-package: PyOptik
|
|
24
25
|
secrets:
|
|
25
26
|
_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -16,8 +16,8 @@ permissions:
|
|
|
16
16
|
|
|
17
17
|
jobs:
|
|
18
18
|
ManyLinux_x86_64:
|
|
19
|
-
uses: MartinPdeS/MPSActions/.github/workflows/publish_documentation.yml@
|
|
19
|
+
uses: MartinPdeS/MPSActions/.github/workflows/publish_documentation.yml@v5
|
|
20
20
|
with:
|
|
21
21
|
python-version: "3.11"
|
|
22
22
|
package-name: "PyOptik"
|
|
23
|
-
apt-package: xvfb jq
|
|
23
|
+
apt-package: xvfb jq
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: Static quality checks
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: ["master"]
|
|
5
|
+
pull_request:
|
|
6
|
+
branches: ["master"]
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
jobs:
|
|
10
|
+
flake8:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
|
|
14
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.11"
|
|
17
|
+
- run: python -m pip install "flake8==7.1.1"
|
|
18
|
+
- run: python -m flake8 PyOptik tests
|
|
@@ -15,8 +15,8 @@ jobs:
|
|
|
15
15
|
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
16
16
|
|
|
17
17
|
steps:
|
|
18
|
-
- uses: actions/checkout@
|
|
19
|
-
- uses: actions/setup-python@
|
|
18
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
|
|
19
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
|
|
20
20
|
with:
|
|
21
21
|
python-version: ${{ matrix.python-version }}
|
|
22
22
|
cache: pip
|
|
@@ -4,10 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
# Except ...
|
|
6
6
|
!.github
|
|
7
|
+
!conda.recipe
|
|
8
|
+
!conda.recipe/meta.yaml
|
|
7
9
|
!PyOptik
|
|
8
10
|
!development
|
|
9
11
|
!docs
|
|
10
12
|
!tests
|
|
13
|
+
!tools
|
|
14
|
+
!tools/*.py
|
|
11
15
|
!.flake8
|
|
12
16
|
!.gitignore
|
|
13
17
|
!.pre-commit-config.yaml
|
|
@@ -21,6 +25,7 @@
|
|
|
21
25
|
!pytest.ini
|
|
22
26
|
!.coveragerc
|
|
23
27
|
!CHANGELOG.md
|
|
28
|
+
!CONTRIBUTING.md
|
|
24
29
|
|
|
25
30
|
# But ignore docs/build inside docs and code
|
|
26
31
|
docs/build/
|
|
@@ -0,0 +1,84 @@
|
|
|
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
|
+
## [3.2.0] - 2026-09-16
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Task-oriented getting-started and material-catalog guides.
|
|
15
|
+
- Executable gallery examples for measured-material import and YAML round
|
|
16
|
+
trips, Fresnel polarization and Brewster angle, quarter-wave antireflection
|
|
17
|
+
coatings, dielectric Bragg mirrors, and catalog provenance workflows.
|
|
18
|
+
- Direct README links to the principal guides, examples, and API reference.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Documentation navigation now groups content into Start here, User guide,
|
|
23
|
+
Learn by example, and Reference sections.
|
|
24
|
+
- The documentation landing page, page titles, API hierarchy, and gallery
|
|
25
|
+
descriptions now use clearer task-oriented language.
|
|
26
|
+
|
|
27
|
+
## [3.1.0] - 2026-09-16
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- Support for all nine RefractiveIndex.INFO dispersion formula types.
|
|
32
|
+
- `MaterialCatalog.search()` with hierarchy, source, reference, and local
|
|
33
|
+
availability filters.
|
|
34
|
+
- `MaterialPage.provenance()` for serializable material-source records.
|
|
35
|
+
- `MaterialCatalog.verify_integrity()` for SHA-256 verification of cached
|
|
36
|
+
material data.
|
|
37
|
+
- `compute_group_delay_wavelength_slope()` for the explicit wavelength-space
|
|
38
|
+
derivative, `dτ_g/dλ`.
|
|
39
|
+
- Convenience APIs for real index, extinction coefficient, relative
|
|
40
|
+
permittivity, and absorption coefficient.
|
|
41
|
+
- Split tabulated ``n`` and ``k`` YAML support and opt-in monotonic PCHIP
|
|
42
|
+
interpolation.
|
|
43
|
+
- A physical conventions and provenance documentation guide.
|
|
44
|
+
- Numerical regression, unit-equivalence, catalog-search, and cache-integrity
|
|
45
|
+
test coverage.
|
|
46
|
+
- A new PyOptik prism logo and documentation favicon.
|
|
47
|
+
- Typed, validated material documents for formula and tabulated optical data.
|
|
48
|
+
- User-defined material construction from arrays, CSV files, and formula
|
|
49
|
+
coefficients, with atomic RefractiveIndex.INFO-compatible YAML export.
|
|
50
|
+
- An optional Textual terminal browser for searching the local material
|
|
51
|
+
catalog and inspecting provenance.
|
|
52
|
+
- Fresnel reflection and transmission calculations for s and p polarization,
|
|
53
|
+
including Brewster and critical-angle helpers.
|
|
54
|
+
- Coherent transfer-matrix calculations for isotropic multilayer thin films,
|
|
55
|
+
supporting constant complex indices and wavelength-dependent PyOptik
|
|
56
|
+
material models.
|
|
57
|
+
- Numerical reference tests for interfaces, total internal reflection,
|
|
58
|
+
antireflection coatings, absorbing films, custom material round trips, and
|
|
59
|
+
malformed input paths.
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- `compute_group_delay_dispersion()` now returns conventional frequency-domain
|
|
64
|
+
GDD, `dτ_g/dω`, with time-squared units.
|
|
65
|
+
- Material plots use a consistent built-in Matplotlib layout and typography.
|
|
66
|
+
- Public catalog and group-delay APIs use expanded NumPy-style docstrings.
|
|
67
|
+
- Material YAML loading and export share one typed parser and validation layer.
|
|
68
|
+
- Wavelength validity endpoints tolerate floating-point round-off introduced
|
|
69
|
+
by unit conversions.
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
|
|
73
|
+
- Formula type 6 now accumulates every gas-dispersion term instead of
|
|
74
|
+
overwriting earlier terms.
|
|
75
|
+
|
|
76
|
+
### Removed
|
|
77
|
+
|
|
78
|
+
- The `MPSPlots` runtime dependency and its use in examples and material
|
|
79
|
+
plotting helpers.
|
|
80
|
+
- Retired logo assets.
|
|
81
|
+
|
|
82
|
+
[Unreleased]: https://github.com/MartinPdeS/PyOptik/compare/v3.2.0...HEAD
|
|
83
|
+
[3.2.0]: https://github.com/MartinPdeS/PyOptik/compare/v3.1.0...v3.2.0
|
|
84
|
+
[3.1.0]: https://github.com/MartinPdeS/PyOptik/compare/v3.0.5...v3.1.0
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Contributing to PyOptik
|
|
2
|
+
|
|
3
|
+
Contributions should preserve PyOptik's offline material-catalogue workflow.
|
|
4
|
+
Add tests for behaviour changes, document data provenance and physical units,
|
|
5
|
+
and avoid committing generated assets, caches, or `PyOptik/_version.py`.
|
|
6
|
+
|
|
7
|
+
Use `make quality`, `make test`, and `make docs` as appropriate before a pull
|
|
8
|
+
request. Semantic release commands (`make release patch`, `minor`, or `major`)
|
|
9
|
+
create and push the release commit and exact tag; `make tag VERSION=vX.Y.Z`
|
|
10
|
+
creates a local-only tag.
|
|
@@ -3,10 +3,13 @@ BUILD_DIR ?= build
|
|
|
3
3
|
DIST_DIR ?= dist
|
|
4
4
|
DOCS_DIR ?= docs
|
|
5
5
|
DOCS_BUILD_DIR ?= $(DOCS_DIR)/build
|
|
6
|
+
RELEASE_KIND := $(filter major minor patch,$(MAKECMDGOALS))
|
|
6
7
|
|
|
7
8
|
.PHONY: help quality test docs build install uninstall quick rebuild editable \
|
|
8
9
|
setup download-all clean
|
|
9
10
|
|
|
11
|
+
.PHONY: release tag major minor patch
|
|
12
|
+
|
|
10
13
|
help:
|
|
11
14
|
@echo "PyOptik development targets:"
|
|
12
15
|
@echo " make quality Run static checks"
|
|
@@ -20,6 +23,7 @@ help:
|
|
|
20
23
|
@echo " make quick Run quality checks, tests, and build"
|
|
21
24
|
@echo " make rebuild Clean, then run the quick workflow"
|
|
22
25
|
@echo " make clean Remove generated build and test artifacts"
|
|
26
|
+
@echo " make release patch Create and push the next patch release"
|
|
23
27
|
|
|
24
28
|
quality:
|
|
25
29
|
$(PYTHON) -m flake8 PyOptik tests
|
|
@@ -55,6 +59,16 @@ setup:
|
|
|
55
59
|
download-all:
|
|
56
60
|
$(PYTHON) -m PyOptik download-all $(ARGS)
|
|
57
61
|
|
|
62
|
+
tag:
|
|
63
|
+
$(PYTHON) tools/release_tag.py "$(VERSION)"
|
|
64
|
+
|
|
65
|
+
release:
|
|
66
|
+
@test "$(words $(RELEASE_KIND))" -eq 1 || { echo "usage: make release [patch|minor|major]" >&2; exit 2; }
|
|
67
|
+
@set -eu; tag="$$($(PYTHON) tools/next_release_version.py $(RELEASE_KIND))"; $(PYTHON) tools/release_tag.py "$$tag"; git push origin HEAD "refs/tags/$$tag"
|
|
68
|
+
|
|
69
|
+
major minor patch:
|
|
70
|
+
@:
|
|
71
|
+
|
|
58
72
|
clean:
|
|
59
73
|
rm -rf $(BUILD_DIR) $(DIST_DIR) $(DOCS_BUILD_DIR) \
|
|
60
74
|
.pytest_cache htmlcov .coverage
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyOptik
|
|
3
|
-
Version: 3.0
|
|
3
|
+
Version: 3.2.0
|
|
4
4
|
Summary: A package for refractive index values.
|
|
5
5
|
Author-email: Martin Poinsinet de Sivry-Houle <martin.poinsinet.de.sivry@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -55,6 +55,8 @@ Requires-Dist: sphinx-rtd-theme==2.0.0; extra == "documentation"
|
|
|
55
55
|
Requires-Dist: pydata-sphinx-theme==0.14.1; extra == "documentation"
|
|
56
56
|
Provides-Extra: dev
|
|
57
57
|
Requires-Dist: flake8==7.1.1; extra == "dev"
|
|
58
|
+
Provides-Extra: ui
|
|
59
|
+
Requires-Dist: textual>=1.0; extra == "ui"
|
|
58
60
|
Dynamic: license-file
|
|
59
61
|
|
|
60
62
|
|logo|
|
|
@@ -94,6 +96,24 @@ catalog interface for the hierarchical `RefractiveIndex.INFO
|
|
|
94
96
|
The library is designed for optical design, photonics simulations,
|
|
95
97
|
electromagnetic modeling, and experimental data analysis.
|
|
96
98
|
|
|
99
|
+
Documentation
|
|
100
|
+
-------------
|
|
101
|
+
|
|
102
|
+
The full documentation is organized by task:
|
|
103
|
+
|
|
104
|
+
* `Getting started <https://martinpdes.github.io/PyOptik/getting_started.html>`_
|
|
105
|
+
for installation and a first unit-aware calculation.
|
|
106
|
+
* `Materials and catalog <https://martinpdes.github.io/PyOptik/materials_and_catalog.html>`_
|
|
107
|
+
for model selection, search, provenance, and cache integrity.
|
|
108
|
+
* `Custom materials <https://martinpdes.github.io/PyOptik/custom_materials.html>`_
|
|
109
|
+
for arrays, CSV import, coefficients, validation, and YAML export.
|
|
110
|
+
* `Interfaces and thin films <https://martinpdes.github.io/PyOptik/thin_films.html>`_
|
|
111
|
+
for Fresnel coefficients and coherent multilayer design.
|
|
112
|
+
* `Example gallery <https://martinpdes.github.io/PyOptik/examples.html>`_
|
|
113
|
+
for complete, executable workflows.
|
|
114
|
+
* `API reference <https://martinpdes.github.io/PyOptik/code.html>`_ for public
|
|
115
|
+
classes and functions.
|
|
116
|
+
|
|
97
117
|
Features
|
|
98
118
|
--------
|
|
99
119
|
|
|
@@ -101,6 +121,7 @@ Features
|
|
|
101
121
|
* Tabulated complex refractive index data, ``n + i k``.
|
|
102
122
|
* Unit-aware wavelength calculations through ``TypedUnit`` and Pint.
|
|
103
123
|
* Group index, group velocity, group delay, and group-delay dispersion.
|
|
124
|
+
* Fresnel interfaces and coherent multilayer thin-film calculations.
|
|
104
125
|
* NumPy-compatible scalar and array evaluation.
|
|
105
126
|
* Plotting helpers for dispersion and absorption data.
|
|
106
127
|
* Hierarchical catalog access using upstream ``shelf / book / page`` identity.
|
|
@@ -197,6 +218,35 @@ Use ``material.n(wavelength)``, ``material.k(wavelength)``,
|
|
|
197
218
|
See the documentation's physical-conventions page for the vacuum-wavelength,
|
|
198
219
|
``n + i k``, GDD, interpolation, and extrapolation conventions.
|
|
199
220
|
|
|
221
|
+
User-defined materials
|
|
222
|
+
~~~~~~~~~~~~~~~~~~~~~~
|
|
223
|
+
|
|
224
|
+
Create tabulated materials directly from measured arrays or a CSV file, then
|
|
225
|
+
export them in the same validated YAML format used by the catalog:
|
|
226
|
+
|
|
227
|
+
.. code-block:: python
|
|
228
|
+
|
|
229
|
+
from TypedUnit import ureg
|
|
230
|
+
from PyOptik import TabulatedMaterial
|
|
231
|
+
|
|
232
|
+
sample = TabulatedMaterial.from_arrays(
|
|
233
|
+
"sample",
|
|
234
|
+
[400, 500, 600] * ureg.nanometer,
|
|
235
|
+
n=[1.40, 1.45, 1.50],
|
|
236
|
+
k=[0.01, 0.02, 0.04],
|
|
237
|
+
reference="Laboratory measurement",
|
|
238
|
+
)
|
|
239
|
+
sample.to_yaml("sample.yml")
|
|
240
|
+
|
|
241
|
+
# CSV headers default to: wavelength,n,k
|
|
242
|
+
imported = TabulatedMaterial.from_csv(
|
|
243
|
+
"sample.csv",
|
|
244
|
+
wavelength_unit=ureg.nanometer,
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
Formula materials can be authored in the same way with
|
|
248
|
+
``SellmeierMaterial.from_coefficients(...)`` and exported with ``to_yaml()``.
|
|
249
|
+
|
|
200
250
|
Validity ranges
|
|
201
251
|
~~~~~~~~~~~~~~~
|
|
202
252
|
|
|
@@ -241,6 +291,55 @@ These methods accept scalar or array wavelengths and return unit-aware values.
|
|
|
241
291
|
``dτ_g/dω`` (typically expressed in fs²); use
|
|
242
292
|
``compute_group_delay_wavelength_slope`` for ``dτ_g/dλ``.
|
|
243
293
|
|
|
294
|
+
Interfaces and thin films
|
|
295
|
+
-------------------------
|
|
296
|
+
|
|
297
|
+
Calculate s- or p-polarized Fresnel coefficients at a single interface:
|
|
298
|
+
|
|
299
|
+
.. code-block:: python
|
|
300
|
+
|
|
301
|
+
from TypedUnit import ureg
|
|
302
|
+
from PyOptik import fresnel_coefficients, brewster_angle, critical_angle
|
|
303
|
+
|
|
304
|
+
interface = fresnel_coefficients(
|
|
305
|
+
1.0,
|
|
306
|
+
1.5,
|
|
307
|
+
angle=45 * ureg.degree,
|
|
308
|
+
polarization="p",
|
|
309
|
+
)
|
|
310
|
+
print(interface.reflectance, interface.transmittance)
|
|
311
|
+
|
|
312
|
+
print(brewster_angle(1.0, 1.5).to(ureg.degree))
|
|
313
|
+
print(critical_angle(1.5, 1.0).to(ureg.degree))
|
|
314
|
+
|
|
315
|
+
For coherent multilayers, supply constant indices or PyOptik material models.
|
|
316
|
+
Each thickness should carry units:
|
|
317
|
+
|
|
318
|
+
.. code-block:: python
|
|
319
|
+
|
|
320
|
+
import numpy
|
|
321
|
+
from PyOptik import ThinFilmLayer, thin_film_stack
|
|
322
|
+
|
|
323
|
+
wavelength = 600 * ureg.nanometer
|
|
324
|
+
substrate_index = 1.5
|
|
325
|
+
coating_index = numpy.sqrt(substrate_index)
|
|
326
|
+
coating = ThinFilmLayer(
|
|
327
|
+
coating_index,
|
|
328
|
+
wavelength / (4 * coating_index),
|
|
329
|
+
)
|
|
330
|
+
spectrum = thin_film_stack(
|
|
331
|
+
[500, 550, 600, 650, 700] * ureg.nanometer,
|
|
332
|
+
[coating],
|
|
333
|
+
incident_index=1.0,
|
|
334
|
+
substrate_index=substrate_index,
|
|
335
|
+
polarization="s",
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
The returned results contain complex amplitude coefficients and the power
|
|
339
|
+
fractions ``reflectance``, ``transmittance``, and ``absorptance``. The model is
|
|
340
|
+
coherent and isotropic; it does not model roughness, anisotropy, or incoherent
|
|
341
|
+
thick substrates.
|
|
342
|
+
|
|
244
343
|
Plotting
|
|
245
344
|
--------
|
|
246
345
|
|
|
@@ -262,6 +361,20 @@ Matplotlib backend before importing plotting code:
|
|
|
262
361
|
import matplotlib
|
|
263
362
|
matplotlib.use("Agg")
|
|
264
363
|
|
|
364
|
+
Worked examples
|
|
365
|
+
---------------
|
|
366
|
+
|
|
367
|
+
The documentation gallery includes downloadable Python scripts and notebooks
|
|
368
|
+
for:
|
|
369
|
+
|
|
370
|
+
* Sellmeier and tabulated material dispersion;
|
|
371
|
+
* group index and group velocity;
|
|
372
|
+
* importing, interpolating, exporting, and reloading measured optical data;
|
|
373
|
+
* s- and p-polarized Fresnel reflectance and Brewster angle;
|
|
374
|
+
* quarter-wave antireflection coatings;
|
|
375
|
+
* multilayer dielectric Bragg mirrors; and
|
|
376
|
+
* catalog search, canonical source selection, and provenance capture.
|
|
377
|
+
|
|
265
378
|
Hierarchical material catalog
|
|
266
379
|
-----------------------------
|
|
267
380
|
|
|
@@ -325,6 +438,18 @@ The command-line interface provides the canonical catalog workflow:
|
|
|
325
438
|
After installation, the equivalent console command is ``pyoptik
|
|
326
439
|
download-all --data-root ./refractiveindex-data``.
|
|
327
440
|
|
|
441
|
+
An optional terminal interface provides live search and a provenance pane for
|
|
442
|
+
browsing the downloaded database:
|
|
443
|
+
|
|
444
|
+
.. code-block:: bash
|
|
445
|
+
|
|
446
|
+
python -m pip install "PyOptik[ui]"
|
|
447
|
+
pyoptik setup
|
|
448
|
+
pyoptik browse
|
|
449
|
+
|
|
450
|
+
Use the arrow keys or mouse to select a page, ``/`` to focus search, and ``q``
|
|
451
|
+
to quit. Pass ``--data-root`` when browsing a non-default snapshot location.
|
|
452
|
+
|
|
328
453
|
For a beginner-friendly first-time setup, use:
|
|
329
454
|
|
|
330
455
|
.. code-block:: bash
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
try:
|
|
2
|
+
from ._version import version as __version__ # noqa: F401
|
|
3
|
+
|
|
4
|
+
except ImportError:
|
|
5
|
+
__version__ = "0.0.0"
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
from .material_type import MaterialType # noqa: E402
|
|
13
|
+
from .catalog import MaterialCatalog, MaterialId, MaterialPage, download_snapshot # noqa: E402
|
|
14
|
+
|
|
15
|
+
from .material import TabulatedMaterial # noqa: E402
|
|
16
|
+
from .material import SellmeierMaterial # noqa: E402
|
|
17
|
+
from .material import ( # noqa: E402
|
|
18
|
+
FormulaDataset, MaterialDocument, MaterialMetadata, TabulatedDataset, parse_material,
|
|
19
|
+
)
|
|
20
|
+
from .thin_film import ( # noqa: E402
|
|
21
|
+
FresnelResult,
|
|
22
|
+
ThinFilmLayer,
|
|
23
|
+
ThinFilmResult,
|
|
24
|
+
brewster_angle,
|
|
25
|
+
critical_angle,
|
|
26
|
+
fresnel_coefficients,
|
|
27
|
+
thin_film_stack,
|
|
28
|
+
)
|
|
29
|
+
from .material import base_class # noqa: E402
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
TIMEOUT = 10 # Default timeout for requests in seconds
|
|
@@ -22,7 +22,7 @@ def main() -> None:
|
|
|
22
22
|
"command",
|
|
23
23
|
nargs="?",
|
|
24
24
|
default="setup",
|
|
25
|
-
choices=("setup", "download-all"),
|
|
25
|
+
choices=("setup", "download-all", "browse"),
|
|
26
26
|
help="Canonical catalog command (default: setup)",
|
|
27
27
|
)
|
|
28
28
|
parser.add_argument(
|
|
@@ -70,6 +70,16 @@ def main() -> None:
|
|
|
70
70
|
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
|
71
71
|
)
|
|
72
72
|
|
|
73
|
+
if args.command == "browse":
|
|
74
|
+
if args.force or args.fail_fast or args.source != "snapshot" or args.workers != 8 or args.no_progress:
|
|
75
|
+
parser.error("download options cannot be used with browse")
|
|
76
|
+
from PyOptik.tui import run_browser
|
|
77
|
+
try:
|
|
78
|
+
run_browser(args.data_root)
|
|
79
|
+
except (FileNotFoundError, RuntimeError) as error:
|
|
80
|
+
parser.error(str(error))
|
|
81
|
+
return
|
|
82
|
+
|
|
73
83
|
if args.command == "setup" and args.source != "snapshot":
|
|
74
84
|
parser.error("setup always uses the upstream snapshot; use download-all for page mode")
|
|
75
85
|
source = "snapshot" if args.command == "setup" else args.source
|
|
@@ -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 = '3.0
|
|
22
|
-
__version_tuple__ = version_tuple = (3,
|
|
21
|
+
__version__ = version = '3.2.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (3, 2, 0)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g7c8410160'
|
|
@@ -145,17 +145,16 @@ class MaterialPage:
|
|
|
145
145
|
"""
|
|
146
146
|
from PyOptik.material.sellmeier_class import SellmeierMaterial
|
|
147
147
|
from PyOptik.material.tabulated_class import TabulatedMaterial
|
|
148
|
+
from PyOptik.material.dataset import parse_material
|
|
148
149
|
|
|
149
150
|
if self.local_path is not None and self.local_path.exists():
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
entries = document.get("DATA", [])
|
|
153
|
-
if any("formula" in str(entry.get("type", "")) for entry in entries):
|
|
151
|
+
document = parse_material(self.local_path)
|
|
152
|
+
if document.formula_datasets:
|
|
154
153
|
material = SellmeierMaterial(self.name, file_path=self.local_path)
|
|
155
154
|
material.catalog_id = self.id.key
|
|
156
155
|
material.source_url = self.source_url
|
|
157
156
|
return material
|
|
158
|
-
if
|
|
157
|
+
if document.tabulated_datasets:
|
|
159
158
|
material = TabulatedMaterial(
|
|
160
159
|
self.name,
|
|
161
160
|
file_path=self.local_path,
|
|
@@ -54,6 +54,7 @@ user_data_path = _default_user_data_path()
|
|
|
54
54
|
user_sellmeier_data_path = user_data_path / "sellmeier"
|
|
55
55
|
user_tabulated_data_path = user_data_path / "tabulated"
|
|
56
56
|
|
|
57
|
+
|
|
57
58
|
def material_paths(material_type):
|
|
58
59
|
"""Return the user data directory for a material type.
|
|
59
60
|
|
|
@@ -10,6 +10,7 @@ from TypedUnit import Length, AnyUnit, Time, ureg, validate_units
|
|
|
10
10
|
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
12
12
|
|
|
13
|
+
|
|
13
14
|
class BaseMaterial(object):
|
|
14
15
|
"""Common interface for refractive-index material models.
|
|
15
16
|
|
|
@@ -195,8 +196,13 @@ class BaseMaterial(object):
|
|
|
195
196
|
raise ValueError("out_of_range must be 'warn', 'raise', or 'clip'.")
|
|
196
197
|
if self.wavelength_bound is not None:
|
|
197
198
|
min_value, max_value = self.wavelength_bound
|
|
199
|
+
values = wavelength.to(ureg.meter).magnitude
|
|
200
|
+
lower = min_value.to(ureg.meter).magnitude
|
|
201
|
+
upper = max_value.to(ureg.meter).magnitude
|
|
202
|
+
below = (values < lower) & ~numpy.isclose(values, lower, rtol=1e-12, atol=0.0)
|
|
203
|
+
above = (values > upper) & ~numpy.isclose(values, upper, rtol=1e-12, atol=0.0)
|
|
198
204
|
|
|
199
|
-
if numpy.any(
|
|
205
|
+
if numpy.any(below | above):
|
|
200
206
|
message = (
|
|
201
207
|
f"Wavelength range goes from {wavelength.min().to_compact()} to {wavelength.max().to_compact()} "
|
|
202
208
|
f"which is outside the allowable range of {min_value.to_compact()} to {max_value.to_compact()} µm. "
|