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 rxPlot(): #Get Rx rx = np.transpose(np.genfromtxt('/home/rallured/Dropbox/AXRO/WSTracing/' '150528_Pauls_Rx.csv',delimiter=',')) geo = np.transpose(np.genfromtxt('/home/rallured/Dropbox/AXRO/WSTracing/' 'geometric_transmission_102711.txt')) rx = rx[:,geo[1]>0] geo = geo[1][geo[1]>0] f = np.sqrt(rx[1][-1]**2+10000.**2) z = np.sqrt(f**2-rx[1]**2) #spherical #Make plot plt.figure('SX') plt.clf() for i in np.arange(0,len(geo),3): rp1 = con.primrad(z[i]+50.,rx[1][i],1e4) rp2 = con.primrad(z[i]+250.,rx[1][i],1e4) rh1 = con.secrad(z[i]-50.,rx[1][i],1e4) rh2 = con.secrad(z[i]-250.,rx[1][i],1e4) uplt.isoplot([rp1,rp2],[z[i]+50.-1e4,z[i]+250.-1e4],'b') uplt.isoplot([rh1,rh2],[z[i]-50.-1e4,z[i]-250.-1e4],'b') return rx,geo
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
def fullMaskTrace(fold, prim, sec, woltVignette=True, foldrot=0.): #Get Wolter parameters alpha, p, d, e = conicsolve.woltparam(220., 8400.) foc = 8400. #Trace to fold mirror #translate to center of fold mirror PT.transform(0., 85.12, foc - 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() PT.transform(0, 0, -8400., 0, 0, 0) #Place secondary #Go to tangent point, apply misalignment, place mirror, and reverse 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.) if woltVignette is True: 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) #Back at nominal secondary tangent point PT.itransform(0, -conicsolve.secrad(8325., 220., 8400.), 8325., 0, 0, 0) #Place primary #Go to tangent point, apply misalignment, place mirror, and reverse 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.transform(0,0,8475.,0,0,0) ## PT.flat() ## PT.itransform(0,0,8475.,0,0,0) ## PT.wolterprimary(220.,8400.) PT.primaryLL(220., 8400., 8525., 8425., 30. * np.pi / 180., pcoeff, pax, paz) ## pdb.set_trace() if woltVignette is True: ind = logical_and(PT.z < 8525., PT.z > 8425.) PT.vignette(ind=ind) PT.reflect() 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) #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 traceThroughPair(rays,mask,primalign=np.zeros(6),\ detalign=np.zeros(6),cenSig=0.,\ primCoeffs=None,secCoeffs=None,\ secalign=np.zeros(6)): """ Trace rays through the primary mirror and then down to a focus. Need to simulate an initial misalignment and then applying an optimization algorithm to align primary to beam. Merit function should include the random error in spot centroiding primCoeffs is a list of coefficients, axial orders, and azimuthal orders Use global coordinate systems to determine sign conventions """ #Move to primary reference frame - rays 200 mm above node tran.transform(rays, 0, 0, -200., 0, 0, 0) glo = [tran.tr.identity_matrix()] * 4 #Move to mirror tangent point and apply misalignment tran.transform(rays, conic.primrad(8450., 220., 8400.), 0, 50, 0, 0, 0, coords=glo) tran.transform(rays, 0, 0, 0, *primalign[3:], coords=glo) tran.itransform(rays, conic.primrad(8450., 220., 8400.), 0, 50, 0, 0, 0, coords=glo) tran.transform(rays, 0, 0, -8400., 0, 0, 0, coords=glo) #Trace to Wolter surface if primCoeffs is None: surf.wolterprimary(rays, 220., 8400.) else: surf.primaryLL(rays,220.,8400.,8500.,8400.,100./220.,\ *primCoeffs) tran.reflect(rays) #Place secondary in primary reference frame tran.transform(rays,conic.secrad(8350.,220.,8400.),0,8350.,0,0,0,\ coords=glo) tran.transform(rays, *secalign, coords=glo) tran.itransform(rays,conic.secrad(8350.,220.,8400.),0,8350.,0,0,0,\ coords=glo) if secCoeffs is None: surf.woltersecondary(rays, 220., 8400.) else: surf.secondaryLL(rays,220.,8400.,8400.,8300.,100./220.,\ *secCoeffs) rays = tran.applyT(rays, glo, inverse=True) #Rays are now at secondary in global coordinate system #(origin on optical axis and at nominal node height) #Now reflect and go to detector tran.reflect(rays) tran.transform(rays, 0, 0, -8400., 0, 0, 0) tran.transform(rays, *detalign) surf.flat(rays) #Pick out spot centroids cen = [anal.centroid(rays, weights=mask == i) for i in range(mask[-1] + 1)] cen = np.transpose(np.array(cen)) #Add centroiding error if cenSig > 0: cen = cen + np.random.normal(scale=cenSig, size=np.shape(cen)) return cen