def __init__(self, s, seq, wave=standard_wavelength, num_pupil_points=100, stopsize=10, pilotbundle_solution=-1, pilotbundle_generation="complex", pilotbundle_delta_angle=1 * degree, pilotbundle_delta_size=0.1, pilotbundle_sampling_points=3, name="", kind="aimy", **kwargs): super(Aimy, self).__init__(name=name, kind=kind, **kwargs) self.field_raster = RectGrid() self.pupil_raster = RectGrid() self.stopsize = stopsize self.num_pupil_points = num_pupil_points self.wave = wave self.pilotbundle_solution = pilotbundle_solution self.pilotbundle_generation = pilotbundle_generation self.pilotbundle_delta_angle = pilotbundle_delta_angle self.pilotbundle_delta_size = pilotbundle_delta_size self.pilotbundle_sampling_points = pilotbundle_sampling_points self.update(s, seq)
def __init__(self, s, seq, wave=standard_wavelength, num_pupil_points=100, stopsize=10, pilotbundle_solution=-1, pilotbundle_generation="complex", pilotbundle_delta_angle=1 * degree, pilotbundle_delta_size=0.1, pilotbundle_sampling_points=3, name=""): # TODO: reduce arguments by summarizing pilotbundle # parameters into class super(Aimy, self).__init__(name=name) self.field_raster = RectGrid() self.pupil_raster = RectGrid() self.stopsize = stopsize self.num_pupil_points = num_pupil_points self.wave = wave self.pilotbundle_solution = pilotbundle_solution self.pilotbundle_generation = pilotbundle_generation self.pilotbundle_delta_angle = pilotbundle_delta_angle self.pilotbundle_delta_size = pilotbundle_delta_size self.pilotbundle_sampling_points = pilotbundle_sampling_points self.update(s, seq)
def bundles_step3(nrays=100, rpup=7.5, maxfield_deg=2.): """ Creates an array of collimated RayBundle objects for step 3. """ bundles = [] fields_rad = np.array([0, 0.5*np.sqrt(2), 1]) * maxfield_deg * pi / 180. (px, py) = RectGrid().getGrid(nrays) for field in fields_rad: starty = -30 * np.tan(field) # TODO: this step explicitly sets the pupil # so the stop position is ignored. Better get Aimy to run ... o = np.vstack((rpup*px, rpup*py + starty, np.zeros_like(px))) k = np.zeros_like(o) k[1, :] = np.sin(field) k[2, :] = np.cos(field) E0 = np.cross(k, canonical_ex, axisa=0, axisb=0).T bundles += [RayBundle(o, k, E0, wave=Fline)] bundles += [RayBundle(o, k, E0, wave=dline)] bundles += [RayBundle(o, k, E0, wave=Cline)] return bundles
def bundle(fpx, fpy, nrays=16, rpup=5): """ Creates a RayBundle * o is the origin - this is ok * k is the wave vector, i.e. direction; needs to be normalized * E0 is the polarization vector """ (px, py) = RectGrid().getGrid(nrays) #pts_on_first_surf = np.vstack((rpup*px, rpup*py, np.zeros_like(px))) pts_on_entrance_pupil = np.vstack( (rpup * px, rpup * py, np.ones(px.shape) * spd.psys.entpup)) o = np.concatenate([ fpx * spd.psys.field_size_obj() * np.ones([1,len(px)]), \ -fpy * spd.psys.field_size_obj() * np.ones([1,len(px)]), \ spd.psys.obj_dist() * np.ones([1,len(px)]) ], axis=0 ) k = (pts_on_entrance_pupil - o) normk = np.sqrt([np.sum(k * k, axis=0)]) k = k / (np.matmul(np.ones([3, 1]), normk)) E0 = np.cross(k, canonical_ex, axisa=0, axisb=0).T #wavelength is in [mm] return RayBundle(o, k, E0, wave=0.00058756), px, py
def __init__(self, s, seq, wave=standard_wavelength, num_pupil_points=100, stopsize=10, name="", kind="aimy", **kwargs): super(Aimy, self).__init__(name=name, kind=kind, **kwargs) self.field_raster = RectGrid() self.pupil_raster = RectGrid() self.stopsize = stopsize self.num_pupil_points = num_pupil_points self.wave = wave self.update(s, seq)
def bundle_step1(nrays=100, rpup=7.5): """ Creates an on-axis collimated RayBundle for step 1. """ (px, py) = RectGrid().getGrid(nrays) o = np.vstack((rpup*px, rpup*py, np.zeros_like(px))) k = np.zeros_like(o) k[2, :] = 1. # 2.*math.pi/wavelength E0 = np.cross(k, canonical_ex, axisa=0, axisb=0).T return RayBundle(o, k, E0, wave=dline)
def __init__(self, s, seq, wave=standard_wavelength, num_pupil_points=100, stopsize=10, pilotbundle_solution=-1, pilotbundle_generation="complex", pilotbundle_delta_angle=1*degree, pilotbundle_delta_size=0.1, pilotbundle_sampling_points=3, name="", kind="aimy", **kwargs): super(Aimy, self).__init__(name=name, kind=kind, **kwargs) self.field_raster = RectGrid() self.pupil_raster = RectGrid() self.stopsize = stopsize self.num_pupil_points = num_pupil_points self.wave = wave self.pilotbundle_solution = pilotbundle_solution self.pilotbundle_generation = pilotbundle_generation self.pilotbundle_delta_angle = pilotbundle_delta_angle self.pilotbundle_delta_size = pilotbundle_delta_size self.pilotbundle_sampling_points = pilotbundle_sampling_points self.update(s, seq)
class Aimy(BaseLogger): """ Should take care about ray aiming (approximatively and real). Should generate aiming matrices and raybundles according to aiming specifications and field specifications. """ def __init__(self, s, seq, wave=standard_wavelength, num_pupil_points=100, stopsize=10, pilotbundle_solution=-1, pilotbundle_generation="complex", pilotbundle_delta_angle=1 * degree, pilotbundle_delta_size=0.1, pilotbundle_sampling_points=3, name=""): # TODO: reduce arguments by summarizing pilotbundle # parameters into class super(Aimy, self).__init__(name=name) self.field_raster = RectGrid() self.pupil_raster = RectGrid() self.stopsize = stopsize self.num_pupil_points = num_pupil_points self.wave = wave self.pilotbundle_solution = pilotbundle_solution self.pilotbundle_generation = pilotbundle_generation self.pilotbundle_delta_angle = pilotbundle_delta_angle self.pilotbundle_delta_size = pilotbundle_delta_size self.pilotbundle_sampling_points = pilotbundle_sampling_points self.update(s, seq) def setKind(self): self.kind = "aimy" def extract_abcd(self, xyuv): """ Extracts sub matrices from a general linear transfer matrix. """ self.debug(str(xyuv.shape)) a_xyuv = xyuv[0:2, 0:2] b_xyuv = xyuv[0:2, 2:4] # take only real part of the k vectors c_xyuv = xyuv[2:4, 0:2] d_xyuv = xyuv[2:4, 2:4] return (a_xyuv, b_xyuv, c_xyuv, d_xyuv) def update(self, system, seq): """ Update the matrices from object to stop and from stop to image for a specific system and a specific sequence. """ obj_dx = self.pilotbundle_delta_size # pilot bundle properties obj_dphi = self.pilotbundle_delta_angle # pilot bundle properties first_element_seq_name = seq[0] (first_element_name, first_element_seq) = first_element_seq_name (objsurfname, _) = first_element_seq[0] self.objectsurface = system.elements[first_element_name].\ surfaces[objsurfname] self.start_material = system.material_background # TODO: pilotray starts always in background (how about immersion?) # if mat is None: .... if self.pilotbundle_generation.lower() == "real": self.info("call real sampled pilotbundle") pilotbundles = build_pilotbundle( self.objectsurface, self.start_material, (obj_dx, obj_dx), (obj_dphi, obj_dphi), num_sampling_points=self.pilotbundle_sampling_points) # TODO: wavelength? elif self.pilotbundle_generation.lower() == "complex": self.info("call complex sampled pilotbundle") pilotbundles = build_pilotbundle_complex( self.objectsurface, self.start_material, (obj_dx, obj_dx), (obj_dphi, obj_dphi), num_sampling_points=self.pilotbundle_sampling_points) self.info("choose " + str(self.pilotbundle_solution) + " raybundle") self.pilotbundle = pilotbundles[self.pilotbundle_solution] # one of the last two (self.m_obj_stop, self.m_stop_img) =\ system.extractXYUV( self.pilotbundle, seq, pilotbundle_generation=self.pilotbundle_generation) self.info("show linear matrices") self.info( "obj -> stop:\n" + np.array_str(self.m_obj_stop, precision=10, suppress_small=True)) self.info( "stop -> img:\n" + np.array_str(self.m_stop_img, precision=10, suppress_small=True)) def aim_core_angle_known(self, theta2d): """ Calculates different start positions for the rays when direction vector is known. """ (thetax, thetay) = theta2d rmx = rodrigues(thetax, [0, 1, 0]) rmy = rodrigues(thetay, [1, 0, 0]) rmfinal = np.dot(rmy, rmx) dpilot_global = self.pilotbundle.returnKtoD()[0, :, 0] kpilot_global = self.pilotbundle.k[0, :, 0] dpilot_object = self.objectsurface.rootcoordinatesystem.\ returnGlobalToLocalDirections(dpilot_global)[:, np.newaxis] kpilot_object = self.objectsurface.rootcoordinatesystem.\ returnGlobalToLocalDirections(kpilot_global)[:, np.newaxis] kpilot_object = np.repeat(kpilot_object, self.num_pupil_points, axis=1) dvec = np.dot(rmfinal, dpilot_object) kvec = returnDtoK(dvec) # TODO: implement fake implementation dk_vec = kvec - kpilot_object dk_obj = dk_vec[0:2, :] (a_obj_stop, b_obj_stop, _, _) = self.extract_abcd(self.m_obj_stop) a_obj_stop_inv = np.linalg.inv(a_obj_stop) (xraster, yraster) = self.pupil_raster.getGrid(self.num_pupil_points) dr_stop = (np.vstack((xraster, yraster)) * self.stopsize) intermediate = np.dot(b_obj_stop, dk_obj) dr_obj = np.dot(a_obj_stop_inv, dr_stop - intermediate) return (dr_obj, dk_obj) def aim_core_k_known(self, dk_obj): """ Calculates different start position and angles when k-vector is known. """ (a_obj_stop, b_obj_stop, _, _) = self.extract_abcd(self.m_obj_stop) a_obj_stop_inv = np.linalg.inv(a_obj_stop) (xraster, yraster) = self.pupil_raster.getGrid(self.num_pupil_points) (num_points, ) = xraster.shape dr_stop = (np.vstack((xraster, yraster)) * self.stopsize) dk_obj2 = np.repeat(dk_obj[:, np.newaxis], num_points, axis=1) intermediate = np.dot(b_obj_stop, dk_obj2) dr_obj = np.dot(a_obj_stop_inv, dr_stop - intermediate) return (dr_obj, dk_obj2) def aim_core_r_known(self, delta_xy): """ Calculates different start position and angles when position at stop is known. """ (a_obj_stop, b_obj_stop, _, _) = self.extract_abcd(self.m_obj_stop) self.debug(str(b_obj_stop.shape)) b_obj_stop_inv = np.linalg.inv(b_obj_stop) (xraster, yraster) = self.pupil_raster.getGrid(self.num_pupil_points) (num_points, ) = xraster.shape dr_stop = (np.vstack((xraster, yraster)) * self.stopsize) dr_obj = np.repeat(delta_xy[:, np.newaxis], num_points, axis=1) dk_obj = np.dot(b_obj_stop_inv, dr_stop - np.dot(a_obj_stop, dr_obj)) # TODO: in general some direction vector is derived # TODO: this must been mapped to a k vector # TODO: what about anamorphic systems? return (dr_obj, dk_obj) def aim(self, delta_xy, fieldtype="angle"): """ Generates bundles. """ if fieldtype == "angle": (dr_obj, dk_obj) = self.aim_core_angle_known(delta_xy) elif fieldtype == "objectheight": (dr_obj, dk_obj) = self.aim_core_r_known(delta_xy) elif fieldtype == "kvector": # (dr_obj, dk_obj) = self.aim_core_k_known(delta_xy) raise NotImplementedError() else: raise NotImplementedError() (_, num_points) = np.shape(dr_obj) dr_obj3d = np.vstack((dr_obj, np.zeros(num_points))) dk_obj3d = np.vstack((dk_obj, np.zeros(num_points))) xp_objsurf = self.objectsurface.rootcoordinatesystem.\ returnGlobalToLocalPoints(self.pilotbundle.x[0, :, 0]) xp_objsurf = np.repeat(xp_objsurf[:, np.newaxis], num_points, axis=1) dx3d = np.dot(self.objectsurface.rootcoordinatesystem.localbasis.T, dr_obj3d) xparabasal = xp_objsurf + dx3d kp_objsurf = self.objectsurface.rootcoordinatesystem.\ returnGlobalToLocalDirections(self.pilotbundle.k[0, :, 0]) kp_objsurf = np.repeat(kp_objsurf[:, np.newaxis], num_points, axis=1) dk3d = np.dot(self.objectsurface.rootcoordinatesystem.localbasis.T, dk_obj3d) # FIXME: k coordinate system for which dispersion relation is respected # modified k in general violates dispersion relation kparabasal = kp_objsurf + dk3d efield_obj = self.pilotbundle.Efield[0, :, 0] efield_parabasal = np.repeat(efield_obj[:, np.newaxis], num_points, axis=1) # Eparabasal introduces anisotropy in aiming through # rotationally symmetric system since copy of Eparabasal (above) # is not in the right direction for the # dispersion relation (i.e. in isotropic media k perp E which is not # fulfilled); solution: use k, insert into propagator (svdmatrix), # calculate E by (u, sigma, v) = np.linalg.svd(propagator) where E is # some linearcombination of all u which belong to sigma = 0 values. # This is necessary to get the right ray direction also in isotropic # case # Outstanding problems: # * Only vacuum considered (attach to material!) # [i.e. svdmatrix should come from material] # * Selection of E depends only on smallest eigenvalue # (this is the "I don't care about polarization variant") # => Later the user should choose the polarization in an stable # reproducible way (i.e. sorting by scalar products) (_, nlength) = kparabasal.shape kronecker = np.repeat(np.identity(3)[np.newaxis, :, :], nlength, axis=0) svdmatrix = -kronecker * np.sum(kparabasal * kparabasal, axis=0)[:, np.newaxis, np.newaxis] +\ np.einsum("i...,j...", kparabasal, kparabasal) +\ kronecker # epstensor # svdmatrix = -delta_ij (k*k) + k_i k_j + delta (unitary_arrays, singular_values, _) = np.linalg.svd(svdmatrix) smallest_absolute_values = np.argsort(np.abs(singular_values), axis=1).T[0] for i in range(nlength): efield_parabasal[:, i] =\ unitary_arrays[i, :, smallest_absolute_values[i]] # Aimy: returns only linearized results which are not exact return RayBundle(xparabasal, kparabasal, efield_parabasal, wave=self.wave)
class Aimy(BaseLogger): """ Should take care about ray aiming (approximatively and real). Should generate aiming matrices and raybundles according to aiming specifications and field specifications. """ def __init__(self, s, seq, wave=standard_wavelength, num_pupil_points=100, stopsize=10, pilotbundle_solution=-1, pilotbundle_generation="complex", pilotbundle_delta_angle=1 * degree, pilotbundle_delta_size=0.1, pilotbundle_sampling_points=3, name=""): super(Aimy, self).__init__(name=name) self.field_raster = RectGrid() self.pupil_raster = RectGrid() self.stopsize = stopsize self.num_pupil_points = num_pupil_points self.wave = wave self.pilotbundle_solution = pilotbundle_solution self.pilotbundle_generation = pilotbundle_generation self.pilotbundle_delta_angle = pilotbundle_delta_angle self.pilotbundle_delta_size = pilotbundle_delta_size self.pilotbundle_sampling_points = pilotbundle_sampling_points self.update(s, seq) def setKind(self): self.kind = "aimy" def extractABCD(self, xyuv): self.debug(str(xyuv.shape)) Axyuv = xyuv[0:2, 0:2] Bxyuv = xyuv[0:2, 2:4] # take only real part of the k vectors Cxyuv = xyuv[2:4, 0:2] Dxyuv = xyuv[2:4, 2:4] return (Axyuv, Bxyuv, Cxyuv, Dxyuv) def update(self, s, seq): obj_dx = self.pilotbundle_delta_size # pilot bundle properties obj_dphi = self.pilotbundle_delta_angle # pilot bundle properties first_element_seq_name = seq[0] (first_element_name, first_element_seq) = first_element_seq_name (objsurfname, objsurfoptions) = first_element_seq[0] self.objectsurface = s.elements[first_element_name].surfaces[ objsurfname] self.start_material = s.material_background # TODO: pilotray starts always in background (how about immersion?) # if mat is None: .... if self.pilotbundle_generation.lower() == "real": self.info("call real sampled pilotbundle") pilotbundles = build_pilotbundle( self.objectsurface, self.start_material, (obj_dx, obj_dx), (obj_dphi, obj_dphi), num_sampling_points=self.pilotbundle_sampling_points) # TODO: wavelength? elif self.pilotbundle_generation.lower() == "complex": self.info("call complex sampled pilotbundle") pilotbundles = build_pilotbundle_complex( self.objectsurface, self.start_material, (obj_dx, obj_dx), (obj_dphi, obj_dphi), num_sampling_points=self.pilotbundle_sampling_points) self.info("choose " + str(self.pilotbundle_solution) + " raybundle") self.pilotbundle = pilotbundles[self.pilotbundle_solution] # one of the last two (self.m_obj_stop, self.m_stop_img) = s.extractXYUV( self.pilotbundle, seq, pilotbundle_generation=self.pilotbundle_generation) self.info("show linear matrices") self.info( "obj -> stop:\n" + np.array_str(self.m_obj_stop, precision=10, suppress_small=True)) self.info( "stop -> img:\n" + np.array_str(self.m_stop_img, precision=10, suppress_small=True)) def aim_core_angle_known(self, theta2d): """ knows about xyuv matrices """ (thetax, thetay) = theta2d rmx = rodrigues(thetax, [0, 1, 0]) rmy = rodrigues(thetay, [1, 0, 0]) rmfinal = np.dot(rmy, rmx) dpilot_global = self.pilotbundle.returnKtoD()[0, :, 0] kpilot_global = self.pilotbundle.k[0, :, 0] dpilot_object = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalDirections( dpilot_global)[:, np.newaxis] kpilot_object = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalDirections( kpilot_global)[:, np.newaxis] kpilot_object = np.repeat(kpilot_object, self.num_pupil_points, axis=1) d = np.dot(rmfinal, dpilot_object) k = returnDtoK(d) # TODO: implement fake implementation dk = k - kpilot_object dk_obj = dk[0:2, :] (A_obj_stop, B_obj_stop, C_obj_stop, D_obj_stop) = self.extractABCD(self.m_obj_stop) A_obj_stop_inv = np.linalg.inv(A_obj_stop) (xp, yp) = self.pupil_raster.getGrid(self.num_pupil_points) dr_stop = (np.vstack((xp, yp)) * self.stopsize) intermediate = np.dot(B_obj_stop, dk_obj) dr_obj = np.dot(A_obj_stop_inv, dr_stop - intermediate) return (dr_obj, dk_obj) def aim_core_k_known(self, dk_obj): """ knows about xyuv matrices """ (A_obj_stop, B_obj_stop, C_obj_stop, D_obj_stop) = self.extractABCD(self.m_obj_stop) A_obj_stop_inv = np.linalg.inv(A_obj_stop) (xp, yp) = self.pupil_raster.getGrid(self.num_pupil_points) (num_points, ) = xp.shape dr_stop = (np.vstack((xp, yp)) * self.stopsize) dk_obj2 = np.repeat(dk_obj[:, np.newaxis], num_points, axis=1) intermediate = np.dot(B_obj_stop, dk_obj2) dr_obj = np.dot(A_obj_stop_inv, dr_stop - intermediate) return (dr_obj, dk_obj2) def aim_core_r_known(self, delta_xy): (A_obj_stop, B_obj_stop, C_obj_stop, D_obj_stop) = self.extractABCD(self.m_obj_stop) self.debug(str(B_obj_stop.shape)) B_obj_stop_inv = np.linalg.inv(B_obj_stop) (xp, yp) = self.pupil_raster.getGrid(self.num_pupil_points) (num_points, ) = xp.shape dr_stop = (np.vstack((xp, yp)) * self.stopsize) dr_obj = np.repeat(delta_xy[:, np.newaxis], num_points, axis=1) dk_obj = np.dot(B_obj_stop_inv, dr_stop - np.dot(A_obj_stop, dr_obj)) # TODO: in general some direction vector is derived # TODO: this must been mapped to a k vector # TODO: what about anamorphic systems? return (dr_obj, dk_obj) def aim(self, delta_xy, fieldtype="angle"): """ Generates bundles. """ if fieldtype == "angle": (dr_obj, dk_obj) = self.aim_core_angle_known(delta_xy) elif fieldtype == "objectheight": (dr_obj, dk_obj) = self.aim_core_r_known(delta_xy) elif fieldtype == "kvector": # (dr_obj, dk_obj) = self.aim_core_k_known(delta_xy) raise NotImplementedError() else: raise NotImplementedError() (dim, num_points) = np.shape(dr_obj) dr_obj3d = np.vstack((dr_obj, np.zeros(num_points))) dk_obj3d = np.vstack((dk_obj, np.zeros(num_points))) xp_objsurf = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalPoints( self.pilotbundle.x[0, :, 0]) xp_objsurf = np.repeat(xp_objsurf[:, np.newaxis], num_points, axis=1) dx3d = np.dot(self.objectsurface.rootcoordinatesystem.localbasis.T, dr_obj3d) xparabasal = xp_objsurf + dx3d kp_objsurf = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalDirections( self.pilotbundle.k[0, :, 0]) kp_objsurf = np.repeat(kp_objsurf[:, np.newaxis], num_points, axis=1) dk3d = np.dot(self.objectsurface.rootcoordinatesystem.localbasis.T, dk_obj3d) # FIXME: k coordinate system for which dispersion relation is respected # modified k in general violates dispersion relation kparabasal = kp_objsurf + dk3d self.debug("E pilotbundle") self.debug(str(self.pilotbundle.Efield.shape)) self.debug(str(self.pilotbundle.Efield)) E_obj = self.pilotbundle.Efield[0, :, 0] self.debug("E_obj") self.debug(str(E_obj)) Eparabasal = np.repeat(E_obj[:, np.newaxis], num_points, axis=1) self.debug(str(np.sum(kparabasal * Eparabasal, axis=0))) # FIXME: Efield introduces anisotropy in aiming through # rotationally symmetric system # since copy of Eparabasal is not in the right direction for the # dispersion relation (i.e. in isotropic media k perp E which is not # fulfilled); solution: use k, insert into propagator, calculate # E by (u, sigma, v) = np.linalg.svd(propagator) where E is # linearcombination of all u which belong to sigma = 0 values. # This is necessary to get the right ray direction also in isotropic # case # Aimy: returns only linearized results which are not exact return RayBundle(xparabasal, kparabasal, Eparabasal, wave=self.wave)
class Aimy(BaseLogger): """ Should take care about ray aiming (approximatively and real). Should generate aiming matrices and raybundles according to aiming specifications and field specifications. """ def __init__(self, s, seq, wave=standard_wavelength, num_pupil_points=100, stopsize=10, name="", kind="aimy", **kwargs): super(Aimy, self).__init__(name=name, kind=kind, **kwargs) self.field_raster = RectGrid() self.pupil_raster = RectGrid() self.stopsize = stopsize self.num_pupil_points = num_pupil_points self.wave = wave self.update(s, seq) def extractABCD(self, xyuv): self.info(str(xyuv.shape)) Axyuv = xyuv[0:2, 0:2] Bxyuv = xyuv[0:2, 2:4] # take only real part of the k vectors Cxyuv = xyuv[2:4, 0:2] Dxyuv = xyuv[2:4, 2:4] return (Axyuv, Bxyuv, Cxyuv, Dxyuv) def update(self, s, seq): obj_dx = 0.1 # pilot bundle properties obj_dphi = 1. * degree # pilot bundle properties first_element_seq_name = seq[0] (first_element_name, first_element_seq) = first_element_seq_name (objsurfname, objsurfoptions) = first_element_seq[0] self.objectsurface = s.elements[first_element_name].surfaces[ objsurfname] self.start_material = s.material_background # TODO: pilotray starts always in background (how about immersion?) # if mat is None: .... #build_pilotbundle( # self.objectsurface, # self.start_material, # (obj_dx, obj_dx), # (obj_dphi, obj_dphi), # num_sampling_points=3) # TODO: wavelength? self.info("call complex sampled pilotbundle") pilotbundles = build_pilotbundle_complex(self.objectsurface, self.start_material, (obj_dx, obj_dx), (obj_dphi, obj_dphi), num_sampling_points=3) self.info("choose last raybundle (hard coded)") self.pilotbundle = pilotbundles[-1] # TODO: one solution selected hard coded (self.m_obj_stop, self.m_stop_img) = s.extractXYUV(self.pilotbundle, seq) self.info("show linear matrices") self.info( np.array_str(self.m_obj_stop, precision=5, suppress_small=True)) self.info( np.array_str(self.m_stop_img, precision=5, suppress_small=True)) def aim_core_angle_known(self, theta2d): """ knows about xyuv matrices """ (thetax, thetay) = theta2d rmx = rodrigues(thetax, [0, 1, 0]) rmy = rodrigues(thetay, [1, 0, 0]) rmfinal = np.dot(rmy, rmx) dpilot_global = self.pilotbundle.returnKtoD()[0, :, 0] kpilot_global = self.pilotbundle.k[0, :, 0] dpilot_object = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalDirections( dpilot_global)[:, np.newaxis] kpilot_object = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalDirections( kpilot_global)[:, np.newaxis] kpilot_object = np.repeat(kpilot_object, self.num_pupil_points, axis=1) d = np.dot(rmfinal, dpilot_object) k = returnDtoK(d) # TODO: implement fake implementation dk = k - kpilot_object dk_obj = dk[0:2, :] (A_obj_stop, B_obj_stop, C_obj_stop, D_obj_stop) = self.extractABCD(self.m_obj_stop) A_obj_stop_inv = np.linalg.inv(A_obj_stop) (xp, yp) = self.pupil_raster.getGrid(self.num_pupil_points) dr_stop = (np.vstack((xp, yp)) * self.stopsize) intermediate = np.dot(B_obj_stop, dk_obj) dr_obj = np.dot(A_obj_stop_inv, dr_stop - intermediate) return (dr_obj, dk_obj) def aim_core_k_known(self, dk_obj): """ knows about xyuv matrices """ (A_obj_stop, B_obj_stop, C_obj_stop, D_obj_stop) = self.extractABCD(self.m_obj_stop) A_obj_stop_inv = np.linalg.inv(A_obj_stop) (xp, yp) = self.pupil_raster.getGrid(self.num_pupil_points) dr_stop = (np.vstack((xp, yp)) * self.stopsize) dk_obj2 = np.repeat(dk_obj[:, np.newaxis], self.num_pupil_points, axis=1) intermediate = np.dot(B_obj_stop, dk_obj2) dr_obj = np.dot(A_obj_stop_inv, dr_stop - intermediate) return (dr_obj, dk_obj2) def aim_core_r_known(self, delta_xy): (A_obj_stop, B_obj_stop, C_obj_stop, D_obj_stop) = self.extractABCD(self.m_obj_stop) self.info(str(B_obj_stop.shape)) B_obj_stop_inv = np.linalg.inv(B_obj_stop) (xp, yp) = self.pupil_raster.getGrid(self.num_pupil_points) dr_stop = (np.vstack((xp, yp)) * self.stopsize) dr_obj = np.repeat(delta_xy[:, np.newaxis], self.num_pupil_points, axis=1) dk_obj = np.dot(B_obj_stop_inv, dr_stop - np.dot(A_obj_stop, dr_obj)) # TODO: in general some direction vector is derived # TODO: this must been mapped to a k vector # TODO: what about anamorphic systems? return (dr_obj, dk_obj) def aim(self, delta_xy, fieldtype="angle"): """ Generates bundles. """ if fieldtype == "angle": (dr_obj, dk_obj) = self.aim_core_angle_known(delta_xy) elif fieldtype == "objectheight": (dr_obj, dk_obj) = self.aim_core_r_known(delta_xy) elif fieldtype == "kvector": # (dr_obj, dk_obj) = self.aim_core_k_known(delta_xy) raise NotImplementedError() else: raise NotImplementedError() (dim, num_points) = np.shape(dr_obj) dr_obj3d = np.vstack((dr_obj, np.zeros(num_points))) dk_obj3d = np.vstack((dk_obj, np.zeros(num_points))) xp_objsurf = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalPoints( self.pilotbundle.x[0, :, 0]) xp_objsurf = np.repeat(xp_objsurf[:, np.newaxis], num_points, axis=1) dx3d = np.dot(self.objectsurface.rootcoordinatesystem.localbasis.T, dr_obj3d) xparabasal = xp_objsurf + dx3d kp_objsurf = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalDirections( self.pilotbundle.k[0, :, 0]) kp_objsurf = np.repeat(kp_objsurf[:, np.newaxis], num_points, axis=1) dk3d = np.dot(self.objectsurface.rootcoordinatesystem.localbasis.T, dk_obj3d) # TODO: k coordinate system for which dispersion relation is respected kparabasal = kp_objsurf + dk3d E_obj = self.pilotbundle.Efield[0, :, 0] Eparabasal = np.repeat(E_obj[:, np.newaxis], num_points, axis=1) # Aimy: returns only linearized results which are not exact return RayBundle(xparabasal, kparabasal, Eparabasal, wave=self.wave)
class Aimy(BaseLogger): """ Should take care about ray aiming (approximatively and real). Should generate aiming matrices and raybundles according to aiming specifications and field specifications. """ def __init__(self, s, seq, wave=standard_wavelength, num_pupil_points=100, stopsize=10, pilotbundle_solution=-1, pilotbundle_generation="complex", pilotbundle_delta_angle=1*degree, pilotbundle_delta_size=0.1, pilotbundle_sampling_points=3, name="", kind="aimy", **kwargs): super(Aimy, self).__init__(name=name, kind=kind, **kwargs) self.field_raster = RectGrid() self.pupil_raster = RectGrid() self.stopsize = stopsize self.num_pupil_points = num_pupil_points self.wave = wave self.pilotbundle_solution = pilotbundle_solution self.pilotbundle_generation = pilotbundle_generation self.pilotbundle_delta_angle = pilotbundle_delta_angle self.pilotbundle_delta_size = pilotbundle_delta_size self.pilotbundle_sampling_points = pilotbundle_sampling_points self.update(s, seq) def extractABCD(self, xyuv): self.debug(str(xyuv.shape)) Axyuv = xyuv[0:2, 0:2] Bxyuv = xyuv[0:2, 2:4] # take only real part of the k vectors Cxyuv = xyuv[2:4, 0:2] Dxyuv = xyuv[2:4, 2:4] return (Axyuv, Bxyuv, Cxyuv, Dxyuv) def update(self, s, seq): obj_dx = self.pilotbundle_delta_size # pilot bundle properties obj_dphi = self.pilotbundle_delta_angle # pilot bundle properties first_element_seq_name = seq[0] (first_element_name, first_element_seq) = first_element_seq_name (objsurfname, objsurfoptions) = first_element_seq[0] self.objectsurface = s.elements[first_element_name].surfaces[objsurfname] self.start_material = s.material_background # TODO: pilotray starts always in background (how about immersion?) # if mat is None: .... if self.pilotbundle_generation.lower() == "real": self.info("call real sampled pilotbundle") pilotbundles = build_pilotbundle( self.objectsurface, self.start_material, (obj_dx, obj_dx), (obj_dphi, obj_dphi), num_sampling_points=self.pilotbundle_sampling_points) # TODO: wavelength? elif self.pilotbundle_generation.lower() == "complex": self.info("call complex sampled pilotbundle") pilotbundles = build_pilotbundle_complex( self.objectsurface, self.start_material, (obj_dx, obj_dx), (obj_dphi, obj_dphi), num_sampling_points=self.pilotbundle_sampling_points) self.info("choose " + str(self.pilotbundle_solution) + " raybundle") self.pilotbundle = pilotbundles[self.pilotbundle_solution] # one of the last two (self.m_obj_stop, self.m_stop_img) = s.extractXYUV(self.pilotbundle, seq, pilotbundle_generation=self.pilotbundle_generation) self.info("show linear matrices") self.info("obj -> stop:\n" + np.array_str(self.m_obj_stop, precision=10, suppress_small=True)) self.info("stop -> img:\n" + np.array_str(self.m_stop_img, precision=10, suppress_small=True)) def aim_core_angle_known(self, theta2d): """ knows about xyuv matrices """ (thetax, thetay) = theta2d rmx = rodrigues(thetax, [0, 1, 0]) rmy = rodrigues(thetay, [1, 0, 0]) rmfinal = np.dot(rmy, rmx) dpilot_global = self.pilotbundle.returnKtoD()[0, :, 0] kpilot_global = self.pilotbundle.k[0, :, 0] dpilot_object = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalDirections(dpilot_global)[:, np.newaxis] kpilot_object = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalDirections(kpilot_global)[:, np.newaxis] kpilot_object = np.repeat(kpilot_object, self.num_pupil_points, axis=1) d = np.dot(rmfinal, dpilot_object) k = returnDtoK(d) # TODO: implement fake implementation dk = k - kpilot_object dk_obj = dk[0:2, :] (A_obj_stop, B_obj_stop, C_obj_stop, D_obj_stop) = self.extractABCD(self.m_obj_stop) A_obj_stop_inv = np.linalg.inv(A_obj_stop) (xp, yp) = self.pupil_raster.getGrid(self.num_pupil_points) dr_stop = (np.vstack((xp, yp))*self.stopsize) intermediate = np.dot(B_obj_stop, dk_obj) dr_obj = np.dot(A_obj_stop_inv, dr_stop - intermediate) return (dr_obj, dk_obj) def aim_core_k_known(self, dk_obj): """ knows about xyuv matrices """ (A_obj_stop, B_obj_stop, C_obj_stop, D_obj_stop) = self.extractABCD(self.m_obj_stop) A_obj_stop_inv = np.linalg.inv(A_obj_stop) (xp, yp) = self.pupil_raster.getGrid(self.num_pupil_points) (num_points,) = xp.shape dr_stop = (np.vstack((xp, yp))*self.stopsize) dk_obj2 = np.repeat(dk_obj[:, np.newaxis], num_points, axis=1) intermediate = np.dot(B_obj_stop, dk_obj2) dr_obj = np.dot(A_obj_stop_inv, dr_stop - intermediate) return (dr_obj, dk_obj2) def aim_core_r_known(self, delta_xy): (A_obj_stop, B_obj_stop, C_obj_stop, D_obj_stop) = self.extractABCD(self.m_obj_stop) self.debug(str(B_obj_stop.shape)) B_obj_stop_inv = np.linalg.inv(B_obj_stop) (xp, yp) = self.pupil_raster.getGrid(self.num_pupil_points) (num_points,) = xp.shape dr_stop = (np.vstack((xp, yp))*self.stopsize) dr_obj = np.repeat(delta_xy[:, np.newaxis], num_points, axis=1) dk_obj = np.dot(B_obj_stop_inv, dr_stop - np.dot(A_obj_stop, dr_obj)) # TODO: in general some direction vector is derived # TODO: this must been mapped to a k vector # TODO: what about anamorphic systems? return (dr_obj, dk_obj) def aim(self, delta_xy, fieldtype="angle"): """ Generates bundles. """ if fieldtype == "angle": (dr_obj, dk_obj) = self.aim_core_angle_known(delta_xy) elif fieldtype == "objectheight": (dr_obj, dk_obj) = self.aim_core_r_known(delta_xy) elif fieldtype == "kvector": # (dr_obj, dk_obj) = self.aim_core_k_known(delta_xy) raise NotImplementedError() else: raise NotImplementedError() (dim, num_points) = np.shape(dr_obj) dr_obj3d = np.vstack((dr_obj, np.zeros(num_points))) dk_obj3d = np.vstack((dk_obj, np.zeros(num_points))) xp_objsurf = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalPoints(self.pilotbundle.x[0, :, 0]) xp_objsurf = np.repeat(xp_objsurf[:, np.newaxis], num_points, axis=1) dx3d = np.dot(self.objectsurface.rootcoordinatesystem.localbasis.T, dr_obj3d) xparabasal = xp_objsurf + dx3d kp_objsurf = self.objectsurface.rootcoordinatesystem.returnGlobalToLocalDirections(self.pilotbundle.k[0, :, 0]) kp_objsurf = np.repeat(kp_objsurf[:, np.newaxis], num_points, axis=1) dk3d = np.dot(self.objectsurface.rootcoordinatesystem.localbasis.T, dk_obj3d) # FIXME: k coordinate system for which dispersion relation is respected # modified k in general violates dispersion relation kparabasal = kp_objsurf + dk3d self.debug("E pilotbundle") self.debug(str(self.pilotbundle.Efield.shape)) self.debug(str(self.pilotbundle.Efield)) E_obj = self.pilotbundle.Efield[0, :, 0] self.debug("E_obj") self.debug(str(E_obj)) Eparabasal = np.repeat(E_obj[:, np.newaxis], num_points, axis=1) self.debug(str(np.sum(kparabasal*Eparabasal, axis=0))) # FIXME: Efield introduces anisotropy in aiming through # rotationally symmetric system # since copy of Eparabasal is not in the right direction for the # dispersion relation (i.e. in isotropic media k perp E which is not # fulfilled); solution: use k, insert into propagator, calculate # E by (u, sigma, v) = np.linalg.svd(propagator) where E is # linearcombination of all u which belong to sigma = 0 values. # This is necessary to get the right ray direction also in isotropic # case # Aimy: returns only linearized results which are not exact return RayBundle(xparabasal, kparabasal, Eparabasal, wave=self.wave)