PyOptik 1.11.0__tar.gz → 1.12.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. {pyoptik-1.11.0 → pyoptik-1.12.0}/.gitignore +1 -1
  2. {pyoptik-1.11.0 → pyoptik-1.12.0}/PKG-INFO +6 -1
  3. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/__main__.py +1 -1
  4. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/_version.py +2 -2
  5. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/material/base_class.py +54 -7
  6. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/material/sellmeier_class.py +12 -12
  7. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/material/tabulated_class.py +9 -9
  8. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/units.py +2 -1
  9. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik.egg-info/PKG-INFO +6 -1
  10. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik.egg-info/SOURCES.txt +1 -0
  11. {pyoptik-1.11.0 → pyoptik-1.12.0}/README.rst +5 -0
  12. {pyoptik-1.11.0 → pyoptik-1.12.0}/pyproject.toml +1 -0
  13. pyoptik-1.12.0/tests/test_group_properties.py +27 -0
  14. {pyoptik-1.11.0 → pyoptik-1.12.0}/.flake8 +0 -0
  15. {pyoptik-1.11.0 → pyoptik-1.12.0}/.github/dependabot.yml +0 -0
  16. {pyoptik-1.11.0 → pyoptik-1.12.0}/.github/workflows/deploy_PyPi.yml +0 -0
  17. {pyoptik-1.11.0 → pyoptik-1.12.0}/.github/workflows/deploy_anaconda.yml +0 -0
  18. {pyoptik-1.11.0 → pyoptik-1.12.0}/.github/workflows/deploy_coverage.yml +0 -0
  19. {pyoptik-1.11.0 → pyoptik-1.12.0}/.github/workflows/deploy_documentation.yml +0 -0
  20. {pyoptik-1.11.0 → pyoptik-1.12.0}/LICENSE +0 -0
  21. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/__init__.py +0 -0
  22. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/__init__.py +0 -0
  23. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/BAK1.yml +0 -0
  24. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/BK7.yml +0 -0
  25. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/SF5.yml +0 -0
  26. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/ZBLAN.yml +0 -0
  27. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/acetone.yml +0 -0
  28. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/air.yml +0 -0
  29. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/argon.yml +0 -0
  30. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/crown.yml +0 -0
  31. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/flint.yml +0 -0
  32. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/fused_silica.yml +0 -0
  33. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/germanium.yml +0 -0
  34. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/lithium_niobate.yml +0 -0
  35. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/polystyren.yml +0 -0
  36. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/soda_lime_glass.yml +0 -0
  37. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/sellmeier/water.yml +0 -0
  38. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/tabulated/aluminium.yml +0 -0
  39. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/tabulated/calcium.yml +0 -0
  40. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/tabulated/copper.yml +0 -0
  41. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/tabulated/gold.yml +0 -0
  42. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/tabulated/iron.yml +0 -0
  43. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/tabulated/nickel.yml +0 -0
  44. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/tabulated/polyetylene.yml +0 -0
  45. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/tabulated/silicon.yml +0 -0
  46. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/tabulated/silver.yml +0 -0
  47. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/tabulated/sodium.yml +0 -0
  48. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/data/tabulated/zinc.yml +0 -0
  49. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/directories.py +0 -0
  50. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/libraries/__init__.py +0 -0
  51. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/libraries/classics.yml +0 -0
  52. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/libraries/dielectrics.yml +0 -0
  53. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/libraries/metals.yml +0 -0
  54. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/libraries/minimal.yml +0 -0
  55. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/libraries/organics.yml +0 -0
  56. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/libraries/others.yml +0 -0
  57. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/libraries/polymers.yml +0 -0
  58. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/libraries/repertoire.yml +0 -0
  59. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/material/__init__.py +0 -0
  60. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/material_bank.py +0 -0
  61. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/material_type.py +0 -0
  62. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik/utils.py +0 -0
  63. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik.egg-info/dependency_links.txt +0 -0
  64. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik.egg-info/requires.txt +0 -0
  65. {pyoptik-1.11.0 → pyoptik-1.12.0}/PyOptik.egg-info/top_level.txt +0 -0
  66. {pyoptik-1.11.0 → pyoptik-1.12.0}/development/dev_0.py +0 -0
  67. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/Makefile +0 -0
  68. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/README.rst +0 -0
  69. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/sellmeier/README.rst +0 -0
  70. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/sellmeier/plot_bk7.py +0 -0
  71. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/sellmeier/plot_silica.py +0 -0
  72. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/sellmeier/plot_water.py +0 -0
  73. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/tabulated/README.rst +0 -0
  74. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/tabulated/plot_sf5.py +0 -0
  75. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/tabulated/plot_silver.py +0 -0
  76. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/utils/README.rst +0 -0
  77. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/utils/__build_library.py +0 -0
  78. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/utils/__download_yml_file.py +0 -0
  79. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/utils/create_sellmeier_file.py +0 -0
  80. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/examples/utils/create_tabulated_file.py +0 -0
  81. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/images/example_bk7.png +0 -0
  82. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/images/logo.png +0 -0
  83. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/make.bat +0 -0
  84. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/source/_static/default.css +0 -0
  85. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/source/_static/thumbnail.png +0 -0
  86. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/source/code.rst +0 -0
  87. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/source/conf.py +0 -0
  88. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/source/gallery/index.rst +0 -0
  89. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/source/index.rst +0 -0
  90. {pyoptik-1.11.0 → pyoptik-1.12.0}/docs/source/references.rst +0 -0
  91. {pyoptik-1.11.0 → pyoptik-1.12.0}/meta.yaml +0 -0
  92. {pyoptik-1.11.0 → pyoptik-1.12.0}/setup.cfg +0 -0
  93. {pyoptik-1.11.0 → pyoptik-1.12.0}/tests/__init__.py +0 -0
  94. {pyoptik-1.11.0 → pyoptik-1.12.0}/tests/test_base_material_decorator.py +0 -0
  95. {pyoptik-1.11.0 → pyoptik-1.12.0}/tests/test_material_bank_extra.py +0 -0
  96. {pyoptik-1.11.0 → pyoptik-1.12.0}/tests/test_sellmeier.py +0 -0
  97. {pyoptik-1.11.0 → pyoptik-1.12.0}/tests/test_tabulated.py +0 -0
  98. {pyoptik-1.11.0 → pyoptik-1.12.0}/tests/test_usual_materials.py +0 -0
  99. {pyoptik-1.11.0 → pyoptik-1.12.0}/tests/test_utils.py +0 -0
  100. {pyoptik-1.11.0 → pyoptik-1.12.0}/tests/test_utils_extra.py +0 -0
@@ -6,7 +6,7 @@
6
6
  *.a
7
7
  .coverage*
8
8
  *.pytest_cache
9
- htmlcov
9
+ htmlcov*
10
10
  dist
11
11
  build
12
12
  *.egg*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyOptik
3
- Version: 1.11.0
3
+ Version: 1.12.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
@@ -92,6 +92,7 @@ Features
92
92
  - **Simulation Ready**: Ideal for light-matter interaction simulations, particularly in optics and photonics.
93
93
  - **Simple API**: Easy-to-use API that integrates well with other Python libraries.
94
94
  - **Open Source**: Fully open-source.
95
+ - **Group Index and Velocity**: Compute group index and group velocity directly from material objects.
95
96
 
96
97
  Installation
97
98
  ************
@@ -174,6 +175,10 @@ After installing PyOptik and building the material library, you can easily acces
174
175
  bk7 = MaterialBank.BK7
175
176
  n = bk7.compute_refractive_index(0.55e-6)
176
177
  print(f"Refractive index at 0.55 µm: {n}")
178
+ # Group index and group velocity
179
+ n_g = bk7.compute_group_index(0.55e-6)
180
+ v_g = bk7.compute_group_velocity(0.55e-6)
181
+ print(f"Group index: {n_g:.3f}, group velocity: {v_g:.1f}")
177
182
 
178
183
  Example
179
184
  *******
@@ -4,4 +4,4 @@ import logging
4
4
 
5
5
  if __name__ == '__main__':
6
6
  logging.info('Building material library')
7
- MaterialBank.build_library('classics')
7
+ MaterialBank.build_library('all')
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '1.11.0'
21
- __version_tuple__ = version_tuple = (1, 11, 0)
20
+ __version__ = version = '1.12.0'
21
+ __version_tuple__ = version_tuple = (1, 12, 0)
@@ -2,12 +2,12 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  from typing import Callable
5
- from PyOptik.units import Quantity, meter
5
+ from PyOptik import units
6
6
  import numpy
7
7
  import warnings
8
8
 
9
9
 
10
- class BaseMaterial:
10
+ class BaseMaterial(object):
11
11
  def __eq__(self, other) -> bool:
12
12
  if not isinstance(other, self.__class__):
13
13
  return False
@@ -39,7 +39,7 @@ class BaseMaterial:
39
39
  """
40
40
  return self.__str__()
41
41
 
42
- def _check_wavelength(self, wavelength: Quantity) -> None:
42
+ def _check_wavelength(self, wavelength: units.Quantity) -> None:
43
43
  """
44
44
  Checks if a wavelength is within the material's allowable range and raises a warning if it is not.
45
45
 
@@ -77,14 +77,61 @@ class BaseMaterial:
77
77
  Wrapped version of ``func`` that accepts numerical wavelengths and
78
78
  converts them to metre-based :class:`~PyOptik.units.Quantity` objects.
79
79
  """
80
- def wrapper(self, wavelength: Quantity = None, *args, **kwargs):
80
+ def wrapper(self, wavelength: units.Quantity = None, *args, **kwargs):
81
81
  if wavelength is None:
82
82
  if self.wavelength_bound is None:
83
83
  raise ValueError('Wavelength must be provided for computation.')
84
84
  wavelength = numpy.linspace(self.wavelength_bound[0].magnitude, self.wavelength_bound[1].magnitude, 100) * self.wavelength_bound.units
85
85
 
86
- import PyOptik.units
87
- if not isinstance(wavelength, PyOptik.units.Quantity):
88
- wavelength = wavelength * meter
86
+ if not isinstance(wavelength, units.Quantity):
87
+ wavelength = wavelength * units.meter
89
88
  return func(self, wavelength, *args, **kwargs)
90
89
  return wrapper
90
+
91
+ @ensure_units
92
+ def compute_group_index(self, wavelength: units.Quantity, delta: units.Quantity = 1 * units.nanometer) -> units.Quantity:
93
+ """
94
+ Calculate the group refractive index n_g(\u03bb).
95
+ The group index is defined as n_g(\u03bb) = n(\u03bb) - \u03bb * dn/d\u03bb,
96
+ where n(\u03bb) is the refractive index and dn/d\u03bb is the derivative of
97
+ the refractive index with respect to wavelength.
98
+
99
+ Parameters
100
+ ----------
101
+ wavelength : units.Quantity
102
+ Wavelength at which to compute the group index, in metres.
103
+ delta : units.Quantity, optional
104
+ Small change in wavelength for numerical differentiation, default is 1 nanometer.
105
+
106
+ Returns
107
+ -------
108
+ units.Quantity
109
+ Group refractive index at the specified wavelength, in dimensionless units.
110
+ -------
111
+ units.Quantity
112
+ Group refractive index at the specified wavelength, in dimensionless units.
113
+ """
114
+ n = self.compute_refractive_index(wavelength)
115
+ n_plus = self.compute_refractive_index(wavelength + delta)
116
+ dn_dlambda = (n_plus - n) / delta
117
+ return n - wavelength * dn_dlambda
118
+
119
+ @ensure_units
120
+ def compute_group_velocity(self, wavelength: units.Quantity) -> units.Quantity:
121
+ """
122
+ Calculate the group velocity v_g(\u03bb) = c / n_g(\u03bb),
123
+ where c is the speed of light in vacuum and n_g(\u03bb) is the group index.
124
+
125
+ Parameters
126
+ ----------
127
+ wavelength : units.Quantity
128
+ Wavelength at which to compute the group velocity, in metres.
129
+
130
+ Returns
131
+ -------
132
+ units.Quantity
133
+ Group velocity at the specified wavelength, in metres per second.
134
+ """
135
+ ng = self.compute_group_index(wavelength)
136
+ c = 299792458 * units.meter / units.second
137
+ return c / ng
@@ -7,7 +7,7 @@ import itertools
7
7
  from MPSPlots.styles import mps
8
8
  import matplotlib.pyplot as plt
9
9
  from typing import Optional, Union
10
- from PyOptik.units import micrometer, Quantity
10
+ from PyOptik import units
11
11
  from PyOptik.directories import sellmeier_data_path
12
12
  from PyOptik.material.base_class import BaseMaterial
13
13
 
@@ -80,7 +80,7 @@ class SellmeierMaterial(BaseMaterial):
80
80
  if 'wavelength_range' in parsed_yaml['DATA'][0]:
81
81
  data_str = parsed_yaml['DATA'][0]['wavelength_range'].split()
82
82
 
83
- self.wavelength_bound = numpy.array([float(val) for val in data_str]) * micrometer
83
+ self.wavelength_bound = numpy.array([float(val) for val in data_str]) * units.micrometer
84
84
 
85
85
  else:
86
86
  self.wavelength_bound = None
@@ -89,18 +89,18 @@ class SellmeierMaterial(BaseMaterial):
89
89
  self.reference = parsed_yaml.get('REFERENCES', None)
90
90
 
91
91
  @BaseMaterial.ensure_units
92
- def compute_refractive_index(self, wavelength: Union[Quantity]) -> Union[float, numpy.ndarray]:
92
+ def compute_refractive_index(self, wavelength: Union[units.Quantity]) -> Union[float, numpy.ndarray]:
93
93
  r"""
94
94
  Computes the refractive index n(\u03bb) using the appropriate formula (either Formula 1, 2, 5, or 6).
95
95
 
96
96
  Parameters
97
97
  ----------
98
- wavelength : Union[Quantity]
98
+ wavelength : Union[units.Quantity]
99
99
  The wavelength \u03bb in meters, can be a single float or a numpy array.
100
100
 
101
101
  Returns
102
102
  -------
103
- Union[Quantity]
103
+ Union[units.Quantity]
104
104
  The refractive index n(\u03bb) for the given wavelength or array of wavelengths.
105
105
 
106
106
  Raises
@@ -120,25 +120,25 @@ class SellmeierMaterial(BaseMaterial):
120
120
  case 1: # Formula 1 computation (standard Sellmeier)
121
121
  n_squared = 1.0
122
122
  for (B, C) in zipped_coefficients:
123
- n_squared += (B * wavelength.to(micrometer).magnitude**2) / (wavelength.to(micrometer).magnitude**2 - C**2)
123
+ n_squared += (B * wavelength.to(units.micrometer).magnitude**2) / (wavelength.to(units.micrometer).magnitude**2 - C**2)
124
124
 
125
125
  n = numpy.sqrt(n_squared)
126
126
 
127
127
  case 2: # Formula 2 computation (extended Sellmeier)
128
128
  n_squared = 1 + self.coefficients[0]
129
129
  for (B, C) in zipped_coefficients:
130
- n_squared += (B * wavelength.to(micrometer).magnitude**2) / (wavelength.to(micrometer).magnitude**2 - C)
130
+ n_squared += (B * wavelength.to(units.micrometer).magnitude**2) / (wavelength.to(units.micrometer).magnitude**2 - C)
131
131
  n = numpy.sqrt(n_squared)
132
132
 
133
133
  case 5: # Formula 5 computation (extended Sellmeier)
134
134
  n = 1 + self.coefficients[0]
135
135
  for (B, C) in zipped_coefficients:
136
- n += B * wavelength.to(micrometer).magnitude**C
136
+ n += B * wavelength.to(units.micrometer).magnitude**C
137
137
 
138
138
  case 6:
139
139
  n = 1 + self.coefficients[0]
140
140
  for (B, C) in zipped_coefficients:
141
- n = B / (C - wavelength.to(micrometer).magnitude**-2)
141
+ n = B / (C - wavelength.to(units.micrometer).magnitude**-2)
142
142
 
143
143
  case _:
144
144
  raise ValueError(f"Unsupported formula type: {self.formula_type}")
@@ -146,13 +146,13 @@ class SellmeierMaterial(BaseMaterial):
146
146
  return n[0] if return_as_scalar else n
147
147
 
148
148
  @BaseMaterial.ensure_units
149
- def plot(self, wavelength: Optional[Quantity] = None) -> None:
149
+ def plot(self, wavelength: Optional[units.Quantity] = None) -> None:
150
150
  """
151
151
  Plots the refractive index as a function of wavelength over a specified range.
152
152
 
153
153
  Parameters
154
154
  ----------
155
- wavelength : Optional[Quantity]
155
+ wavelength : Optional[units.Quantity]
156
156
  The range of wavelengths to plot, in meters. If not provided, the entire allowable wavelength range is used.
157
157
 
158
158
  Raises
@@ -174,7 +174,7 @@ class SellmeierMaterial(BaseMaterial):
174
174
  xlabel=r'Wavelength [$\mu$m]',
175
175
  title=f"Refractive Index vs. Wavelength: [{self.filename}]"
176
176
  )
177
- ax.plot(wavelength.to(micrometer).magnitude, refractive_index.real, linewidth=2, label='Real Part')
177
+ ax.plot(wavelength.to(units.micrometer).magnitude, refractive_index.real, linewidth=2, label='Real Part')
178
178
  ax.legend()
179
179
 
180
180
  plt.show()
@@ -8,7 +8,7 @@ from PyOptik.directories import tabulated_data_path
8
8
  from PyOptik.material.base_class import BaseMaterial
9
9
  from MPSPlots.styles import mps
10
10
  import matplotlib.pyplot as plt
11
- from PyOptik.units import Quantity, micrometer, meter
11
+ from PyOptik import units
12
12
 
13
13
 
14
14
 
@@ -82,19 +82,19 @@ class TabulatedMaterial(BaseMaterial):
82
82
  data_points = parsed_yaml['DATA'][0]['data'].strip().split('\n')
83
83
  data = numpy.array([[float(value) for value in point.split()] for point in data_points])
84
84
 
85
- self.wavelength = data[:, 0] * micrometer
85
+ self.wavelength = data[:, 0] * units.micrometer
86
86
  self.n_values = data[:, 1]
87
87
  self.k_values = data[:, 2]
88
88
  except (KeyError, IndexError, ValueError):
89
89
  raise ValueError(f"Invalid or missing data in YAML file {file_path}")
90
90
 
91
- self.wavelength_bound = [self.wavelength.min().magnitude, self.wavelength.max().magnitude] * micrometer
91
+ self.wavelength_bound = [self.wavelength.min().magnitude, self.wavelength.max().magnitude] * units.micrometer
92
92
 
93
93
  # Extract reference
94
94
  self.reference = parsed_yaml.get('REFERENCES', None)
95
95
 
96
96
  @BaseMaterial.ensure_units
97
- def compute_refractive_index(self, wavelength: Union[float, Quantity]) -> numpy.ndarray:
97
+ def compute_refractive_index(self, wavelength: Union[float, units.Quantity]) -> numpy.ndarray:
98
98
  """
99
99
  Interpolates the refractive index (n) and absorption (k) values for the given wavelength(s).
100
100
 
@@ -119,15 +119,15 @@ class TabulatedMaterial(BaseMaterial):
119
119
 
120
120
  self._check_wavelength(wavelength)
121
121
 
122
- n_interp = numpy.interp(wavelength.to(meter).magnitude, self.wavelength.to(meter).magnitude, self.n_values)
123
- k_interp = numpy.interp(wavelength.to(meter).magnitude, self.wavelength.to(meter).magnitude, self.k_values)
122
+ n_interp = numpy.interp(wavelength.to(units.meter).magnitude, self.wavelength.to(units.meter).magnitude, self.n_values)
123
+ k_interp = numpy.interp(wavelength.to(units.meter).magnitude, self.wavelength.to(units.meter).magnitude, self.k_values)
124
124
 
125
125
  index = n_interp + 1j * k_interp
126
126
 
127
127
  return index[0] if return_as_scalar else index
128
128
 
129
129
  @BaseMaterial.ensure_units
130
- def plot(self, wavelength: Optional[Quantity] = None) -> None:
130
+ def plot(self, wavelength: Optional[units.Quantity] = None) -> None:
131
131
  """
132
132
  Plots the tabulated refractive index (n) and absorption (k) as a function of wavelength.
133
133
 
@@ -152,7 +152,7 @@ class TabulatedMaterial(BaseMaterial):
152
152
  ylabel='Refractive Index (n)',
153
153
  )
154
154
 
155
- ax1.plot(wavelength.to(micrometer).magnitude, n_values, 'o-', color='tab:blue', label='n')
155
+ ax1.plot(wavelength.to(units.micrometer).magnitude, n_values, 'o-', color='tab:blue', label='n')
156
156
 
157
157
  ax2 = ax1.twinx()
158
158
 
@@ -161,7 +161,7 @@ class TabulatedMaterial(BaseMaterial):
161
161
  ylabel='Absorption (k)',
162
162
  )
163
163
 
164
- ax2.plot(wavelength.to(micrometer).magnitude, k_values, 'o-', color='tab:red', label='k')
164
+ ax2.plot(wavelength.to(units.micrometer).magnitude, k_values, 'o-', color='tab:red', label='k')
165
165
 
166
166
  plt.show()
167
167
 
@@ -6,7 +6,8 @@ pint.set_application_registry(ureg)
6
6
 
7
7
  # Define a list of base units to scale
8
8
  BASE_UNITS = [
9
- 'meter'
9
+ 'meter',
10
+ 'second'
10
11
  ]
11
12
 
12
13
  # Define prefixes for scaling units
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyOptik
3
- Version: 1.11.0
3
+ Version: 1.12.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
@@ -92,6 +92,7 @@ Features
92
92
  - **Simulation Ready**: Ideal for light-matter interaction simulations, particularly in optics and photonics.
93
93
  - **Simple API**: Easy-to-use API that integrates well with other Python libraries.
94
94
  - **Open Source**: Fully open-source.
95
+ - **Group Index and Velocity**: Compute group index and group velocity directly from material objects.
95
96
 
96
97
  Installation
97
98
  ************
@@ -174,6 +175,10 @@ After installing PyOptik and building the material library, you can easily acces
174
175
  bk7 = MaterialBank.BK7
175
176
  n = bk7.compute_refractive_index(0.55e-6)
176
177
  print(f"Refractive index at 0.55 µm: {n}")
178
+ # Group index and group velocity
179
+ n_g = bk7.compute_group_index(0.55e-6)
180
+ v_g = bk7.compute_group_velocity(0.55e-6)
181
+ print(f"Group index: {n_g:.3f}, group velocity: {v_g:.1f}")
177
182
 
178
183
  Example
179
184
  *******
@@ -89,6 +89,7 @@ docs/source/_static/thumbnail.png
89
89
  docs/source/gallery/index.rst
90
90
  tests/__init__.py
91
91
  tests/test_base_material_decorator.py
92
+ tests/test_group_properties.py
92
93
  tests/test_material_bank_extra.py
93
94
  tests/test_sellmeier.py
94
95
  tests/test_tabulated.py
@@ -33,6 +33,7 @@ Features
33
33
  - **Simulation Ready**: Ideal for light-matter interaction simulations, particularly in optics and photonics.
34
34
  - **Simple API**: Easy-to-use API that integrates well with other Python libraries.
35
35
  - **Open Source**: Fully open-source.
36
+ - **Group Index and Velocity**: Compute group index and group velocity directly from material objects.
36
37
 
37
38
  Installation
38
39
  ************
@@ -115,6 +116,10 @@ After installing PyOptik and building the material library, you can easily acces
115
116
  bk7 = MaterialBank.BK7
116
117
  n = bk7.compute_refractive_index(0.55e-6)
117
118
  print(f"Refractive index at 0.55 µm: {n}")
119
+ # Group index and group velocity
120
+ n_g = bk7.compute_group_index(0.55e-6)
121
+ v_g = bk7.compute_group_velocity(0.55e-6)
122
+ print(f"Group index: {n_g:.3f}, group velocity: {v_g:.1f}")
118
123
 
119
124
  Example
120
125
  *******
@@ -73,6 +73,7 @@ testpaths = [
73
73
  "tests/test_tabulated.py",
74
74
  "tests/test_usual_materials.py",
75
75
  "tests/test_utils.py",
76
+ "tests/test_group_properties.py",
76
77
  ]
77
78
  addopts = [
78
79
  '-v',
@@ -0,0 +1,27 @@
1
+ import numpy as np
2
+ import pytest
3
+ from PyOptik import MaterialBank
4
+ from PyOptik.units import micrometer, meter, ureg
5
+
6
+
7
+ def test_group_index_sellmeier():
8
+ bk7 = MaterialBank.BK7
9
+ gi = bk7.compute_group_index(0.8 * micrometer)
10
+ assert gi.magnitude > 0.0
11
+
12
+
13
+ def test_group_velocity_tabulated():
14
+ si = MaterialBank.silicon
15
+ gv = si.compute_group_velocity(0.6 * micrometer)
16
+ c = 299792458 * meter / ureg.second
17
+ assert gv < c
18
+
19
+
20
+ def test_group_index_array():
21
+ water = MaterialBank.water
22
+ wavelengths = np.linspace(0.5, 0.6, 3) * micrometer
23
+ gi = water.compute_group_index(wavelengths)
24
+ assert gi.shape == wavelengths.shape
25
+
26
+ if __name__ == "__main__":
27
+ pytest.main(["-W error", "-s", __file__])
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes