Open dominikonysz opened 1 year ago
Hello @dominikonysz, Sorry for the delay in responding. I've looked at your well documented issue and see a modeling problem and have a workaround to the lens not drawing problem.
The first is that add_surface inserts the surface after cur_surface. This is the convention, at least with CODE V. This is different than inserting an item into into a python list. So if you want to insert an element following lens 2, you would set_cur_surface to 4, the rear surface of lens 2.
The workaround for the lens not drawing problem is to use a method in the opm, rebuild_from_seq(). This is my "force rebuild on the element model" hammer that rebuilds everything from the current sequential model.
sm.set_cur_surface(4)
sm.add_surface([100, 5, 'N-LAK9', 'Schott'])
sm.add_surface([1000, 1])
opm.update_model()
opm.rebuild_from_seq()
Clearly, though, this is a bug and should be fixed. I haven't had a chance to test it on my dev version; if it works there, I'll report back.
Let me know if you have any questions on this. Thanks for using ray-optics. Mike Hayford
Hey @mjhoptics,
you're right about the modelling problem. That was a little oopsie in my example because I'm usually using a wrapper around the opm
that uses surface+1
to skip the object surface. Thank you for pointing that out anyway!
And I have tried out the rebuild_from_seq()
and that was exactly what I was looking for! I don't know how I missed that in my search with such a telling name.
Only thing I have noticed is that I need to call opm.rebuild_from_seq()
before opm.update_model()
if I remove surfaces because opm.update_model()
breaks otherwise:
File [/opt/homebrew/Caskroom/miniconda/base/envs/thesis/lib/python3.10/site-packages/rayoptics/optical/opticalmodel.py:338](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniconda/base/envs/thesis/lib/python3.10/site-packages/rayoptics/optical/opticalmodel.py:338), in OpticalModel.update_model(self, **kwargs)
334 if len(self['part_tree'].nodes_with_tag(tag='#element')) == 0:
335 elements_from_sequence(self['ele_model'], self['seq_model'],
336 self['part_tree'])
--> 338 self['ele_model'].update_model(**kwargs)
339 self['part_tree'].update_model(**kwargs)
340 if self.specsheet is None:
File [/opt/homebrew/Caskroom/miniconda/base/envs/thesis/lib/python3.10/site-packages/rayoptics/elem/elements.py:1997](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniconda/base/envs/thesis/lib/python3.10/site-packages/rayoptics/elem/elements.py:1997), in ElementModel.update_model(self, **kwargs)
1994 e.parent = None
1996 self.elements = elements
-> 1997 self.sequence_elements()
1999 src_model = kwargs.get('src_model', None)
2000 if src_model is not self:
...
2024 for e in self.elements:
2025 if hasattr(e, 'z_dir'):
-> 2026 e.z_dir = seq_model.z_dir[e.reference_idx()]
IndexError: list index out of range
I guess the cause is the same as for the other things so simply flipping the calls fixes that.
Thank you for your help!
Hello @dominikonysz, Sorry for the delay in responding. I've looked at your well documented issue and see a modeling problem and have a workaround to the lens not drawing problem.
The first is that add_surface inserts the surface after cur_surface. This is the convention, at least with CODE V. This is different than inserting an item into into a python list. So if you want to insert an element following lens 2, you would set_cur_surface to 4, the rear surface of lens 2.
The workaround for the lens not drawing problem is to use a method in the opm, rebuild_from_seq(). This is my "force rebuild on the element model" hammer that rebuilds everything from the current sequential model.
sm.set_cur_surface(4)
sm.add_surface([100, 5, 'N-LAK9', 'Schott'])
sm.add_surface([1000, 1])
opm.update_model()
opm.rebuild_from_seq()
Clearly, though, this is a bug and should be fixed. I haven't had a chance to test it on my dev version; if it works there, I'll report back.
Let me know if you have any questions on this. Thanks for using ray-optics. Mike Hayford
Hello @dominikonysz , I updated 2 fixes for adding and removing elements when add_surface() and remove() are used. It was mostly there, just needed to wire it together correctly. Thanks again for your reports, let me know if you still see issues with it. Thanks Mike Hayford
Hey @mjhoptics,
as far as I can tell your changes help with adding another lens into an "air gap" between two lenses. However, I'm still having a problem with introducing a new lens by splitting a lens in half and therefore first adding an air gap and then the first surface of the new lens. Here's another example to reproduce:
from rayoptics.environment import *
from matplotlib import pyplot as plt
opm = OpticalModel()
sm = opm.seq_model
osp = opm.optical_spec
osp['pupil'] = PupilSpec(osp, key=['object', 'pupil'], value=12.5)
osp['wvls'] = WvlSpec([('F', 0.5), (587.5618, 1.0), ('C', 0.5)], ref_wl=1)
max_field = 20
FLD = [1e-10, 0.5 * max_field, 0.75 * max_field, max_field]
osp["fov"] = FieldSpec(osp, key=["object", "angle"], value=max(FLD), flds=FLD)
sm.gaps[0].thi=1e10
sm.add_surface([0, 10, 'N-BK7', 'Schott'])
sm.add_surface([0, 10])
sm.add_surface([0, 10, 'N-BK7', 'Schott'])
sm.set_stop()
sm.add_surface([0, 10])
sm.add_surface([0, 10, 'N-BK7', 'Schott'])
sm.add_surface([0, 10])
opm.update_model()
plt.figure(
100,
FigureClass=InteractiveLayout,
opt_model=opm,
is_dark=True,
).plot()
plt.show()
sm.set_cur_surface(3)
sm.gaps[3].thi = 5
sm.add_surface([0, 1, 'air'])
sm.add_surface([0, 5, 'N-BK7', 'Schott'])
opm.update_model()
plt.figure(
100,
FigureClass=InteractiveLayout,
opt_model=opm,
is_dark=True,
).plot()
plt.show()
It's results in
compared to the result with the opm.rebuild_from_seq()
workaround:
Hi @dominikonysz, Yes, this is an (interesting) problem. This feels like less of a quick fix than a rethinking of elements_from_sequence. In the interim, I think whenever surface insertions or deletions cause modifications of existing elements, then using the rebuild_from_seq function is needed. Thanks for the report, hopefully the workaround is acceptable for now. Regards Mike Hayford
Hey @mjhoptics, Sorry, I completely forgot to answer. Yes, the workaround is perfectly sufficient for my needs right now. Thank you for looking into it
Hello Michael,
I'm currently having a problem with plotting an optical model after adding surfaces later on using
seq_model.add_surface(...)
. Here is an example using the Triplet example:So plotting the example optical model obviously works as expected:
but in the second plot the new lens (between the middle and last lens) is not shown although the rays are being traced correctly:
As far as I could see the new elements are not being added to the
part_tree
although the ids of the other elements are updated. I have also tried runningopm.update_model(build="rebuild")
but that didn't help unfortunately.Am I missing some step additional to the
opm.update_model()
or is there some other way to force the reload of thepart_tree
to correctly display the plot?