Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/improved zemax reader #38

Merged
merged 17 commits into from
Jan 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
69e8c78
fix: add wavelength range validation in AbbeMaterial class
HarrisonKramer Dec 9, 2024
f9c86c7
test: add unit test for wavelength out of bounds in AbbeMaterial class
HarrisonKramer Dec 9, 2024
5dbc41b
fix: handle comma as decimal separator in Zemax file reader
HarrisonKramer Dec 9, 2024
514b93c
feat: enhance LensInfoViewer to display AbbeMaterial properties
HarrisonKramer Dec 9, 2024
c8b7c39
Merge branch 'master' into feat/improved_zemax_reader
HarrisonKramer Dec 14, 2024
ffb3d52
Merge branch 'master' into feat/improved_zemax_reader
HarrisonKramer Dec 15, 2024
95e9ed4
Merge branch 'master' into feat/improved_zemax_reader
HarrisonKramer Dec 28, 2024
92f4b28
Merge branch 'master' into feat/improved_zemax_reader
HarrisonKramer Jan 9, 2025
6dd6639
Merge branch 'master' into feat/improved_zemax_reader
HarrisonKramer Jan 12, 2025
3b28480
feat: add support for reading additional Zemax file parameters
HarrisonKramer Jan 22, 2025
02ee335
feat: enhance ZemaxToOpticConverter to support vignette parameters an…
HarrisonKramer Jan 22, 2025
31bb583
test: add tests for reading vignette parameters in ZemaxFileReader
HarrisonKramer Jan 22, 2025
2b686dc
test: add test for configuring vignette fields in ZemaxFileReader
HarrisonKramer Jan 25, 2025
fed98a4
test: add test for configuring vignette decenter fields in ZemaxToOpt…
HarrisonKramer Jan 26, 2025
46ebbfd
test: add test to verify warning for LITHOTEC-CAF2 material
HarrisonKramer Jan 26, 2025
f419b83
chore: exclude generate_csv_database.py from test coverage
HarrisonKramer Jan 26, 2025
5044797
chore: remove coverage exclusion for generate_csv_database.py
HarrisonKramer Jan 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions optiland/fileio/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,30 @@ def _configure_fields(self):
Configure the fields for the optic.
"""
self.optic.set_field_type(field_type=self.data['fields']['type'])
for fx, fy in zip(self.data['fields']['x'], self.data['fields']['y']):
self.optic.add_field(x=fx, y=fy)

field_x = self.data['fields']['x']
field_y = self.data['fields']['y']

try:
vig_x = self.data['fields']['vignette_compress_x']
vig_y = self.data['fields']['vignette_compress_y']
except KeyError:
vig_x = [0.0] * len(field_x)
vig_y = [0.0] * len(field_y)

try:
dx = self.data['fields']['vignette_decenter_x']
dy = self.data['fields']['vignette_decenter_y']

# TODO: Implement decentering.
if any(dx) or any(dy):
print('Warning: Vignette decentering is not supported.')
except KeyError:
pass

for k in range(len(field_x)):
self.optic.add_field(x=field_x[k], y=field_y[k],
vx=vig_x[k], vy=vig_y[k])

def _configure_wavelengths(self):
"""
Expand Down
76 changes: 74 additions & 2 deletions optiland/fileio/zemax_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ def __init__(self, source):
'STOP': self._read_stop,
'MODE': self._read_mode,
'GCAT': self._read_glass_catalog,
'FWGN': self._read_field_weights,
'VDXN': self._read_vignette_decenter_x,
'VDYN': self._read_vignette_decenter_y,
'VCXN': self._read_vignette_compress_x,
'VCYN': self._read_vignette_compress_y,
'VANN': self._read_vignette_tangent_angle,
}

self._current_surf = -1
Expand Down Expand Up @@ -341,8 +347,8 @@ def _read_glass(self, data):
"""
material = data[1]
self._current_surf_data['material'] = material
self._current_surf_data['index'] = float(data[4])
self._current_surf_data['abbe'] = float(data[5])
self._current_surf_data['index'] = float(data[4].replace(',', '.'))
self._current_surf_data['abbe'] = float(data[5].replace(',', '.'))

# Generate a Material object from the material name & manufacturer
try:
Expand Down Expand Up @@ -427,3 +433,69 @@ def _read_surface_parameter(self, data):
"""
key = f'param_{int(data[1])-1}'
self._current_surf_data[key] = float(data[2])

def _read_field_weights(self, data):
"""
Extracts the field weights data.

Args:
data (list): List of data values extracted from the Zemax file.
"""
num_fields = self.data['fields']['num_fields']
self.data['fields']['weights'] = \
[float(value) for value in data[1:num_fields+1]]

def _read_vignette_decenter_x(self, data):
"""
Extracts the vignette decenter x data.

Args:
data (list): List of data values extracted from the Zemax file.
"""
num_fields = self.data['fields']['num_fields']
self.data['fields']['vignette_decenter_x'] = \
[float(value) for value in data[1:num_fields+1]]

def _read_vignette_decenter_y(self, data):
"""
Extracts the vignette decenter y data.

Args:
data (list): List of data values extracted from the Zemax file.
"""
num_fields = self.data['fields']['num_fields']
self.data['fields']['vignette_decenter_y'] = \
[float(value) for value in data[1:num_fields+1]]

def _read_vignette_compress_x(self, data):
"""
Extracts the vignette compress x data.

Args:
data (list): List of data values extracted from the Zemax file.
"""
num_fields = self.data['fields']['num_fields']
self.data['fields']['vignette_compress_x'] = \
[float(value) for value in data[1:num_fields+1]]

def _read_vignette_compress_y(self, data):
"""
Extracts the vignette compress y data.

Args:
data (list): List of data values extracted from the Zemax file.
"""
num_fields = self.data['fields']['num_fields']
self.data['fields']['vignette_compress_y'] = \
[float(value) for value in data[1:num_fields+1]]

def _read_vignette_tangent_angle(self, data):
"""
Extracts the vignette tangent angle data.

Args:
data (list): List of data values extracted from the Zemax file.
"""
num_fields = self.data['fields']['num_fields']
self.data['fields']['vignette_tangent_angle'] = \
[float(value) for value in data[1:num_fields+1]]
2 changes: 2 additions & 0 deletions optiland/materials/abbe.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ def n(self, wavelength):
Returns:
float: The refractive index of the material.
"""
if np.any(wavelength < 0.380) or np.any(wavelength > 0.750):
raise ValueError('Wavelength out of range for this model.')
return np.polyval(self._p, wavelength)

def k(self, wavelength):
Expand Down
42 changes: 42 additions & 0 deletions tests/test_fileio.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,36 @@ def test_read_surf_param(self, zemax_file_reader):
val = zemax_file_reader._current_surf_data['param_0']
assert val == 2

def test_read_vignette_decenter_x(self, zemax_file_reader):
data = ['VDXN', '1', '2']
zemax_file_reader._read_vignette_decenter_x(data)
val = zemax_file_reader.data['fields']['vignette_decenter_x']
assert val == [1, 2]

def test_read_vignette_decenter_y(self, zemax_file_reader):
data = ['VDYN', '1', '2']
zemax_file_reader._read_vignette_decenter_y(data)
val = zemax_file_reader.data['fields']['vignette_decenter_y']
assert val == [1, 2]

def test_read_vignette_compress_x(self, zemax_file_reader):
data = ['VCXN', '1', '2']
zemax_file_reader._read_vignette_compress_x(data)
val = zemax_file_reader.data['fields']['vignette_compress_x']
assert val == [1, 2]

def test_read_vignette_compress_y(self, zemax_file_reader):
data = ['VCYN', '1', '2']
zemax_file_reader._read_vignette_compress_y(data)
val = zemax_file_reader.data['fields']['vignette_compress_y']
assert val == [1, 2]

def test_read_vignette_tangent_angle(self, zemax_file_reader):
data = ['VANN', '1', '2']
zemax_file_reader._read_vignette_tangent_angle(data)
val = zemax_file_reader.data['fields']['vignette_tangent_angle']
assert val == [1, 2]


class TestZemaxToOpticConverter:
def test_generate_lens(self, zemax_file_reader):
Expand All @@ -259,6 +289,18 @@ def test_generate_lens_with_invalid_mode(self, zemax_file_reader):
with pytest.raises(ValueError, match='Unsupported surface type.'):
zemax_file_reader.generate_lens()

def test_configure_fields(self, zemax_file_reader):
vig = [0.5, 0.5, 0.5]
zemax_file_reader.data['fields']['vignette_compress_x'] = vig
zemax_file_reader.data['fields']['vignette_compress_y'] = vig
lens = zemax_file_reader.generate_lens()
assert lens.fields.get_vig_factor(Hx=0, Hy=1) == (0.5, 0.5)

def test_configure_fields_decenter(self, zemax_file_reader):
zemax_file_reader.data['fields']['vignette_decenter_x'] = [0.5]
zemax_file_reader.data['fields']['vignette_decenter_y'] = [0.5]
zemax_file_reader.generate_lens()


def test_save_load_json_obj():
mat = Material('SF11')
Expand Down
11 changes: 11 additions & 0 deletions tests/test_materials.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ def test_from_dict(self):
}
assert materials.Material.from_dict(material_dict).name == 'SF11'

def test_raise_warning(self):
materials.Material('LITHOTEC-CAF2') # prints a warning


@pytest.fixture
def abbe_material():
Expand Down Expand Up @@ -374,3 +377,11 @@ def test_abbe_from_dict():
abbe_material = materials.BaseMaterial.from_dict(abbe_dict)
assert abbe_material.index == 1.5
assert abbe_material.abbe == 50


def test_abbe_out_of_bounds_wavelength():
abbe_material = materials.AbbeMaterial(n=1.5, abbe=50)
with pytest.raises(ValueError):
abbe_material.n(0.3)
with pytest.raises(ValueError):
abbe_material.n(0.8)
Loading