def CDAbeam(num, div, pitch, roll, cda): ## PT.transform(*cda) PT.pointsource(div, num) PT.transform(0, 0, 0, pitch, 0, 0) PT.transform(0, 0, 0, 0, 0, roll) PT.itransform(*cda) return
def primMaskTrace(fold, primary, woltVignette=True, foldrot=0.): #Get Wolter parameters alpha, p, d, e = conicsolve.woltparam(220., 8400.) primfoc = conicsolve.primfocus(220., 8400.) #Trace to fold mirror #translate to center of fold mirror PT.transform(0., 85.12, primfoc - 651.57 + 85.12, 0, 0, 0) #rotate so surface normal points in correct direction PT.transform(0, 0, 0, -3 * pi / 4, 0, 0) PT.transform(0, 0, 0, 0, 0, pi) #trace to fold flat PT.flat() #Introduce fold misalignment PT.transform(*fold) PT.zernsurfrot(foldsag, foldfig, 406. / 2, -174.659 * pi / 180 + foldrot) PT.itransform(*fold) PT.reflect() PT.transform(0, 0, 0, 0, 0, -pi) PT.transform(0, 0, 0, pi / 4, 0, 0) #Translate to optical axis mid-plane, then down to image of #primary focus, place primary mirror and trace PT.transform(0, 85.12, 651.57 - 85.12, 0, 0, 0) PT.flat() ## pdb.set_trace() rt = conicsolve.primrad(8475., 220., 8400.) PT.transform(0, -rt, 75., 0, 0, 0) PT.transform(*primary) PT.transform(0, rt, -8475., 0, 0, 0) ## PT.wolterprimary(220.,8400.) PT.primaryLL(220., 8400., 8525., 8425., 30. * np.pi / 180., pcoeff, pax, paz) if woltVignette is True: ind = logical_and(PT.z < 8525., PT.z > 8425.) PT.vignette(ind=ind) PT.reflect() PT.transform(0, -rt, 8475., 0, 0, 0) PT.itransform(*primary) PT.transform(0, rt, -8475., 0, 0, 0) #Move back up to mask plane and trace flat PT.transform(0, 0, 8400. + 134.18, 0, 0, 0) PT.flat() ## pdb.set_trace() #Rays should now be at Hartmann mask plane return
def setupSource(wave,N,radius=450.,focal=8000.,scatter=50e-6,\ gwidth=25.,glength=32.,pitch=0.,yaw=0.,roll=0.): """Set up converging beam with some scatter. Idea is to place a grating at radius and focal length with an incidence angle of 1.5 degrees """ #Setup rays over grating surface PT.x = np.random.uniform(low=-gwidth / 2, high=gwidth / 2, size=N) PT.y = np.random.uniform(low=-glength / 2, high=glength / 2, size=N) PT.z = np.repeat(0., N) PT.l = np.zeros(N) PT.m = np.zeros(N) PT.n = np.zeros(N) PT.ux = np.zeros(N) PT.uy = np.zeros(N) PT.uz = np.repeat(1., N) #Transform to nominal focus to set ray cosines PT.transform(0, 0, 0, -88.5 * np.pi / 180, 0, 0) PT.transform(0, radius, -focal, 0, 0, 0) rad = np.sqrt(PT.x**2 + PT.y**2 + PT.z**2) PT.l = -PT.x / rad PT.m = -PT.y / rad PT.n = -PT.z / rad #Add scatter PT.l = PT.l + scatter / 10. * np.random.normal(size=N) PT.m = PT.m + scatter * np.random.normal(size=N) PT.n = -np.sqrt(1. - PT.l**2 - PT.m**2) #Go back to plane of of grating PT.transform(0, -radius, focal, 0, 0, 0) PT.transform(0, 0, 0, 88.5 * np.pi / 180, 0, np.pi) #Place grating and diffract hubdist = np.sqrt(radius**2 + focal**2) * np.cos(1.5 * np.pi / 180) PT.flat() PT.reflect() PT.transform(0, 0, 0, pitch, roll, yaw) PT.radgrat(hubdist, 160. / hubdist, 1, wave) PT.itransform(0, 0, 0, pitch, roll, yaw) #Go to focal plane PT.transform(0, 0, 0, np.pi / 2, 0, 0) PT.transform(0, 0, -hubdist, 0, 0, 0) PT.transform(0, 0, 27.27727728 - .04904905, 0, 0, 0) PT.flat() #plt.plot(PT.x,PT.y,'.') return PT.centroid()
def traceBeam(gratAlign,order=1.,wave=2.48,blaze=30.): """Traces a beam to grating, applies misalignment, then traces to focal plane and returns mean x,y position x refers to spectral direction """ #Compute yaw to achieve Littrow configuration phi0 = arccos(sin(1.5*pi/180)/cos(blaze*pi/180)) yaw = -tan(sin(blaze*pi/180)/tan(phi0)) ## yaw = yaw - pi/2 ## pdb.set_trace() #Set up beam rays = PT.pointsource(0.,10) #multiple rays to avoid Python complaints #Rotate to nominal grating reference frame PT.transform(rays,0,0,0,pi/2+1.5*pi/180,0,0) #Apply misalignment PT.transform(rays,*gratAlign) #Trace grating PT.flat(rays) PT.transform(rays,0,0,0,0,0,yaw) #-1.73211678*pi/180 PT.radgrat(rays,11500.,160./11500.,order,wave) PT.itransform(rays,0,0,0,0,0,yaw) #Reverse misalignment PT.itransform(rays,*gratAlign) #Trace to focal plane PT.transform(rays,0,11500.,0,0,0,0) PT.transform(rays,0,0,0,pi/2,0,0) PT.flat(rays) #Return mean positions return mean(rays[1]),mean(rays[2])
def traceFromMask(N, numholes, cda, fold, retro, primary, foldrot=0., retrorot=0.): #Vignette at proper hole h = hartmannMask() ind = h == N PT.vignette(ind=ind) #Continue trace up to retro and back to CDA PT.transform(0, -123.41, 1156.48 - 651.57 - 134.18, 0, 0, 0) PT.flat() PT.transform(0, 0, 0, pi, 0, 0) PT.transform(*retro) PT.zernsurfrot(retrosag, retrofig, 378. / 2, -8.993 * pi / 180 + retrorot) PT.itransform(*retro) PT.reflect() PT.transform(0, 0, 0, -pi, 0, 0) PT.transform(0, 123.41, -1156.48 + 651.57 + 134.18, 0, 0, 0) PT.flat() h = hartmannMask() ind = h == N PT.vignette(ind=ind) PT.transform(0, 0, -134.18, 0, 0, 0) rt = conicsolve.primrad(8475., 220., 8400.) PT.transform(0, -rt, 75., 0, 0, 0) PT.transform(*primary) PT.transform(0, rt, -8475., 0, 0, 0) PT.wolterprimary(220., 8400.) ind = logical_and(PT.z < 8525., PT.z > 8425.) PT.vignette(ind=ind) PT.reflect() PT.transform(0, -rt, 8475., 0, 0, 0) PT.itransform(*primary) PT.transform(0, rt, -8475., 0, 0, 0) PT.transform(0,-85.12,8400.-651.57+85.12\ ,0,0,0) PT.transform(0, 0, 0, -pi / 4, 0, 0) PT.transform(0, 0, 0, 0, 0, pi) PT.flat() PT.transform(*fold) PT.zernsurfrot(foldsag, foldfig, 406. / 2, -174.659 * pi / 180 + foldrot) PT.itransform(*fold) PT.reflect() PT.transform(0, 0, 0, 0, 0, -pi) PT.transform(0, 0, 0, 3 * pi / 4, 0, 0) PT.transform(0,-85.12,-85.12-(conicsolve.primfocus(220.,8400.)-651.57)\ ,0,0,0) PT.transform(*cda) PT.flat() return
def traceCyl(align): """Traces a cylindrical approximation to Wolter I geometry Assumes 1 m radius of curvature in accordance with OAB samples align is a 12 element array giving the transformations to be applied to each mirror Uses identical set of rays each run defined upon module import Adds a restraint such that any vignetting over 25% results in a huge merit function """ #Set up source np.random.seed(5) a, p, d, e = con.woltparam(1000., 10000.) r0 = con.primrad(10025., 1000., 10000.) r1 = con.primrad(10125., 1000., 10000.) dphi = 100. / 1000. PT.subannulus(r0, r1, dphi, 10**4) PT.transform(0, 0, 0, np.pi, 0, 0) PT.transform(0, 0, -10500., 0, 0, 0) #Trace primary cylinder: go to tangent point at center #of mirror and then rotate to cone angle, then move #to new cylinder axis and tracecyl rt = con.primrad(10075., 1000., 10000.) PT.transform(rt, 0, 0, 0, a, 0) PT.transform(*align[:6]) PT.transform(0, 0, 0, np.pi / 2, 0, 0) PT.transform(-1000., 0, 0, 0, 0, 0) PT.cyl(1000.) #Vignette rays missing physical surface ind = np.logical_and(abs(PT.z) < 50., abs(PT.y) < 50.) PT.vignette(ind=ind) #Reflect and reverse transformations PT.reflect() PT.transform(1000., 0, 0, 0, 0, 0) PT.itransform(0, 0, 0, np.pi / 2, 0, 0) PT.itransform(*align[:6]) PT.itransform(rt, 0, 0, 0, a, 0) #Trace secondary cylinder: same principle as before rt = con.secrad(9925., 1000., 10000.) PT.transform(0, 0, -150., 0, 0, 0) PT.transform(rt, 0, 0, 0, 3 * a, 0) PT.transform(*align[6:]) PT.transform(0, 0, 0, np.pi / 2, 0, 0) PT.transform(-1000., 0, 0, 0, 0, 0) PT.cyl(1000.) #Vignette rays missing physical surface ind = np.logical_and(abs(PT.z) < 50., abs(PT.y) < 50.) PT.vignette(ind=ind) #Reflect and reverse transformations PT.reflect() PT.transform(1000., 0, 0, 0, 0, 0) PT.itransform(0, 0, 0, np.pi / 2, 0, 0) PT.itransform(*align[6:]) PT.itransform(rt, 0, 0, 0, 3 * a, 0) #Go down to nominal focus PT.transform(0, 0, -9925., 0, 0, 0) PT.flat() #Compute merit function nom = PT.rmsCentroid() / 10**4 * 180. / np.pi * 60**2 nom = nom + max((9500. - np.size(PT.x)), 0.) return nom
def fullFromMask(N, cda, fold, retro, prim, sec, foldrot=0., retrorot=0.): ## pdb.set_trace() #Vignette at proper hole h = hartmannMask() ind = h == N PT.vignette(ind=ind) #Continue trace up to retro and back to CDA PT.transform(0, -123.41, 1156.48 - 651.57 - 134.18, 0, 0, 0) PT.flat() PT.transform(0, 0, 0, pi, 0, 0) PT.transform(*retro) PT.zernsurfrot(retrosag, retrofig, 378. / 2, -8.993 * pi / 180 + retrorot) PT.itransform(*retro) PT.reflect() PT.transform(0, 0, 0, -pi, 0, 0) #Back to mask PT.transform(0, 123.41, -1156.48 + 651.57 + 134.18, 0, 0, 0) PT.flat() h = hartmannMask() ind = h == N PT.vignette(ind=ind) #Place Wolter surfaces PT.transform(0, 0, -134.18 - 8400., 0, 0, 0) PT.transform(0, -conicsolve.primrad(8425., 220., 8400.), 8425., 0, 0, 0) PT.transform(*prim) PT.itransform(0, -conicsolve.primrad(8425., 220., 8400.), 8425., 0, 0, 0) ## PT.wolterprimary(220.,8400.) PT.primaryLL(220., 8400., 8525., 8425., 30. * np.pi / 180., pcoeff, pax, paz) pdb.set_trace() ind = logical_and(PT.z < 8525., PT.z > 8425.) PT.vignette(ind=ind) PT.transform(0, -conicsolve.primrad(8425., 220., 8400.), 8425., 0, 0, 0) PT.itransform(*prim) PT.itransform(0, -conicsolve.primrad(8425., 220., 8400.), 8425., 0, 0, 0) PT.reflect() #Wolter secondary PT.transform(0, -conicsolve.secrad(8325., 220., 8400.), 8325., 0, 0, 0) PT.transform(*sec) PT.itransform(0, -conicsolve.secrad(8325., 220., 8400.), 8325., 0, 0, 0) PT.woltersecondary(220., 8400.) ind = logical_and(PT.z < 8375., PT.z > 8275.) PT.vignette(ind=ind) PT.reflect() PT.transform(0, -conicsolve.secrad(8325., 220., 8400.), 8325., 0, 0, 0) PT.itransform(*sec) PT.itransform(0, -conicsolve.secrad(8325., 220., 8400.), 8325., 0, 0, 0) ## PT.woltersecondary(220.,8400.) ## ind = logical_and(PT.z<8375.,PT.z>8275.) ## PT.vignette(ind=ind) ## PT.reflect() #Back to fold PT.transform(0,-85.12,8400.-651.57+85.12\ ,0,0,0) PT.transform(0, 0, 0, -pi / 4, 0, 0) PT.transform(0, 0, 0, 0, 0, pi) PT.flat() PT.transform(*fold) PT.zernsurfrot(foldsag, foldfig, 406. / 2, -174.659 * pi / 180 + foldrot) PT.itransform(*fold) PT.reflect() PT.transform(0, 0, 0, 0, 0, -pi) #Back to CDA PT.transform(0, 0, 0, 3 * pi / 4, 0, 0) PT.transform(0,-85.12,-85.12-8400.+651.57\ ,0,0,0) PT.transform(*cda) PT.flat() return