def littrow(): """ Trace rectangular beam into OPG in Littrow. 400 nm groove period 8.4 m groove convergence """ #Set up beam rays = sources.rectArray(50., 50., 1e2) #Trace to Littrow and diffract tran.transform(rays, 0, 0, 0, 0, 52.28 * np.pi / 180, 0) surf.flat(rays) tran.transform(rays, 0, 8400., 0, 0, 0, 0) tran.radgrat(rays, 400. / 8400., 1, 632.8) #Steer out beam tilt tran.steerX(rays) tran.steerY(rays) #Bring rays to common plane surf.flat(rays) #Get wavefront r = anal.wavefront(rays, 200, 200) return r
def wolterprimarynode(rays,r0,z0,psi=1.): """Place Wolter node at current origin, focus at (-r0,0,-z0) """ tran.transform(rays,-r0,0,-z0,0,0,0) wolterprimary(rays,r0,z0,psi) tran.itransform(rays,-r0,0,-z0,0,0,0) return
def focus(rays,fn,weights=None,nr=None,coords=None): dz1 = fn(rays,weights=weights) tran.transform(rays,0,0,dz1,0,0,0,coords=coords) flat(rays,nr=nr) dz2 = fn(rays,weights=weights) tran.transform(rays,0,0,dz2,0,0,0,coords=coords) flat(rays,nr=nr) return dz1+dz2
def plotNodeSpacing(rsec,smax,pmin,fun,nodegap,L=200.,pbeam=True): """ Plot mirror positions and beam extent for each mirror node """ plt.figure('Nodes') plt.clf() for i in range(len(smax)): for r in rsec[i]: #Mirror parameters z = np.sqrt(1e4**2-r**2) psi = np.polyval(fun[i],r) psi = np.max([.01,psi]) #Plot mirrors rp1 = wsPrimrad(pmin[i]+L,r,z,psi) rp2 = wsPrimrad(pmin[i],r,z,psi) rs1 = wsSecrad(smax[i],r,z,psi) rs2 = wsSecrad(smax[i]-L,r,z,psi) plt.plot([rp1,rp2],[pmin[i]+L,pmin[i]],'k') plt.plot([rs1,rs2],[smax[i],smax[i]-L],'k') if np.where(r==rsec[i])[0] == 136: pdb.set_trace() if pbeam is True: #Plot beam #Set up ray ray = sources.pointsource(0.,1) ray[6] = -ray[6] ray[1][0] = rp1 tran.transform(ray,0,0,-1e4,0,0,0) #Trace to shell surf.wsPrimary(ray,r,z,psi) tran.reflect(ray) surf.wsSecondary(ray,r,z,psi) tran.reflect(ray) rb1 = ray[1][0] z1 = ray[3][0] #Set up ray ray = sources.pointsource(0.,1) ray[6] = -ray[6] ray[1][0] = rp2 tran.transform(ray,0,0,-1e4,0,0,0) #Trace to shell surf.wsPrimary(ray,r,z,psi) tran.reflect(ray) surf.wsSecondary(ray,r,z,psi) tran.reflect(ray) rb2 = ray[1][0] z2 = ray[3][0] plt.plot([rp1,rp1,rb1,0],[1e4+500.,pmin[i]+L,z1,0],'b--') plt.plot([rp2,rp2,rb2,0],[1e4+500.,pmin[i],z2,0],'b--') return None
def make_xou_source(clock_angle, wave, N, source_dist): prays = source.subannulus(700, 740, 0.10, N, zhat=-1.) tran.transform(prays, 0., 0., 0., 0., 0., clock_angle - pi / 2) tran.pointTo(prays, 0., mean([705, 745]), source_dist, reverse=1) if type(wave) == float: wavedist = zeros(N) + wave else: wavedist = wave.draw_waves(N) xou_rays = ArcRays.ArcusRays(prays, wavedist) return xou_rays
def tanSphere(rays,rad,nr=None): """ Wrapper for spherical surface placed tangent to XY plane Positive radius of curvature curves toward the +Z direction """ #Go to center of curvature tran.transform(rays,0,0,rad,0,0,0) #Place sphere sphere(rays,rad,nr=nr) #Go back to tangent plane tran.transform(rays,0,0,-rad,0,0,0) return
def wsSecrad(z,r0,z0,psi=1.): """ Determine radius of WS primary """ #Set up ray ray = sources.pointsource(0.,1) tran.transform(ray,0,0,0,0,-np.pi/2,0) tran.transform(ray,-r0-2.,0,-z,0,0,0) surf.wsSecondary(ray,r0,z0,psi) return ray[1][0]
def trace_gwat(gwat_xous=gwat_xous, gwat_facets=gwat_facets, order=order, wave=wave, N=10**5, diff_focus_zloc=None): # Tracing from the source through the SPO MMs. gwat_rays = gwatf.make_gwat_source(N, wave, gwathw.source_dist, gwathw.clock_angles) spomm_rays = ArcSPO.SPOPetalTrace(gwat_rays, gwat_xous) # I'm now doing this rather than what's embedded in the facet calculation. Is it bad? Time will tell. # Computing the SPO focus characteristics, the focal length, and the effective radius. focused_spo_rays, dz = gwatf.bring_rays_to_disp_focus(spomm_rays) xFocus, yFocus, zFocus = array( [mean(focused_spo_rays.x), mean(focused_spo_rays.y), -dz]) # Now creating a saved version of the SPO MM rays (spomm_rays) and readying a set of rays # referenced to the SPO focus for tracing. system_spo_rays = copy.deepcopy(spomm_rays) prays = system_spo_rays.yield_prays() tran.transform(prays, xFocus, yFocus, -zFocus, 0., 0., 0.) system_spo_rays.set_prays(prays) # Setting the GWAT order in accordance with this function for "order selection". gwatf.set_gwat_order(order, facets=gwat_facets) # And now tracing the rays through the adjusted CAT petal. grat_rays = ArcCAT.CATPetalTrace(system_spo_rays, gwat_facets) ## Focusing the diffracted rays. #meas_rays = copy.deepcopy(grat_rays) #prays = meas_rays.yield_prays() #surf.focusX(prays) #meas_rays.set_prays(prays) # Cleaning up and naming everything appropriately. system_spo_rays = system_spo_rays system_grat_rays = grat_rays system_spo_focused_rays, spo_dz = gwatf.bring_rays_to_disp_focus( system_spo_rays) if diff_focus_zloc is None: system_diff_rays, diff_focus_zloc = gwatf.bring_rays_to_disp_focus( system_grat_rays) prays = system_diff_rays.yield_prays() tran.transform(prays, 0., 0., -diff_focus_zloc, 0., 0., 0) system_diff_rays.set_prays(prays) else: system_diff_rays = copy.deepcopy(system_grat_rays) prays = system_diff_rays.yield_prays() tran.transform(prays, 0., 0., diff_focus_zloc, 0., 0., 0) surf.flat(prays) tran.transform(prays, 0., 0., -diff_focus_zloc, 0., 0., 0) system_diff_rays.set_prays(prays) return system_spo_rays, system_grat_rays, system_spo_focused_rays, system_diff_rays, diff_focus_zloc
def littrow(): """ Trace rectangular beam into OPG in Littrow. 400 nm groove period 8.4 m groove convergence """ #Set up beam rays = sources.rectArray(50., 50., 1e2) #Trace to Littrow and diffract tran.transform(rays, 0, 0, 0, 0, 52.28 * np.pi / 180, 0) surf.flat(rays) tran.transform(rays, 0, 8400., 0, 0, 0, 0) tran.radgrat(rays, 400. / 8400., 1, 632.8) #Steer out beam tilt tran.steerX(rays) tran.steerY(rays) #Bring rays to common plane surf.flat(rays) #Interpolate slopes to regular grid y, dx, dy = anal.interpolateVec(rays, 5, 200, 200) x, dx, dy = anal.interpolateVec(rays, 4, 200, 200) #Prepare arrays for integration #Reconstruct requires nans be replaced by 100 #Fortran functions require arrays to be packed in #fortran contiguous mode x = man.padRect(x) y = man.padRect(y) phase = np.zeros(np.shape(x), order='F') phase[np.isnan(x)] = 100. x[np.isnan(x)] = 100. y[np.isnan(y)] = 100. y = np.array(y, order='F') x = np.array(x, order='F') #Reconstruct and remove border phase = reconstruct.reconstruct(x, y, 1e-12, dx, phase) phase[phase == 100] = np.nan x[x == 100] = np.nan y[y == 100] = np.nan return man.stripnans(phase), man.stripnans(x), man.stripnans(y)
def ellipsoidPrimary(rays,R0,F,S,psi): """ Trace rays to the primary of an ellipsoid-hyperboloid telescope. Call at focus, just like with Wolter-I """ #Compute ellipsoid parameters P,a,b,e,f = con.ellipsoidFunction(S,psi,R0,F) R = b**2/a #Move to vertex tran.transform(rays,0,0,F+f-P-a,0,0,0) #Call conic conic(rays,R,-e**2) #Go back to focus tran.itransform(rays,0,0,F+f-P-a,0,0,0) return
def testTransverseSecondary(r0, z0, zeta=1., offz=0., dx=0.): """ Launch rays perpendicular to optical axis toward mirror. """ #Set up source rays = sources.rectbeam(z0, r0, 1e4) tran.transform(rays, 0, 0, 0, 0, np.pi / 2, 0) tran.transform(rays, -r0 + dx, 0, -z0, 0, 0, 0) #Apply offaxis angle rays[6] = rays[6] + offz rays[4] = -np.sqrt(1 - rays[6]**2) #Trace to primary zi = np.copy(rays[3]) yi = np.copy(rays[2]) surf.wsSecondary(rays, r0, z0, zeta) return rays, yi, zi
def testNormalSecondary(r0, z0, zeta=1., offx=0., dz=0.): """ Launch a slit of rays toward the mirror from infinity. Return the """ #Set up source rays = sources.circularbeam(r0 * 2, 1e4) tran.transform(rays, 0, 0, -z0 + dz, 0, 0, 0) #Apply offaxis angle rays[4] = rays[4] + offx rays[6] = -np.sqrt(1 - rays[4]**2) #Trace to primary xi = np.copy(rays[1]) yi = np.copy(rays[2]) surf.wsSecondary(rays, r0, z0, zeta) return rays, xi, yi
def onaxisMerit(pmin,smax,R0=220.,Z0=1e4,L=200.,psi=1.): """ Trace rays for a given shell and determine amount of rays vignetted """ #Set up aperture a0 = wsPrimrad(pmin,R0,Z0,psi) a1 = wsPrimrad(pmin+L,R0,Z0,psi) rays = sources.annulus(a0,a1,1e3) tran.transform(rays,0,0,-Z0,0,0,0) #Trace to primary surf.wsPrimary(rays,R0,Z0,psi) tran.reflect(rays) #Trace to secondary surf.wsSecondary(rays,R0,Z0,psi) #Determine fraction of rays vignetted try: return np.sum(np.logical_or(rays[3]<smax-L,rays[3]>smax)),np.mean(rays[3]) except: pdb.set_trace()
def traceZeta(pmin,R0=220.,Z0=1e4,psi=1.,offaxis=0.,L=200.,az=100.,pause=False): """ Set initial aperture based on height of bottom of mirror above node (pmin). Assume 100 mm long mirrors. Then, trace to secondary and mark smin and smax for where the rays strike. Then trace out off axis field positions and determine RMS and HPD vs angle. """ #Set up aperture a0 = wsPrimrad(pmin,R0,Z0,psi) a1 = wsPrimrad(pmin+L,R0,Z0,psi) rays = sources.subannulus(a0,a1,az/R0,1e4) tran.transform(rays,0,0,-Z0,0,0,0) #Trace to primary and add off-axis angle surf.wsPrimary(rays,R0,Z0,psi) rays[4] = rays[4]+np.sin(offaxis) rays[6] = -np.sqrt(1.-rays[4]**2) tran.reflect(rays) #Trace to secondary surf.wsSecondary(rays,R0,Z0,psi) tran.reflect(rays) smax = np.nanmax(rays[3]) smin = np.nanmin(rays[3]) if pause is True: pdb.set_trace() #Go to focus f = surf.focusI(rays) #Compute merit functions hpd = anal.hpd(rays) rms = anal.rmsCentroid(rays) return smin,smax,f,hpd,rms
def get_corner_throughput_frac(module_width=150 * u.mm): ''' Returns percentage of incident photons from optic that will not interact with gratings in the OGRE grating array and will instead make it to the central CCD. Parameters ---------- module_width : Quantity Total width of OGRE grating module, centered at x=0. Returns ------- throughput_frac : float Fraction of photons that do not interact with the OGRE grating array. ''' # Define rays. rays = ogre.create_rays() # Pass through optic. rays = ogre.ogre_mirror_module(rays, scatter='bg') # Move to center of OGRE grating module. z_cen = np.mean(np.concatenate((ogre.zg_cen_left, ogre.zg_cen_right))) trans.transform(rays, 0, 0, z_cen, 0, 0, 0) surfaces.flat(rays) # Find starting fraction. start_frac = len(rays[1]) # How many get through. ind = np.where(abs(rays[1]) > module_width.to('mm').value / 2)[0] return len(ind) / float(start_frac)
def traceSingleRay(rtrace,zexit,R0,Z0,zeta,rpos=False): """ Trace single ray through WS shell and return ray at a given exit aperture z position """ #Set up ray ray = sources.pointsource(0.,1) ray[6] = -ray[6] ray[1][0] = rtrace tran.transform(ray,0,0,-Z0,0,0,0) #Trace to shell surf.wsPrimary(ray,R0,Z0,zeta) tran.reflect(ray) surf.wsSecondary(ray,R0,Z0,zeta) tran.reflect(ray) if rpos is True: return ray[1][0],ray[3][0] #Go to exit aperture tran.transform(ray,0,0,zexit,0,0,0) surf.flat(ray) return ray
def ogre_simulation_one_channel(waves, orders, j=j, oa_misalign=oa_misalign, g_misalign=g_misalign, s_misalign=s_misalign, m_misalign=m_misalign, cen_width=5 * u.mm, rib_width=2 * u.mm, rib_num=3, edge_width=5. * u.mm, mod_width=150 * u.mm): ''' Simulate rays going through the OGRE spectrometer. This function will just simulate rays passing through the spectrometer with misalignments, but will not take throughput into consideration. A seperate function is needed to correct this output for throughput. Parameters ---------- waves : Quantity Array of wavelengths to simulate. Each wavelength in the array will be associated with one ray (100 wavelengths = 100 rays). orders : numpy.ndarray Diffraction orders associated with wavelengths passed. j : Quantity FWHM of the jitter throughout the observation. oa_misalign : g_misalign : s_misalign : m_misalign : Returns ------- rays : [opd, x, y, z, l, m, n, nx, ny, nz] Rays on the focal plane of the OGRE spectrometer. waves : Quantity Wavelengths corresponding to each simulated ray. orders : array Diffracted order of each simulated ray. ''' # Define initial rays. n = len(waves) rays = ogre.create_rays(10 * n) # Translate rays to center of optic assembly. rays[3] = np.ones(len(rays[1])) * oa_z_cen surfaces.flat(rays) # Misalign rays relative to optic assembly. trans.transform(rays, 0, 0, 0, oa_pitch, oa_yaw, 0) # Move rays to R_INT position. This is just a global offset. rays[3] = np.ones(len(rays[1])) * 3500. # Add jitter. xj = np.random.normal(0, j.to('rad').value, size=len(rays[4])) yj = np.random.normal(0, j.to('rad').value, size=len(rays[4])) rays[4] += xj rays[5] += yj rays[6] = np.sqrt(1 - rays[4]**2 - rays[5]**2) # Pass rays through optic. rays = ogre.ogre_mirror_module(rays, scatter='bg') # Randomly select indicies to keep based on count rate analysis. n_rays = len(rays[0]) rand_inds = np.random.choice(np.arange(n_rays, dtype=int), len(waves), replace=False) # Keep only those selected indicies. rays = [r[rand_inds] for r in rays] # Add random period error effect. rand_fact = np.random.normal(1, 0.000094, size=len(waves)) # Pass through grating moudle. rays, diff_ind = ogre.ogre_grating_module(rays, waves=waves * orders / rand_fact, g_misalign=g_misalign, s_misalign=s_misalign, m_misalign=m_misalign, return_diff_ind=True) # Keep only wavelength/orders that make it through grating module. waves = waves[diff_ind] orders = orders[diff_ind] # Occult rays that will hit ribs. rays, waves, orders = ogre.grating_rib_occultation(rays, waves=waves, orders=orders) # Transform coordinate system to be at center of rotation. trans.transform(rays, 0, 0, oa_z_cen, 0, 0, 0) # Propagate rays to misaligned plane, simulating center plane of optic assembly. surfaces.flat(rays) # Transform the rays back by the pitch angle to the optical axis coordinate system. trans.itransform(rays, 0, 0, 0, oa_pitch, oa_yaw, 0) # Put the rays back at the intersection plane of the ideal optic. rays[3] = np.ones(len(rays[3])) * oa_z_cen # Misalign in z-hat. trans.transform(rays, 0, 0, oa_z, 0, 0, 0) # Propagate to the focal plane. rays = ogre.ogre_focal_plane(rays, det_misalignments=[0, 0, 0, 0, 0, -det_z]) return rays, waves, orders
def tracePerfectXRS(L=200.,nodegap=50.,Nshell=1e3,energy=1000.,\ rough=1.,offaxis=0.,rrays=False,rnodes=False): """ Trace rays through a perfect Lynx design where all the shells are on the spherical principle surface, with zeta equal to unity. """ #Construct node positions rad = np.array([200.]) z = np.sqrt(1e4**2-rad[-1]**2) #Gap is projected radial shell plus thickness plus vignetting gap rout = wsPrimrad(z+L+nodegap/2.,rad[-1],z) gap = L*3e-3 + 0.4 #Establish radius vector rad = np.array([]) for sec in range(3): rout = 0. #First node position rad = np.append(rad,200.+(1300./3)*sec) #rguess = np.linspace( while rout+gap < 200.+(1300./3)*(sec+1)-10.: #Need to adjust this condition #Compute parameters for current node z = np.sqrt(1e4**2-rad[-1]**2) rout = wsPrimrad(z+L+nodegap/2.,rad[-1],z) rad = np.append(rad,rout+gap) rad = rad[:-1] if rnodes is True: return rad #Use radial nodes and trace Lynx, keeping track of effective area previousrho = 0. for r in rad: #Set up aperture z = np.sqrt(1e4**2-r**2) a0 = wsPrimrad(z+nodegap/2.,r,z) a1 = wsPrimrad(z+nodegap/2.+L,r,z) rays = sources.annulus(a0,a1,Nshell) tran.transform(rays,0,0,-z,0,0,0) #Set up weights (cm^2) weights = np.repeat((a1**2-a0**2) * np.pi / 100. / Nshell,Nshell) #Trace to primary surf.wsPrimary(rays,r,z,1.) rays[4] = rays[4]+np.sin(offaxis) rays[6] = -np.sqrt(1.-rays[4]**2) tran.reflect(rays) ang = anal.grazeAngle(rays) weights = weights*\ pol.computeReflectivities(ang,energy,rough,1,cons)[0] #Trace to secondary surf.wsSecondary(rays,r,z,1.) tran.reflect(rays) ang = anal.grazeAngle(rays) weights = weights*\ pol.computeReflectivities(ang,energy,rough,1,cons)[0] #Handle vignetting ind = np.logical_and(rays[3]>z-nodegap/2.-L,rays[3]<z-nodegap/2.) if sum(ind) == 0: pdb.set_trace() rays = tran.vignette(rays,ind=ind) weights = weights[ind] #Go to exit aperture and confirm rays don't - EDIT HERE! #hit back of previous shell tran.transform(rays,0,0,z-nodegap/2-L,0,0,0) surf.flat(rays) rho = np.sqrt(rays[1]**2+rays[2]**2) ind = rho > previousrho #if np.sum(ind)==0: #pdb.set_trace() if np.sum(~ind) > 100: print '%i rays hit back of shell' % np.sum(~ind) print r #pdb.set_trace() rays = tran.vignette(rays,ind=ind) weights = weights[ind] previousrho = wsSecrad(z-nodegap/2-L,r,z)+.4 #Go to focus try: surf.focusI(rays,weights=weights) except: pdb.set_trace() #Accumulate master rays try: mrays = [np.concatenate([mrays[ti],rays[ti]]) for ti in range(10)] mweights = np.concatenate([mweights,weights]) except: mrays = rays mweights = weights if rrays is True: return mrays,mweights return anal.hpd(mrays,weights=mweights)/1e4*180/np.pi*60**2,\ anal.rmsCentroid(mrays,weights=mweights)/1e4*180/np.pi*60**2,\ np.sum(mweights)
def get_grating_throughput_frac(mid_width=5 * u.mm, edge_support_width=5 * u.mm, grat_thickness=ogre.grating_thickness, rib_width=2 * u.mm, rib_num=3, module_width=150 * u.mm): ''' Returns percentage of incident photons from optic that will interact with gratings in the OGRE grating array. Parameters ---------- mid_width : Quantity Width between two grating stacks in grating module. edge_support_width : Quantity Width of left/right outside support in grating module. grat_thickness : Quantity Thickness of grating in OGRE grating stack. rib_width : Quantity Width of individual rib on wedged grating substrate. rib_num : Quantity Number of ribs on wedged grating substrate. module_width : Quantity Total width of OGRE grating module, centered at x=0. Returns ------- throughput_frac : float Fraction of photons that interact with gratings in the OGRE grating array. ''' # Create rays. rays = ogre.create_rays(n=1000000) # Pass them through the optic with Beckmann + Gaussian scatter. rays = ogre.ogre_mirror_module(rays, scatter='bg') # Move them to the mean grating center point. z_mean = (np.mean(ogre.zg_cen_left) + np.mean(ogre.zg_cen_right)) / 2 trans.transform(rays, 0, 0, z_mean.to('mm').value, 0, 0, 0) surfaces.flat(rays) # Define starting number. start_num = len(rays[0]) # Find photons that hit in between grating stacks. center_ind = np.where(np.abs(rays[1]) < mid_width.to('mm').value / 2)[0] # Find photons with x-positions g.t. maximal grating stack x-extent. outside_ind = np.where( np.abs(rays[1]) > (module_width / 2 - edge_support_width).to('mm').value)[0] # Find photons that hit ribs. grating_width = module_width / 2 - edge_support_width - mid_width / 2 # Find rib positions. rib_cen_positions = np.linspace( rib_width.to('mm').value / 2, (grating_width - rib_width / 2).to('mm').value, rib_num) * u.mm + mid_width / 2 rib_ind = np.array([], dtype=int) for rc in rib_cen_positions: ri = np.where((np.abs(rays[1]) > (rc - rib_width / 2).to('mm').value) & (np.abs(rays[1]) < (rc + rib_width / 2).to('mm').value))[0] rib_ind = np.concatenate((rib_ind, ri)) # Account grating thickness. thick_ind = np.array([], dtype=int) for r in ogre.rg_cen.to('mm').value: # Find which rays will hit grating thickness. ind = np.where((rays[2] < r) & (rays[2] > r - grat_thickness.to('mm').value))[0] # Add to array list. thick_ind = np.concatenate((thick_ind, ind)) # Combine all rays that will be occulted. occ_ind = np.concatenate((center_ind, outside_ind, rib_ind, thick_ind)) # Remove occulted rays. rays = [np.delete(r, occ_ind) for r in rays] # What is ending number? end_num = len(rays[1]) # print('Starting #: ' + str(start_num)) # print('Ending #: ' + str(end_num)) # Fraction of photons making it through? frac = float(end_num) / start_num return frac
def traceXRS(rsec,smax,pmin,fun,nodegap,L=200.,Nshell=1e3,energy=1000.,\ rough=1.,offaxis=0.,rrays=False): """ Using output from defineRx, trace the nodes in a Lynx design. Provide number of sections, and the zeta as a function of radius interpolation function. Calculate node radii iteratively, providing appropriate gaps between nodes in order to limit off-axis vignetting. """ gap = L*3e-3+0.4 #.4 mm glass thickness plus vignetting #Trace through all shells, computing reflectivity and geometric area #for each shell previousrho = [] for i in range(len(smax)): #Variable to store radial position of bottom of previous #secondary mirror previousrho.append(0.) for r in rsec[i]: #Determine zeta for this shell...must be at least .01 psi = np.polyval(fun[i],r) psi = np.max([.01,psi]) #Set up aperture z = np.sqrt(1e4**2-r**2) a0 = wsPrimrad(pmin[i],r,z,psi=psi) a1 = wsPrimrad(pmin[i]+L,r,z,psi=psi) rays = sources.annulus(a0,a1,Nshell) tran.transform(rays,0,0,-z,0,0,0) #Set up weights (cm^2) weights = np.repeat((a1**2-a0**2) * np.pi / 100. / Nshell,Nshell) #Trace to primary surf.wsPrimary(rays,r,z,psi) rays[4] = rays[4]+np.sin(offaxis) rays[6] = -np.sqrt(1.-rays[4]**2) tran.reflect(rays) ang = anal.grazeAngle(rays) weights = weights*\ pol.computeReflectivities(ang,energy,rough,1,cons)[0] #Trace to secondary surf.wsSecondary(rays,r,z,psi) tran.reflect(rays) ang = anal.grazeAngle(rays) weights = weights*\ pol.computeReflectivities(ang,energy,rough,1,cons)[0] #Handle vignetting ind = np.logical_and(rays[3]>smax[i]-L,rays[3]<smax[i]) if sum(ind) == 0: pdb.set_trace() rays = tran.vignette(rays,ind=ind) weights = weights[ind] #Go to exit aperture and confirm rays don't #hit back of previous shell tran.transform(rays,0,0,smax[i]-L,0,0,0) surf.flat(rays) rho = np.sqrt(rays[1]**2+rays[2]**2) ind = rho > previousrho[-1] #if np.sum(ind)==0: #pdb.set_trace() if np.sum(~ind) > 100: print '%i rays hit back of shell' % np.sum(~ind) print r,psi #pdb.set_trace() rays = tran.vignette(rays,ind=ind) weights = weights[ind] previousrho.append(wsSecrad(smax[i]-L,r,z,psi=psi)+.4) #Go to focus if rrays is False: tran.transform(rays,0,0,-smax[i]+L,0,0,0) surf.flat(rays) #Accumulate master rays try: mrays = [np.concatenate([mrays[ti],rays[ti]]) for ti in range(10)] mweights = np.concatenate([mweights,weights]) except: mrays = rays mweights = weights if rrays is True: return mrays,mweights,previousrho #Go to focus try: surf.focusI(rays,weights=weights) except: pdb.set_trace() return anal.hpd(mrays,weights=mweights)/1e4*180/np.pi*60**2,\ anal.rmsCentroid(mrays,weights=mweights)/1e4*180/np.pi*60**2,\ np.sum(mweights)
z_in = z0 + mirror_sep / 2 z_out = z_in + mirror_len r_in = conic.primrad(z_in, r0, z0) r_out = conic.primrad(z_out, r0, z0) # Define full angular width of subannulus. dphi = np.radians(30.) # # Define subannulus of rays. rays = sources.subannulus(r_in, r_out, dphi, 1000000) # rays = np.loadtxt('rays.txt') # Rotate so that dispersion direction is in the x-dimension. trans.transform(rays, 0, 0, 0, 0, 0, -np.pi / 2) # Find centroid of rays and move rays down to center of beamline. cen_optic = analyses.centroid(rays) trans.transform(rays, 0, cen_optic[1], 0, 0, 0, 0) trans.transform(rays, 0, -30, 0, 0, 0, 0) # Change ray direction cosines to emanate from source (48 m away). hyp = np.sqrt(L**2 + rays[1]**2 + rays[2]**2) l = rays[1] / hyp m = rays[2] / hyp n = -np.sqrt(1. - l**2 - m**2) rays = [rays[0], rays[1], rays[2], rays[3], l, m, n, rays[7], rays[8], rays[9]] # Shift rays back up.
# Define Wolter-I parameters. r0 = 165. # Radius at the intersection plane of primary/secondary. z0 = 3500. # mirror_len = 100. mirror_sep = 5. # Define inner & outer radii to create rays. rp_front = conic.primrad(z0 + mirror_sep / 2 + mirror_len, r0, z0) rp_back = conic.primrad(z0 + mirror_sep / 2, r0, z0) # Define initial rays in subannulus. rays = sources.subannulus(rp_back, rp_front, np.radians(30.), 100000) # Transform rays to intersection plane of optic. trans.transform(rays, 0, 0, -z0, 0, 0, 0) # Rotate 90 degrees so that diffraction occurs in x-axis. trans.transform(rays, 0, 0, 0, 0, 0, -np.radians(90.)) # Pass through primary. surfaces.wolterprimary(rays, r0, z0) trans.reflect(rays) # # Add some scatter. ogre.beckmann_scatter(rays, 0, 0, 1.48e-5) # Pass through secondary. surfaces.woltersecondary(rays, r0, z0) trans.reflect(rays)
z_in = z0 + mirror_sep / 2 z_out = z_in + mirror_length r_in = conic.primrad(z_in, r_int[0], z0) r_out = conic.primrad(z_out, r_int[-1], z0) # Define full angular width of subannulus. dphi = np.radians(30.) # Define subannulus of rays. rays = sources.subannulus(r_in, r_out, dphi, num) np.save('originalpyxfrays.npy', rays) # Rotate so that dispersion direction is in the x-dimension. trans.transform(rays, 0, 0, 0, 0, 0, -np.pi / 2) # Find centroid of rays and move rays down to center of beamline. cen_optic = analyses.centroid(rays) trans.transform(rays, 0, cen_optic[1], 0, 0, 0, 0) trans.transform(rays, 0, -30, 0, 0, 0, 0) # Change ray direction cosines to emanate from source (48 m away). hyp = np.sqrt(L**2 + rays[1]**2 + rays[2]**2) l = rays[1] / hyp m = rays[2] / hyp n = -np.sqrt(1. - l**2 - m**2) rays = [rays[0], rays[1], rays[2], rays[3], l, m, n, rays[7], rays[8], rays[9]] # Shift rays back up.