PyOptik 3.1.0__tar.gz → 3.2.1__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.2.1/.github/workflows/deploy_documentation.yml +56 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/CHANGELOG.md +19 -1
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PKG-INFO +33 -1
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/__init__.py +9 -7
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/_version.py +3 -3
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/catalog.py +5 -6
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/directories.py +1 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/material/base_class.py +1 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/material/dataset.py +0 -1
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/thin_film.py +0 -1
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/tui.py +0 -1
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/utils.py +1 -1
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik.egg-info/PKG-INFO +33 -1
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik.egg-info/SOURCES.txt +14 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik.egg-info/scm_file_list.json +14 -0
- pyoptik-3.2.1/PyOptik.egg-info/scm_version.json +8 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/README.rst +32 -0
- pyoptik-3.2.1/docs/examples/catalog/README.rst +6 -0
- pyoptik-3.2.1/docs/examples/catalog/plot_catalog_search.py +48 -0
- pyoptik-3.2.1/docs/examples/custom_materials/README.rst +6 -0
- pyoptik-3.2.1/docs/examples/custom_materials/plot_measured_material.py +54 -0
- pyoptik-3.2.1/docs/examples/interfaces/README.rst +6 -0
- pyoptik-3.2.1/docs/examples/interfaces/plot_fresnel_angles.py +42 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/sellmeier/plot_water.py +0 -1
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/tabulated/plot_silver.py +0 -1
- pyoptik-3.2.1/docs/examples/thin_films/README.rst +6 -0
- pyoptik-3.2.1/docs/examples/thin_films/plot_antireflection_coating.py +46 -0
- pyoptik-3.2.1/docs/examples/thin_films/plot_bragg_mirror.py +50 -0
- pyoptik-3.2.1/docs/images/logo.svg +22 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/source/_static/default.css +18 -1
- pyoptik-3.2.1/docs/source/_static/favicon.png +0 -0
- pyoptik-3.2.1/docs/source/_static/favicon.svg +18 -0
- pyoptik-3.2.1/docs/source/_static/logo-dark.svg +22 -0
- pyoptik-3.2.1/docs/source/_static/logo.svg +22 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/source/catalog_browser.rst +2 -3
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/source/code.rst +21 -28
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/source/conf.py +13 -3
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/source/conventions.rst +2 -2
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/source/custom_materials.rst +2 -3
- pyoptik-3.2.1/docs/source/examples.rst +19 -0
- pyoptik-3.2.1/docs/source/getting_started.rst +66 -0
- pyoptik-3.2.1/docs/source/index.rst +50 -0
- pyoptik-3.2.1/docs/source/materials_and_catalog.rst +64 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/source/sg_execution_times.rst +27 -12
- pyoptik-3.2.1/docs/source/user_guide.rst +35 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/conftest.py +2 -2
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/test_base_material_decorator.py +1 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/test_catalog.py +26 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/test_utils_extra.py +2 -1
- pyoptik-3.1.0/.github/workflows/deploy_documentation.yml +0 -23
- pyoptik-3.1.0/PyOptik.egg-info/scm_version.json +0 -8
- pyoptik-3.1.0/docs/images/logo.svg +0 -1
- pyoptik-3.1.0/docs/source/_static/favicon.png +0 -0
- pyoptik-3.1.0/docs/source/_static/logo.svg +0 -1
- pyoptik-3.1.0/docs/source/examples.rst +0 -14
- pyoptik-3.1.0/docs/source/index.rst +0 -16
- {pyoptik-3.1.0 → pyoptik-3.2.1}/.coveragerc +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/.flake8 +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/.github/dependabot.yml +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/.github/workflows/deploy_PyPi.yml +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/.github/workflows/deploy_anaconda.yml +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/.github/workflows/deploy_coverage.yml +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/.github/workflows/quality.yml +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/.github/workflows/tests.yml +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/.gitignore +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/.pre-commit-config.yaml +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/CONTRIBUTING.md +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/LICENSE +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/Makefile +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/__main__.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/material/__init__.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/material/sellmeier_class.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/material/tabulated_class.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik/material_type.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik.egg-info/dependency_links.txt +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik.egg-info/entry_points.txt +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik.egg-info/requires.txt +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/PyOptik.egg-info/top_level.txt +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/conda.recipe/meta.yaml +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/Makefile +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/README.rst +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/group_properties/README.rst +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/group_properties/plot_group_properties.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/sellmeier/README.rst +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/sellmeier/plot_bk7.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/sellmeier/plot_compare_glasses.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/sellmeier/plot_silica.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/tabulated/README.rst +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/tabulated/plot_polyethylene.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/examples/tabulated/plot_silicon_nk.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/images/example_bk7.png +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/make.bat +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/source/_static/thumbnail.png +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/source/references.rst +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/docs/source/thin_films.rst +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/pyproject.toml +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/pytest.ini +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/setup.cfg +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/__init__.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/test_datasets_and_custom_materials.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/test_docstrings.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/test_main_cli.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/test_material_models.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/test_thin_film.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/test_tui.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tests/test_validation_and_logging.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tools/next_release_version.py +0 -0
- {pyoptik-3.1.0 → pyoptik-3.2.1}/tools/release_tag.py +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Simple workflow for deploying static content to GitHub Pages
|
|
2
|
+
name: Documentation
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches: [ "master" ]
|
|
7
|
+
tags: [ "v*" ]
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: [ "master" ]
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: documentation-build-${{ github.repository }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: write
|
|
17
|
+
pages: write
|
|
18
|
+
id-token: write
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
ManyLinux_x86_64:
|
|
22
|
+
uses: MartinPdeS/MPSActions/.github/workflows/publish_documentation.yml@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.11"
|
|
25
|
+
package-name: "PyOptik"
|
|
26
|
+
apt-package: xvfb jq
|
|
27
|
+
deploy-pages: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')) }}
|
|
28
|
+
|
|
29
|
+
deploy_pages:
|
|
30
|
+
needs: ManyLinux_x86_64
|
|
31
|
+
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')) }}
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
permissions:
|
|
34
|
+
contents: read
|
|
35
|
+
pages: write
|
|
36
|
+
id-token: write
|
|
37
|
+
environment:
|
|
38
|
+
name: github-pages
|
|
39
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
40
|
+
steps:
|
|
41
|
+
- name: Checkout generated documentation
|
|
42
|
+
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
|
|
43
|
+
with:
|
|
44
|
+
ref: documentation_page
|
|
45
|
+
|
|
46
|
+
- name: Configure GitHub Pages
|
|
47
|
+
uses: actions/configure-pages@v5
|
|
48
|
+
|
|
49
|
+
- name: Upload GitHub Pages artifact
|
|
50
|
+
uses: actions/upload-pages-artifact@v3
|
|
51
|
+
with:
|
|
52
|
+
path: .
|
|
53
|
+
|
|
54
|
+
- name: Deploy GitHub Pages
|
|
55
|
+
id: deployment
|
|
56
|
+
uses: actions/deploy-pages@v4
|
|
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
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
|
+
|
|
10
27
|
## [3.1.0] - 2026-09-16
|
|
11
28
|
|
|
12
29
|
### Added
|
|
@@ -62,5 +79,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
62
79
|
plotting helpers.
|
|
63
80
|
- Retired logo assets.
|
|
64
81
|
|
|
65
|
-
[Unreleased]: https://github.com/MartinPdeS/PyOptik/compare/v3.
|
|
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
|
|
66
84
|
[3.1.0]: https://github.com/MartinPdeS/PyOptik/compare/v3.0.5...v3.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyOptik
|
|
3
|
-
Version: 3.1
|
|
3
|
+
Version: 3.2.1
|
|
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
|
|
@@ -96,6 +96,24 @@ catalog interface for the hierarchical `RefractiveIndex.INFO
|
|
|
96
96
|
The library is designed for optical design, photonics simulations,
|
|
97
97
|
electromagnetic modeling, and experimental data analysis.
|
|
98
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
|
+
|
|
99
117
|
Features
|
|
100
118
|
--------
|
|
101
119
|
|
|
@@ -343,6 +361,20 @@ Matplotlib backend before importing plotting code:
|
|
|
343
361
|
import matplotlib
|
|
344
362
|
matplotlib.use("Agg")
|
|
345
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
|
+
|
|
346
378
|
Hierarchical material catalog
|
|
347
379
|
-----------------------------
|
|
348
380
|
|
|
@@ -9,13 +9,15 @@ import logging
|
|
|
9
9
|
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
from .material_type import MaterialType
|
|
13
|
-
from .catalog import MaterialCatalog, MaterialId, MaterialPage, download_snapshot
|
|
12
|
+
from .material_type import MaterialType # noqa: E402
|
|
13
|
+
from .catalog import MaterialCatalog, MaterialId, MaterialPage, download_snapshot # noqa: E402
|
|
14
14
|
|
|
15
|
-
from .material import TabulatedMaterial
|
|
16
|
-
from .material import SellmeierMaterial
|
|
17
|
-
from .material import
|
|
18
|
-
|
|
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
|
|
19
21
|
FresnelResult,
|
|
20
22
|
ThinFilmLayer,
|
|
21
23
|
ThinFilmResult,
|
|
@@ -24,7 +26,7 @@ from .thin_film import (
|
|
|
24
26
|
fresnel_coefficients,
|
|
25
27
|
thin_film_stack,
|
|
26
28
|
)
|
|
27
|
-
from .material import base_class
|
|
29
|
+
from .material import base_class # noqa: E402
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
TIMEOUT = 10 # Default timeout for requests in seconds
|
|
@@ -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.1
|
|
22
|
-
__version_tuple__ = version_tuple = (3,
|
|
21
|
+
__version__ = version = '3.2.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (3, 2, 1)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g6f0650682'
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""Catalog and upstream-identity support for optical material data."""
|
|
2
2
|
|
|
3
|
-
from __future__ import annotations
|
|
4
3
|
|
|
5
4
|
from dataclasses import dataclass
|
|
6
5
|
from pathlib import Path
|
|
@@ -78,7 +77,7 @@ class MaterialPage:
|
|
|
78
77
|
if not self.available:
|
|
79
78
|
return None
|
|
80
79
|
try:
|
|
81
|
-
with self.local_path.open("r") as stream:
|
|
80
|
+
with self.local_path.open("r", encoding="utf-8") as stream:
|
|
82
81
|
reference = (yaml.safe_load(stream) or {}).get("REFERENCES")
|
|
83
82
|
return str(reference) if reference is not None else None
|
|
84
83
|
except (OSError, yaml.YAMLError):
|
|
@@ -286,7 +285,7 @@ class MaterialCatalog:
|
|
|
286
285
|
existing_manifest = None
|
|
287
286
|
if catalog_file.exists() and not force:
|
|
288
287
|
try:
|
|
289
|
-
with (root / "manifest.json").open("r") as stream:
|
|
288
|
+
with (root / "manifest.json").open("r", encoding="utf-8") as stream:
|
|
290
289
|
existing_manifest = json.load(stream)
|
|
291
290
|
except (FileNotFoundError, json.JSONDecodeError):
|
|
292
291
|
existing_manifest = None
|
|
@@ -381,7 +380,7 @@ class MaterialCatalog:
|
|
|
381
380
|
def load_catalog(self, catalog_file: Path | str) -> None:
|
|
382
381
|
"""Load an upstream ``catalog-nk.yml`` file."""
|
|
383
382
|
catalog_file = Path(catalog_file)
|
|
384
|
-
with catalog_file.open("r") as stream:
|
|
383
|
+
with catalog_file.open("r", encoding="utf-8") as stream:
|
|
385
384
|
document = yaml.safe_load(stream) or []
|
|
386
385
|
self._pages.clear()
|
|
387
386
|
|
|
@@ -529,7 +528,7 @@ class MaterialCatalog:
|
|
|
529
528
|
if not self.manifest_path.exists():
|
|
530
529
|
return {"catalog": {}, "pages": {}}
|
|
531
530
|
try:
|
|
532
|
-
with self.manifest_path.open("r") as stream:
|
|
531
|
+
with self.manifest_path.open("r", encoding="utf-8") as stream:
|
|
533
532
|
manifest = json.load(stream)
|
|
534
533
|
manifest.setdefault("catalog", {})
|
|
535
534
|
manifest.setdefault("pages", {})
|
|
@@ -542,7 +541,7 @@ class MaterialCatalog:
|
|
|
542
541
|
"""Atomically write the download manifest after a page completes."""
|
|
543
542
|
self.data_root.mkdir(parents=True, exist_ok=True)
|
|
544
543
|
temporary = self.manifest_path.with_suffix(".json.tmp")
|
|
545
|
-
with temporary.open("w") as stream:
|
|
544
|
+
with temporary.open("w", encoding="utf-8") as stream:
|
|
546
545
|
json.dump(manifest, stream, indent=2, sort_keys=True)
|
|
547
546
|
stream.write("\n")
|
|
548
547
|
temporary.replace(self.manifest_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
|
|
|
@@ -103,6 +103,6 @@ def download_yml_file(
|
|
|
103
103
|
except requests.exceptions.HTTPError as e:
|
|
104
104
|
logger.error("HTTP error while downloading %s: %s", url, e)
|
|
105
105
|
raise
|
|
106
|
-
except Exception
|
|
106
|
+
except Exception:
|
|
107
107
|
logger.exception("Unexpected error while saving %s to %s", url, file_path)
|
|
108
108
|
raise
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyOptik
|
|
3
|
-
Version: 3.1
|
|
3
|
+
Version: 3.2.1
|
|
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
|
|
@@ -96,6 +96,24 @@ catalog interface for the hierarchical `RefractiveIndex.INFO
|
|
|
96
96
|
The library is designed for optical design, photonics simulations,
|
|
97
97
|
electromagnetic modeling, and experimental data analysis.
|
|
98
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
|
+
|
|
99
117
|
Features
|
|
100
118
|
--------
|
|
101
119
|
|
|
@@ -343,6 +361,20 @@ Matplotlib backend before importing plotting code:
|
|
|
343
361
|
import matplotlib
|
|
344
362
|
matplotlib.use("Agg")
|
|
345
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
|
+
|
|
346
378
|
Hierarchical material catalog
|
|
347
379
|
-----------------------------
|
|
348
380
|
|
|
@@ -42,8 +42,14 @@ conda.recipe/meta.yaml
|
|
|
42
42
|
docs/Makefile
|
|
43
43
|
docs/make.bat
|
|
44
44
|
docs/examples/README.rst
|
|
45
|
+
docs/examples/catalog/README.rst
|
|
46
|
+
docs/examples/catalog/plot_catalog_search.py
|
|
47
|
+
docs/examples/custom_materials/README.rst
|
|
48
|
+
docs/examples/custom_materials/plot_measured_material.py
|
|
45
49
|
docs/examples/group_properties/README.rst
|
|
46
50
|
docs/examples/group_properties/plot_group_properties.py
|
|
51
|
+
docs/examples/interfaces/README.rst
|
|
52
|
+
docs/examples/interfaces/plot_fresnel_angles.py
|
|
47
53
|
docs/examples/sellmeier/README.rst
|
|
48
54
|
docs/examples/sellmeier/plot_bk7.py
|
|
49
55
|
docs/examples/sellmeier/plot_compare_glasses.py
|
|
@@ -53,6 +59,9 @@ docs/examples/tabulated/README.rst
|
|
|
53
59
|
docs/examples/tabulated/plot_polyethylene.py
|
|
54
60
|
docs/examples/tabulated/plot_silicon_nk.py
|
|
55
61
|
docs/examples/tabulated/plot_silver.py
|
|
62
|
+
docs/examples/thin_films/README.rst
|
|
63
|
+
docs/examples/thin_films/plot_antireflection_coating.py
|
|
64
|
+
docs/examples/thin_films/plot_bragg_mirror.py
|
|
56
65
|
docs/images/example_bk7.png
|
|
57
66
|
docs/images/logo.svg
|
|
58
67
|
docs/source/catalog_browser.rst
|
|
@@ -61,12 +70,17 @@ docs/source/conf.py
|
|
|
61
70
|
docs/source/conventions.rst
|
|
62
71
|
docs/source/custom_materials.rst
|
|
63
72
|
docs/source/examples.rst
|
|
73
|
+
docs/source/getting_started.rst
|
|
64
74
|
docs/source/index.rst
|
|
75
|
+
docs/source/materials_and_catalog.rst
|
|
65
76
|
docs/source/references.rst
|
|
66
77
|
docs/source/sg_execution_times.rst
|
|
67
78
|
docs/source/thin_films.rst
|
|
79
|
+
docs/source/user_guide.rst
|
|
68
80
|
docs/source/_static/default.css
|
|
69
81
|
docs/source/_static/favicon.png
|
|
82
|
+
docs/source/_static/favicon.svg
|
|
83
|
+
docs/source/_static/logo-dark.svg
|
|
70
84
|
docs/source/_static/logo.svg
|
|
71
85
|
docs/source/_static/thumbnail.png
|
|
72
86
|
tests/__init__.py
|
|
@@ -33,8 +33,14 @@
|
|
|
33
33
|
"conda.recipe/meta.yaml",
|
|
34
34
|
"docs/Makefile",
|
|
35
35
|
"docs/examples/README.rst",
|
|
36
|
+
"docs/examples/catalog/README.rst",
|
|
37
|
+
"docs/examples/catalog/plot_catalog_search.py",
|
|
38
|
+
"docs/examples/custom_materials/README.rst",
|
|
39
|
+
"docs/examples/custom_materials/plot_measured_material.py",
|
|
36
40
|
"docs/examples/group_properties/README.rst",
|
|
37
41
|
"docs/examples/group_properties/plot_group_properties.py",
|
|
42
|
+
"docs/examples/interfaces/README.rst",
|
|
43
|
+
"docs/examples/interfaces/plot_fresnel_angles.py",
|
|
38
44
|
"docs/examples/sellmeier/README.rst",
|
|
39
45
|
"docs/examples/sellmeier/plot_bk7.py",
|
|
40
46
|
"docs/examples/sellmeier/plot_compare_glasses.py",
|
|
@@ -44,11 +50,16 @@
|
|
|
44
50
|
"docs/examples/tabulated/plot_polyethylene.py",
|
|
45
51
|
"docs/examples/tabulated/plot_silicon_nk.py",
|
|
46
52
|
"docs/examples/tabulated/plot_silver.py",
|
|
53
|
+
"docs/examples/thin_films/README.rst",
|
|
54
|
+
"docs/examples/thin_films/plot_antireflection_coating.py",
|
|
55
|
+
"docs/examples/thin_films/plot_bragg_mirror.py",
|
|
47
56
|
"docs/images/example_bk7.png",
|
|
48
57
|
"docs/images/logo.svg",
|
|
49
58
|
"docs/make.bat",
|
|
50
59
|
"docs/source/_static/default.css",
|
|
51
60
|
"docs/source/_static/favicon.png",
|
|
61
|
+
"docs/source/_static/favicon.svg",
|
|
62
|
+
"docs/source/_static/logo-dark.svg",
|
|
52
63
|
"docs/source/_static/logo.svg",
|
|
53
64
|
"docs/source/_static/thumbnail.png",
|
|
54
65
|
"docs/source/catalog_browser.rst",
|
|
@@ -57,10 +68,13 @@
|
|
|
57
68
|
"docs/source/conventions.rst",
|
|
58
69
|
"docs/source/custom_materials.rst",
|
|
59
70
|
"docs/source/examples.rst",
|
|
71
|
+
"docs/source/getting_started.rst",
|
|
60
72
|
"docs/source/index.rst",
|
|
73
|
+
"docs/source/materials_and_catalog.rst",
|
|
61
74
|
"docs/source/references.rst",
|
|
62
75
|
"docs/source/sg_execution_times.rst",
|
|
63
76
|
"docs/source/thin_films.rst",
|
|
77
|
+
"docs/source/user_guide.rst",
|
|
64
78
|
"pyproject.toml",
|
|
65
79
|
"pytest.ini",
|
|
66
80
|
"tests/__init__.py",
|
|
@@ -35,6 +35,24 @@ catalog interface for the hierarchical `RefractiveIndex.INFO
|
|
|
35
35
|
The library is designed for optical design, photonics simulations,
|
|
36
36
|
electromagnetic modeling, and experimental data analysis.
|
|
37
37
|
|
|
38
|
+
Documentation
|
|
39
|
+
-------------
|
|
40
|
+
|
|
41
|
+
The full documentation is organized by task:
|
|
42
|
+
|
|
43
|
+
* `Getting started <https://martinpdes.github.io/PyOptik/getting_started.html>`_
|
|
44
|
+
for installation and a first unit-aware calculation.
|
|
45
|
+
* `Materials and catalog <https://martinpdes.github.io/PyOptik/materials_and_catalog.html>`_
|
|
46
|
+
for model selection, search, provenance, and cache integrity.
|
|
47
|
+
* `Custom materials <https://martinpdes.github.io/PyOptik/custom_materials.html>`_
|
|
48
|
+
for arrays, CSV import, coefficients, validation, and YAML export.
|
|
49
|
+
* `Interfaces and thin films <https://martinpdes.github.io/PyOptik/thin_films.html>`_
|
|
50
|
+
for Fresnel coefficients and coherent multilayer design.
|
|
51
|
+
* `Example gallery <https://martinpdes.github.io/PyOptik/examples.html>`_
|
|
52
|
+
for complete, executable workflows.
|
|
53
|
+
* `API reference <https://martinpdes.github.io/PyOptik/code.html>`_ for public
|
|
54
|
+
classes and functions.
|
|
55
|
+
|
|
38
56
|
Features
|
|
39
57
|
--------
|
|
40
58
|
|
|
@@ -282,6 +300,20 @@ Matplotlib backend before importing plotting code:
|
|
|
282
300
|
import matplotlib
|
|
283
301
|
matplotlib.use("Agg")
|
|
284
302
|
|
|
303
|
+
Worked examples
|
|
304
|
+
---------------
|
|
305
|
+
|
|
306
|
+
The documentation gallery includes downloadable Python scripts and notebooks
|
|
307
|
+
for:
|
|
308
|
+
|
|
309
|
+
* Sellmeier and tabulated material dispersion;
|
|
310
|
+
* group index and group velocity;
|
|
311
|
+
* importing, interpolating, exporting, and reloading measured optical data;
|
|
312
|
+
* s- and p-polarized Fresnel reflectance and Brewster angle;
|
|
313
|
+
* quarter-wave antireflection coatings;
|
|
314
|
+
* multilayer dielectric Bragg mirrors; and
|
|
315
|
+
* catalog search, canonical source selection, and provenance capture.
|
|
316
|
+
|
|
285
317
|
Hierarchical material catalog
|
|
286
318
|
-----------------------------
|
|
287
319
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Search materials and inspect provenance
|
|
3
|
+
=======================================
|
|
4
|
+
|
|
5
|
+
Find locally available BK7 datasets, inspect their canonical identities, and
|
|
6
|
+
compare representative glass pages at a standard wavelength.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# %%
|
|
10
|
+
import matplotlib.pyplot as plt
|
|
11
|
+
from TypedUnit import ureg
|
|
12
|
+
|
|
13
|
+
from PyOptik import MaterialCatalog
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
catalog = MaterialCatalog.from_snapshot()
|
|
17
|
+
matches = catalog.search("BK7", shelf="specs", available=True)
|
|
18
|
+
|
|
19
|
+
print(f"Found {len(matches)} cached BK7 pages")
|
|
20
|
+
for page in matches[:5]:
|
|
21
|
+
print(page.id.key, "—", page.description)
|
|
22
|
+
|
|
23
|
+
# %%
|
|
24
|
+
# Canonical IDs make source selection explicit and reproducible.
|
|
25
|
+
identifiers = [
|
|
26
|
+
"specs/SCHOTT-optical/N-BK7",
|
|
27
|
+
"specs/OHARA-optical/S-BSL7",
|
|
28
|
+
]
|
|
29
|
+
wavelength = 587.6 * ureg.nanometer
|
|
30
|
+
labels, indices = [], []
|
|
31
|
+
|
|
32
|
+
for identifier in identifiers:
|
|
33
|
+
page = catalog.get(identifier)
|
|
34
|
+
material = page.load()
|
|
35
|
+
labels.append(page.id.page)
|
|
36
|
+
indices.append(float(material.n(wavelength, out_of_range="raise")))
|
|
37
|
+
print(material.provenance)
|
|
38
|
+
|
|
39
|
+
# %%
|
|
40
|
+
figure, axis = plt.subplots(figsize=(6, 3.5), layout="constrained")
|
|
41
|
+
axis.bar(labels, indices, color=["tab:blue", "tab:orange"])
|
|
42
|
+
axis.set(
|
|
43
|
+
ylabel="Refractive index at 587.6 nm",
|
|
44
|
+
title="Catalog-backed glass comparison",
|
|
45
|
+
ylim=(1.50, 1.54),
|
|
46
|
+
)
|
|
47
|
+
axis.grid(axis="y", alpha=0.25)
|
|
48
|
+
plt.show()
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Create and export a measured material
|
|
3
|
+
=====================================
|
|
4
|
+
|
|
5
|
+
This example builds a complex refractive-index model from measured arrays,
|
|
6
|
+
evaluates the interpolation, and verifies a YAML export/reload round trip.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# %%
|
|
10
|
+
from tempfile import TemporaryDirectory
|
|
11
|
+
|
|
12
|
+
import matplotlib.pyplot as plt
|
|
13
|
+
import numpy
|
|
14
|
+
from TypedUnit import ureg
|
|
15
|
+
|
|
16
|
+
from PyOptik import TabulatedMaterial
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
wavelength_samples = numpy.array([400, 475, 550, 625, 700]) * ureg.nanometer
|
|
20
|
+
measured_n = [1.58, 1.56, 1.545, 1.535, 1.528]
|
|
21
|
+
measured_k = [0.030, 0.018, 0.010, 0.006, 0.004]
|
|
22
|
+
|
|
23
|
+
material = TabulatedMaterial.from_arrays(
|
|
24
|
+
"measured-film",
|
|
25
|
+
wavelength_samples,
|
|
26
|
+
n=measured_n,
|
|
27
|
+
k=measured_k,
|
|
28
|
+
interpolation="pchip",
|
|
29
|
+
reference="Illustrative ellipsometry dataset",
|
|
30
|
+
conditions={"temperature": "293 K"},
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# %%
|
|
34
|
+
# Exported files use the same validated schema as catalog materials.
|
|
35
|
+
with TemporaryDirectory() as directory:
|
|
36
|
+
path = material.to_yaml(f"{directory}/measured-film.yml")
|
|
37
|
+
restored = TabulatedMaterial("measured-film", file_path=path, interpolation="pchip")
|
|
38
|
+
assert restored.reference == material.reference
|
|
39
|
+
|
|
40
|
+
# %%
|
|
41
|
+
wavelengths = numpy.linspace(400, 700, 301) * ureg.nanometer
|
|
42
|
+
index = material.compute_refractive_index(wavelengths, out_of_range="raise")
|
|
43
|
+
|
|
44
|
+
figure, (axis_n, axis_k) = plt.subplots(2, 1, sharex=True, layout="constrained")
|
|
45
|
+
axis_n.plot(wavelengths.magnitude, index.real, label="PCHIP interpolation")
|
|
46
|
+
axis_n.scatter(wavelength_samples.magnitude, measured_n, label="Measurements")
|
|
47
|
+
axis_n.set(ylabel="Refractive index n", title="User-defined optical constants")
|
|
48
|
+
axis_n.legend()
|
|
49
|
+
|
|
50
|
+
axis_k.plot(wavelengths.magnitude, index.imag, color="tab:red")
|
|
51
|
+
axis_k.scatter(wavelength_samples.magnitude, measured_k, color="tab:red")
|
|
52
|
+
axis_k.set(xlabel="Wavelength [nm]", ylabel="Extinction coefficient k")
|
|
53
|
+
|
|
54
|
+
plt.show()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Fresnel reflectance versus incidence angle
|
|
3
|
+
==========================================
|
|
4
|
+
|
|
5
|
+
Compare s and p polarization at an air-to-glass interface and identify the
|
|
6
|
+
Brewster angle where p-polarized reflection vanishes.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# %%
|
|
10
|
+
import matplotlib.pyplot as plt
|
|
11
|
+
import numpy
|
|
12
|
+
from TypedUnit import ureg
|
|
13
|
+
|
|
14
|
+
from PyOptik import brewster_angle, fresnel_coefficients
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
angles = numpy.linspace(0, 89, 500) * ureg.degree
|
|
18
|
+
reflectance_s = numpy.array([
|
|
19
|
+
fresnel_coefficients(1.0, 1.5, angle, polarization="s").reflectance
|
|
20
|
+
for angle in angles
|
|
21
|
+
])
|
|
22
|
+
reflectance_p = numpy.array([
|
|
23
|
+
fresnel_coefficients(1.0, 1.5, angle, polarization="p").reflectance
|
|
24
|
+
for angle in angles
|
|
25
|
+
])
|
|
26
|
+
brewster = brewster_angle(1.0, 1.5).to(ureg.degree).magnitude
|
|
27
|
+
|
|
28
|
+
# %%
|
|
29
|
+
figure, axis = plt.subplots(layout="constrained")
|
|
30
|
+
axis.plot(angles.magnitude, reflectance_s, label="s polarization")
|
|
31
|
+
axis.plot(angles.magnitude, reflectance_p, label="p polarization")
|
|
32
|
+
axis.axvline(brewster, color="black", linestyle="--", label=f"Brewster: {brewster:.1f}°")
|
|
33
|
+
axis.set(
|
|
34
|
+
xlabel="Incidence angle [degree]",
|
|
35
|
+
ylabel="Reflectance",
|
|
36
|
+
title="Air–glass Fresnel reflectance",
|
|
37
|
+
xlim=(0, 90),
|
|
38
|
+
ylim=(0, 1),
|
|
39
|
+
)
|
|
40
|
+
axis.grid(alpha=0.25)
|
|
41
|
+
axis.legend()
|
|
42
|
+
plt.show()
|