def test_conic_surface(): # Prove that with a conic surface we can focus parallel rays perfectly. n1 = 1 n2 = 1.5 f = 1 roc = f * (n2 - n1) / n2 x0s = [-0.2, -0.1, 0, 0.1, 0.2] # There is a formula for this: # https://www.iap.uni - jena.de/iapmedia/de/Lecture/Advanced + Lens + Design1393542000/ALD13_Advanced + Lens + Design + 7 + _ + Aspheres + and +freeforms.pdf # but I obtained it numerically (in demo_conic_surface.py). kappa = 0.55555 f = roc * n2 / (n2 - n1) interface = rt1.FresnelInterface(ri.FixedIndex(n1), ri.FixedIndex(n2)) conic_surface = rt1.Surface(rt1.ConicProfile(roc, kappa), interface=interface) origin = v4hb.stack_xyzw(x0s, 0, -1, 1) vector = v4hb.stack_xyzw(0, 0, 1, 0) detector_surface = rt1.Surface(rt1.PlanarProfile(), matrix=h4t.make_translation(0, 0, f)) surfaces = conic_surface, detector_surface line = rt1.Line(origin, vector) pol = v4hb.cross(line.vector, [0, 1, 0, 0]) ray = rt1.Ray(line, pol, 1, 0, 860e-9, n1) segments = ray.trace_surfaces(surfaces, ['transmitted', 'incident'])[0] assert len(segments) == 3 xy = segments[-1].ray.line.origin[..., :2] # The focusing is close (f number 2.5) but not quite perfect due to errors in the intersection solver. assert np.allclose(xy, 0, atol=2e-6)
def test_pbg_calc_field(): origin = v4hb.stack_xyzw(0, 0, 0, 1) vector = v4hb.stack_xyzw(0, 0, 1, 0) axis1 = v4hb.normalize(v4hb.stack_xyzw(1, 1j, 0.5j, 0)) lamb = 860e-9 k = 2*np.pi/lamb waist = 100e-6 z_R = np.pi*waist**2/lamb z_waist = 1*z_R mode = pbg.Mode.make(rt1.Line(origin, vector), axis1, lamb, waist, z_waist)[0] z = np.linspace(-z_R*16, z_R*16, 200)[:, None] x = np.arange(3)[:, None, None]*waist #zv, xv = [array.ravel() for array in np.broadcast_arrays(zs, xs)] points = v4hb.concatenate_xyzw(x, 0, z, 1) field, phi_axis, grad_phi = mode.calc_field(k, points, calc_grad_phi=True) psis = field*mathx.expj(-z*k) psis_true = beams.FundamentalGaussian(lamb, w_0=waist, flux=1).E(z - z_waist, x)*np.exp( -1j*np.arctan(z_waist/z_R)) assert np.allclose(psis, psis_true) if 0: # Useful for testing in IPython. glw = pg.GraphicsLayoutWidget() absz_plot = glw.addAlignedPlot() glw.nextRows() phase_plot = glw.addAlignedPlot() for x, color, psi, psi_true in zip(xs, pg.tableau10, psis.T, psis_true.T): absz_plot.plot(zs[:, 0]*1e3, abs(psi), pen=color) absz_plot.plot(zs[:, 0]*1e3, abs(psi_true), pen=pg.mkPen(color, style=pg.DashLine)) phase_plot.plot(zs[:, 0]*1e3, np.angle(psi), pen=color) phase_plot.plot(zs[:, 0]*1e3, np.angle(psi_true), pen=pg.mkPen(color, style=pg.DashLine)) glw.show()
def test_reflect_Surface(): s = rt1.Surface(rt1.PlanarProfile(), interface=rt1.Mirror()) s.rotate_y(np.pi / 4) line = rt1.Line((0, 0, -1, 1), (0, 0, 1, 0)) pol = v4hb.cross(line.vector, [0, 1, 0, 0]) ray = rt1._raytrace.Ray(line, pol, 0, 860e-9, 1) segments = ray.trace_surfaces([s], ['reflected'])[0] assert len(segments) == 2 assert np.allclose(segments[-1].ray.line.vector, (-1, 0, 0, 0))
def test_make_spherical_lens_surfaces(): roc1 = 100 roc2 = 50 d = 30 n = 1.5 f, h1, h2 = paraxial.calc_thick_spherical_lens(n, roc1, -roc2, d) surfaces = rt1.make_spherical_lens_surfaces(roc1, -roc2, d, ri.FixedIndex(n)) line = rt1.Line((0, 0, -f + h1 - d / 2, 1), v4hb.normalize((1e-4, 1e-4, 1, 0))) pol = v4hb.cross(line.vector, [0, 1, 0, 0]) ray = rt1.Ray(line, pol, 0, 860e-9, 1) segments = ray.trace_surfaces(surfaces, ['transmitted'] * 2)[0] assert len(segments) == 3 assert segments[1].ray.n == n assert np.allclose(segments[-1].ray.line.vector, (0, 0, 1, 0))
def test_rt_pgl(qtbot): surface = rt1.Surface(rt1.PlanarProfile()) line = rt1.Line((0, 0, -1, 1), (0, 0, 1, 0)) segments = otk.rt1._raytrace.Ray(line, [1, 0, 0, 0], 0, 860e-9, 1).trace_surfaces((surface, ), ['incident']) widget = rtpgl.plot_surfaces((surface, )) qtbot.addWidget(widget) item = rtpgl.ParentItem() item.add_surface(surface) rtpgl.SegmentsItem(segments, item) widget = pgl.GLViewWidget() widget.addItem(item) qtbot.addWidget(widget)
def test_pbg_project_field(): # Define a fundamental Gaussian beam point along z axis. lamb = 860e-9 k = 2*np.pi/lamb waist = 10e-6 flux = 2 beam = beams.FundamentalGaussian(lamb=lamb, w_0=waist, flux=flux) z_waist = beam.z_R # Put waist of Gaussian at one Rayleigh range. z = 2*beam.z_R # Sample at two Rayleigh ranges. y = np.linspace(-0.5, 0.5, 16)[:, None]*6*waist x = np.linspace(-0.5, 0.5, 16)[:, None, None]*6*waist Er = beam.E(z - z_waist, (x**2 + y**2)**0.5)*np.exp(1j*k*z) Er *= np.exp(1j*beam.Gouy(-z_waist)) # Want phase at origin to be zero for comparison below. # Define a set of PBGs of different angles with same waist plane as Er. origin = v4hb.stack_xyzw(0, 0, 0, 1) thetay = np.linspace(-0.5, 0.5, 3)[:, None]*6*lamb/(np.pi*waist) thetax = np.linspace(-0.5, 0.5, 3)[:, None, None]*6*lamb/(np.pi*waist) vector = v4hb.normalize(v4hb.concatenate_xyzw(thetax, thetay, 1, 0)) axis1 = v4hb.normalize(v4hb.stack_xyzw(1, 0, 0, 0)) mode_bundle = pbg.Mode.make(rt1.Line(origin, vector), axis1, lamb, waist, z_waist)[0] flux_, phi_axis_origin_, projected_field = mode_bundle.project_field(k, v4hb.concatenate_xyzw(x, y, z, 1), Er) coefficients = flux_**0.5 * np.exp(1j*phi_axis_origin_) testing.assert_allclose(coefficients, np.asarray([[0, 0, 0], [0, flux**0.5, 0], [0, 0, 0]])[:, :, None], atol=1e-10) # TODO restore me # def test_pbg_collimate(qtbot): # lamb = 860e-9 # waist = 10e-6 # n1 = 1.5 # n2 = 3 # f = 0.1 # surface = rt.Surface(rt.SphericalProfile(f*(n2 - n1)), interface=rt.FresnelInterface(ri.FixedIndex(n1), ri.FixedIndex(n2))) # line_base = otk.rt.lines.Line([0, 0, -f*n1, 1], [0, 0, 1, 0]) # beam0 = pbg.Beam.make(line_base, [1, 0, 0, 0], lamb, waist, [1,0,0,0], 1, n=n1) # surfaces = (surface, ) # segments = pbg.trace_surfaces(surfaces, ['transmitted'], beam0) # assert len(segments) == 2 # beam1 = segments[1].beam # assert beam1.n == n2 # assert np.isclose(beam1.flux, abs(omath.calc_fresnel_coefficients(n1, n2, 1)[1][0])**2*n2/n1) # for surface_index in range(2): # TODO fix this # widget = segments[-1].make_profile_widget(0) # qtbot.addWidget(widget)
def test_refraction(): """Test collimation of a point source by a spherical refracting surface.""" n1 = 1.5 n2 = 3 f = 100 r0 = np.asarray((100, 20, 300, 1)) interface = rt1.FresnelInterface(ri.FixedIndex(n1), ri.FixedIndex(n2)) s = rt1.Surface(rt1.SphericalProfile(f * (n2 - n1)), otk.h4t.make_translation(*r0[:3]), interface=interface) origin = r0 + (0, 0, -f * n1, 0) line = rt1.Line(origin, v4hb.normalize((0.001, 0.001, 1, 0))) pol = v4hb.cross(line.vector, [0, 1, 0, 0]) ray = rt1.Ray(line, pol, 0, 860e-9, n1) segments = ray.trace_surfaces((s, ), ('transmitted', ))[0] assert len(segments) == 2 assert segments[-1].ray.n == n2 assert np.allclose(segments[-1].ray.line.vector, (0, 0, 1, 0))