def distortTrace(cone1,sag1,roc1,cone2,sag2,roc2,despace=0.,secondaryTilt=0.,\ nominal=True): """ Trace rays through a Wolter mirror pair with low order distortions. Distortions can be applied to either primary or secondary or both. axial sag, azimuthal sag, and cone angle are included. """ #Define ray subannulus r1 = surf.con.primrad(8600., 1000., 8400.) ang = 260. / 1000. #arc length over radius is angular extent rays = sources.subannulus(1000., r1, ang, 10**3) tran.transform(rays, 0, 0, 0, np.pi, 0, 0) #Point in -z tran.transform(rays, 0, 0, -10000, 0, 0, 0) #Converge from above #Trace to primary surf.primaryLL(rays,1000.,8400.,8600,8400,ang,[cone1,sag1,roc1],\ [1,2,0],[0,0,2]) #Vignette rays missing ind = np.logical_and(rays[3] < 8600., rays[3] > 8400.) rays = tran.vignette(rays, ind) numin = float(len(rays[1])) #Reflect tran.reflect(rays) #Apply secondary misalignment tran.transform(rays, surf.con.secrad(8300., 1000., 8400.), 0, 8300, 0, 0, 0) tran.transform(rays, 0, 0, despace, 0, secondaryTilt, 0) tran.itransform(rays, surf.con.secrad(8300., 1000., 8400.), 0, 8300, 0, 0, 0) #Trace to secondary surf.secondaryLL(rays,1000.,8400.,8400.,8200.,ang,[cone2,sag2,roc2],\ [1,2,0],[0,0,2]) #Vignette rays missing ind = np.logical_and(rays[3] < 8400., rays[3] > 8200.) rays = tran.vignette(rays, ind) numout = float(len(rays[1])) #Reflect tran.reflect(rays) #Reverse secondary misalignment tran.transform(rays, surf.con.secrad(8300., 1000., 8400.), 0, 8300, 0, 0, 0) tran.itransform(rays, 0, 0, despace, 0, secondaryTilt, 0) tran.itransform(rays, surf.con.secrad(8300., 1000., 8400.), 0, 8300, 0, 0, 0) #Go to focus if nominal is True: surf.flat(rays) else: surf.focusI(rays) #Return merit function return rays #anal.hpd(rays)/8400.,numout/numin
def findGratingPosition(N, hubdist=11832.911, order=1, wave=4.4, disp=0.): """Place the SPO pair, find the focus, and then go back up to grating placement """ #Set up SPO rays = traceSource(N) placeSPO(rays) #SPO intersection plane is global coordinate system #Go to focus gratc = [tran.tr.identity_matrix()] * 4 surf.focusI(rays, coords=gratc) #Go back up to grating point tran.transform(rays, 0, 0, np.mean(-11828.856 * rays[6]), 0, 0, 0, coords=gratc) surf.flat(rays) #Place grating #Get to XY centroid of beam, now at center of grating tran.transform(rays, np.mean(rays[1]), 0, 0, 0, 0, 0, coords=gratc) gratc2 = np.copy(gratc) #Rotate to proper incidence angle tran.steerX(rays, coords=gratc2) tran.transform(rays, 0, 0, 0, 0, pi / 2 - 1.5 * pi / 180, 0, coords=gratc2) surf.flat(rays) tran.transform(rays, 0, 0, 0, 0, 0, pi / 2, coords=gratc2) #Go to hub and diffract #Add yaw yaw = grat.blazeYaw(1.5 * pi / 180, 2.4, 3, 160.) tran.transform(rays, 0, 0, 0, 0, 0, yaw, coords=gratc2) tran.transform(rays, 0, -hubdist + disp, 0, 0, 0, 0, coords=gratc2) tran.reflect(rays) tran.radgrat(rays, 160. / hubdist, order, wave) pdb.set_trace() #Go back to reference frame of grating rays = tran.applyT(rays, gratc2, inverse=True) #Back to global #rays = tran.applyT(rays,gratc) #forward to grating #Go to focus focusc = [tran.tr.identity_matrix()] * 4 surf.focusY(rays, coords=focusc) #Get rid of mean X and Y tran.transform(rays,np.mean(rays[1]),np.mean(rays[2]),0,0,0,0,\ coords=focusc) return rays,[gratc[1][i][-1] for i in range(3)],\ [focusc[1][i][-1] for i in range(3)]
def pairRaytrace(secondaryTilt, despace): """Trace the distorted mirror pair. Assume no gap for now. Vignette rays that land outside active mirror areas.""" #Define ray subannulus r1 = surf.con.primrad(8600., 1000., 8400.) ang = 260. / 1000. #arc length over radius is angular extent rays = sources.subannulus(1000., r1, ang, 10**3) tran.transform(rays, 0, 0, 0, np.pi, 0, 0) #Point in -z tran.transform(rays, 0, 0, -10000, 0, 0, 0) #Converge from above #Trace to primary surf.primaryLL(rays, 1000., 8400., 8600, 8400, ang, res[0], res[2], res[1]) #Vignette rays missing ind = np.logical_and(rays[3] < 8600., rays[3] > 8400.) rays = tran.vignette(rays, ind) numin = float(len(rays[1])) #Reflect tran.reflect(rays) #Bring to midplane of despaced secondary #Apply secondary misalignment tran.transform(rays, surf.con.secrad(8300., 1000., 8400.), 0, 8300, 0, 0, 0) tran.transform(rays, 0, 0, despace, 0, secondaryTilt, 0) tran.itransform(rays, surf.con.secrad(8300., 1000., 8400.), 0, 8300, 0, 0, 0) #Trace to secondary surf.secondaryLL(rays, 1000., 8400., 8400., 8200., ang, res2[0], res2[2], res2[1]) #Vignette rays missing ind = np.logical_and(rays[3] < 8400., rays[3] > 8200.) rays = tran.vignette(rays, ind) numout = float(len(rays[1])) #Reflect tran.reflect(rays) #Reverse secondary misalignment tran.transform(rays, surf.con.secrad(8300., 1000., 8400.), 0, 8300, 0, 0, 0) tran.itransform(rays, 0, 0, despace, 0, secondaryTilt, 0) tran.itransform(rays, surf.con.secrad(8300., 1000., 8400.), 0, 8300, 0, 0, 0) #Go to focus surf.focusI(rays) #Get centroid cx, cy = anal.centroid(rays) #Return merit function return anal.rmsCentroid( rays) / 8400. * 180 / np.pi * 60**2, numout / numin, cx, cy
def singleOptic(N, misalign=np.zeros(6)): """Trace single primary mirror from SLF finite source distance. """ #Define some Wolter parameters r1 = conic.primrad(8600., 220., 8400.) dphi = 100. / 220. / 2 #Set up subannulus rays = sources.subannulus(220., r1, dphi * 1.25, N) ## #Set direction cosines ## srcdist = 89.61e3+(1.5e3-misalign[2]) ## raydist = sqrt(srcdist**2+\ ## (rays[1]-misalign[0])**2+\ ## (rays[2]-misalign[1])**2) ## l = (rays[1]-misalign[0])/raydist ## m = (rays[2]-misalign[1])/raydist ## n = -sqrt(1. - l**2 - m**2) ## rays = [rays[0],rays[1],rays[2],rays[3],l,m,n,rays[7],rays[8],rays[9]] #Go to mirror node and apply rotational misalignment tran.transform(rays, 220., 0, 0, misalign[3], misalign[4], misalign[5]) tran.transform(rays, -220., 0, 0, 0, 0, 0) #Place Wolter surfaces tran.transform(rays, 0, 0, -8400., 0, 0, 0) surf.wolterprimary(rays, 220., 8400.) tran.reflect(rays) #Vignette rays not landing in active mirror area indz = np.logical_and(rays[3] > 8426., rays[3] < 8526.) ind = np.logical_and(np.abs(rays[2]) < 50., indz) rays = tran.vignette(rays, ind=ind) #Go to focus surf.flat(rays) f = surf.focusI(rays) - 8400. return rays #anal.hpd(rays)/abs(f)*180/pi*60**2,abs(f)
def mirrorPair(N,srcdist=89.61e3+1.5e3,primalign=np.zeros(6),\ secalign=np.zeros(6),rrays=False,f=None,\ plist=[[0],[0],[0]],hlist=[[0],[0],[0]]): """ SLF finite source trace """ #Establish subannulus of rays rays = sources.subannulus(220., 221., 100. / 220., N, zhat=-1.) #Transform to node position tran.transform(rays, 220, 0, 0, 0, 0, 0) #Set up finite source distance raydist = sqrt(srcdist**2 + rays[1]**2 + rays[2]**2) rays[4] = rays[1] / raydist rays[5] = rays[2] / raydist rays[6] = -sqrt(1. - rays[4]**2 - rays[5]**2) #Place mirror pair coords = [tran.tr.identity_matrix()] * 4 tran.transform(rays,-220+conic.primrad(8450.,220.,8400.),0,50.,0,0,0,\ coords=coords) tran.transform(rays, *primalign, coords=coords) tran.transform(rays,-conic.primrad(8450.,220.,8400.),0,-8450.,0,0,0,\ coords=coords) ## surf.wolterprimary(rays,220.,8400.) surf.primaryLL(rays, 220., 8400., 8500., 8400., 100. / 220, *plist) rays = tran.vignette(rays,ind=np.logical_and(rays[3]<8500.,\ rays[3]>8400.)) tran.reflect(rays) #Place secondary in primary's reference frame tran.transform(rays,conic.secrad(8350.,220.,8400.),0,8350.,0,0,0,\ coords=coords) tran.transform(rays, *secalign, coords=coords) tran.itransform(rays,conic.secrad(8350.,220.,8400.),0,8350.,0,0,0,\ coords=coords) ## surf.woltersecondary(rays,220.,8400.) surf.secondaryLL(rays, 220., 8400., 1., 8400., 8300., 100. / 220, *hlist) rays = tran.vignette(rays,ind=np.logical_and(rays[3]<8400.,\ rays[3]>8300.)) tran.reflect(rays) #Go back to nominal node reference frame and down to focus rays = tran.applyT(rays, coords, inverse=True) if f is None: f = -surf.focusI(rays) print f else: tran.transform(rays, 0, 0, -f, 0, 0, 0) surf.flat(rays) if rrays is True: return rays return anal.hpd(rays)/f * 180/np.pi * 60.**2, \ airnp.mean(rays[1]), np.mean(rays[2])
def singleOptic2(n,misalign=np.zeros(6),srcdist=89.61e3+1.5e3,az=100.,\ returnRays=False,f=None,\ plist=[[0],[0],[0]],\ ax=100.): """Alternative SLF finite source trace""" #Establish subannulus of rays r0 = conic.primrad(8426., 220., 8400.) r1 = conic.primrad(8426. + ax, 220., 8400.) rays = sources.subannulus(r0, r1, az / 220., n, zhat=-1.) #Transform to node position tran.transform(rays, 220, 0, 0, 0, 0, 0) #Set up finite source distance raydist = sqrt(srcdist**2 + rays[1]**2 + rays[2]**2) l = rays[1] / raydist m = rays[2] / raydist n = -sqrt(1. - l**2 - m**2) rays = [ raydist, rays[1], rays[2], rays[3], l, m, n, rays[7], rays[8], rays[9] ] #Align perfectly to beam tran.steerX(rays) #Apply misalignment tran.transform(rays, *misalign) #Place mirror tran.transform(rays, -220., 0, -8400., 0, 0, 0) ## surf.wolterprimarynode(rays,220,8400.) surf.primaryLL(rays, 220., 8400., 8426. + ax, 8426., az / 220., *plist) rays = tran.vignette(rays,ind=np.logical_and(rays[3]<8400.+ax,\ rays[3]>8400.)) tran.itransform(rays, -220., 0., -8400., 0, 0, 0) #Vignette rays not landing in active mirror area ind = np.logical_and(rays[3] > 26., rays[3] < (26. + ax)) ## ind = np.logical_and(np.abs(rays[2])<az/2.,indz) rays = tran.vignette(rays, ind=ind) #Reverse misalignment tran.itransform(rays, *misalign) #Reflect and go to surface tran.reflect(rays) if f is None: f = surf.focusI(rays) else: tran.transform(rays, 0, 0, f, 0, 0, 0) surf.flat(rays) #Get centroid cx, cy = anal.centroid(rays) if returnRays is True: return rays return anal.hpd(rays) / abs(f) * 180 / pi * 60**2, f, cx
def singleEllipse(n,misalign=np.zeros(6),srcdist=89.61e3+1.5e3,az=100.,\ returnRays=False,f=None,\ plist=[[0],[0],[0]],\ ax=100.,psi=psiE): """Alternative SLF finite source trace""" #Establish subannulus of rays r0 = conic.primrad(8426., 220., 8400.) r1 = conic.primrad(8426. + ax, 220., 8400.) rays = sources.subannulus(r0, r1, az / 220., n, zhat=-1.) tran.pointTo(rays, 0., 0., srcdist, reverse=1.) #Transform to node position tran.transform(rays, 220, 0, 0, 0, 0, 0) #Apply misalignment tran.transform(rays, *misalign) #Place mirror tran.transform(rays, -220., 0, -8400., 0, 0, 0) ## surf.wolterprimarynode(rays,220,8400.) surf.ellipsoidPrimaryLL(rays,220.,8400.,srcdist,psi,8426.+ax,8426.,\ az/220.,*plist) tran.itransform(rays, -220., 0., -8400., 0, 0, 0) #Vignette rays not landing in active mirror area ind = np.logical_and(rays[3] > 26., rays[3] < (26. + ax)) ## ind = np.logical_and(np.abs(rays[2])<az/2.,indz) rays = tran.vignette(rays, ind=ind) #Reverse misalignment tran.itransform(rays, *misalign) #Reflect and go to surface tran.reflect(rays) if f is None: f = surf.focusI(rays) else: tran.transform(rays, 0, 0, f, 0, 0, 0) surf.flat(rays) #Get centroid cx, cy = anal.centroid(rays) if returnRays is True: return rays return anal.hpd(rays) / abs(f) * 180 / pi * 60**2 #,f,cx
def ellipsoidPair(N,srcdist=89.61e3+1.5e3,primalign=np.zeros(6),\ secalign=np.zeros(6),rrays=False,f=None,\ plist=[[0],[0],[0]],hlist=[[0],[0],[0]]): """ Trace an ellipsoid-hyperboloid telescope in SLF geometry. plist is [pcoeff,pax,paz] """ #Establish subannulus of rays r1 = conic.ellipsoidRad(srcdist, 1., 220., 8400., 8500.) rays = sources.subannulus(220., r1, 100. / 220., N, zhat=-1.) tran.pointTo(rays, 0, 0, srcdist, reverse=1.) ## #Transform to node position ## tran.transform(rays,220,0,0,0,0,0) ## #Set up finite source distance ## raydist = sqrt(srcdist**2+rays[1]**2+rays[2]**2) ## rays[4] = rays[1]/raydist ## rays[5] = rays[2]/raydist ## rays[6] = -sqrt(1.-rays[4]**2-rays[5]**2) #Place mirror pair coords = [tran.tr.identity_matrix()] * 4 prad = conic.ellipsoidRad(srcdist, 1., 220., 8400., 8450.) tran.transform(rays,prad,0,50.,0,0,0,\ coords=coords) tran.transform(rays, *primalign, coords=coords) tran.transform(rays,-prad,0,-8450.,0,0,0,\ coords=coords) surf.ellipsoidPrimaryLL(rays,220.,8400.,srcdist,1.,8500.,8400.,100./220,\ *plist) #Vignette any rays outside of active area rays = tran.vignette(rays,ind=np.logical_and(rays[3]<8500.,\ rays[3]>8400.)) ## surf.ellipsoidPrimary(rays,220.,8400.,srcdist,1.) tran.reflect(rays) #Place secondary in primary's reference frame srad = conic.ehSecRad(srcdist, 1., 220., 8400., 8350.) tran.transform(rays,srad,0,8350.,0,0,0,\ coords=coords) tran.transform(rays, *secalign, coords=coords) tran.itransform(rays,srad,0,8350.,0,0,0,\ coords=coords) ## surf.ellipsoidSecondary(rays,220.,8400.,srcdist,1.) surf.ellipsoidSecondaryLL(rays,220.,8400.,srcdist,1.,8400.,8300.,100./220,\ *hlist) rays = tran.vignette(rays,ind=np.logical_and(rays[3]<8400.,\ rays[3]>8300.)) ang = anal.grazeAngle(rays) tran.reflect(rays) #Go back to nominal node reference frame and down to focus rays = tran.applyT(rays, coords, inverse=True) if f is None: f = -surf.focusI(rays) print f else: tran.transform(rays, 0, 0, -f, 0, 0, 0) surf.flat(rays) if rrays is True: return rays return anal.hpd(rays) / f * 180 / np.pi * 60.**2
def reproduceChevron(num,rin=220.,axlength=100.,azwidth=50.,F=8.4e3,\ hubdist=8e3,radapprox=False,order=1,wave=.83,f=None,\ autofocus=False,returnMet=False,yaw=0.,N=1,\ gratalign=np.zeros(6)): #Create Wolter beam rout = conic.primrad(F+axlength,rin,F) rays = source.subannulus(rin,rout,azwidth/rin,num,zhat=-1.) surf.wolterprimary(rays,rin,F) tran.reflect(rays) surf.woltersecondary(rays,rin,F) tran.reflect(rays) tran.transform(rays,0,0,0,0,0,np.pi/2) #Go to focus surf.focusI(rays) #Steer beam coords = [tran.tr.identity_matrix()]*4 tran.transform(rays,0,0,0,np.mean(rays[5]),-np.mean(rays[4]),0) pdb.set_trace() #Go up to grating tran.transform(rays,0,0,hubdist/np.cos(1.5*np.pi/180),0,0,0) #Go to incidence angle tran.transform(rays,0,0,0,91.5*np.pi/180,0,0) tran.transform(rays,0,0,0,0,0,yaw) #Apply grating misalignment tran.transform(rays,*gratalign) surf.flat(rays) #Get rid of rays outside grating ind = np.logical_and(np.abs(rays[2])<16,np.abs(rays[1])<25/2.) rays = tran.vignette(rays,ind=ind) plt.figure('grat') plt.clf() plt.plot(rays[1],rays[2],'.') plt.title('Beam Footprint') #Place grating if radapprox is False: tran.reflect(rays) tran.transform(rays,0,-hubdist,0,0,0,0) tran.radgrat(rays,160./hubdist,order,wave) tran.transform(rays,0,hubdist,0,0,0,0) else: tran.reflect(rays) gratedges = np.linspace(-16.,16.,N+1) for i in range(N): ind = np.logical_and(rays[2]>gratedges[i],\ rays[2]<gratedges[i+1]) d = (hubdist+np.mean(gratedges[i:i+2]))/hubdist*160. if np.sum(ind)>0: tran.grat(rays,d,-order,wave,ind=ind) #Go to focal plane tran.transform(rays,*gratalign) tran.transform(rays,0,0,0,0,0,-yaw) tran.transform(rays,0,0,0,-91.5*np.pi/180.,0,0) tran.transform(rays,0,0,0,0,0,np.pi/2) if f is not None: try: tran.transform(rays,0,0,-f,0,0,0) surf.flat(rays) except: pdb.set_trace() if autofocus is True: surf.focusY(rays) if returnMet is True: return anal.hpdY(rays)/F*180/np.pi*60**2 plt.figure('LSF') plt.clf() plt.plot(rays[1],rays[2],'.') plt.title('LSF') return rays
def test(N,rin=700.,rout=737.,azwidth=66.,srcdist=89.61e3+1.5e3,\ hubdist=11832.911,yaw=0.,wave=6.,order=1,\ opgalign=[0,0,0,0,0,0],f=None,\ rrays=False,glob=False,rcen=False,\ groll=0.,gyaw=0.,gpitch=0.,\ scatter=False,coordin=None,\ radapprox=False): """ Trace through the SPO module, then place the OPG module at its nominal position, allowing for misalignments about the center of the OPG module. The module tolerances can be investigated by a coordinate transformation around the OPG module placement. """ #Trace through SPO module rays = traceSPO(N,rin=rin,rout=rout,azwidth=azwidth,srcdist=srcdist,\ scatter=scatter) #Find the nominal OPG module location using formalism #from Flanagan's SPIE paper #Go to focus, steer out X and Y, then go up a distance #defined using Flangan formula, this should leave you #at the center of the beam, therefore the center of the #OPG module if coordin is None: coords = [tran.tr.identity_matrix()]*4 tran.transform(rays,0,0,0,0,-np.mean(rays[4]),0,coords=coords) #tran.steerX(rays,coords=coords) #tran.steerY(rays,coords=coords) tran.transform(rays,0,0,0,pi-np.mean(rays[5]),0,0,coords=coords) f0 = surf.focusI(rays,coords=coords) tran.transform(rays,np.mean(rays[1]),np.mean(rays[2]),0,0,0,0,\ coords=coords) tran.transform(rays,0,0,0,0,pi,0,coords=coords) tran.transform(rays,0,0,11832.911*np.cos(1.5*np.pi/180),0,0,0,coords=coords) tran.transform(rays,0,0,0,0,1.5*np.pi/180,0,coords=coords) else: rays = tran.applyT(rays,coordin) coords = np.copy(coordin) surf.flat(rays) #Now at center of central grating, with -z pointing toward hub tran.transform(rays,*opgalign,coords=coords) rays,record = traceOPG(rays,hubdist=hubdist,yaw=yaw,wave=wave,order=order,\ gyaw=gyaw,groll=groll,gpitch=gpitch,\ radapprox=radapprox) tran.itransform(rays,*opgalign,coords=coords) #Should be at same reference frame, with rays now diffracted if np.sum(record)==0: pdb.set_trace() rays = tran.vignette(rays,ind=record>0) record = record[record>0] #Trace to detector and determine LSF rays = tran.applyT(rays,coords,inverse=True) #surf.focusI(rays) if f is not None: try: tran.transform(rays,0,0,-f,0,0,0) surf.flat(rays) except: pdb.set_trace() if rcen is True: return anal.centroid(rays) if rrays is True: if glob is True: tran.transform(rays,0,0,f,0,0,0) return rays,record #Return LSF in arcseconds return anal.hpdY(rays)/12e3*180/pi*60**2