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 traceChaseParam(num, psi, theta, alpha, L1, z0, bestFocus=False, chaseFocus=False): """Trace a WS mirror pair using the parameters in Eq. 13 of Chase & VanSpeybroeck Return the RMS radius of the focus Can specify whether to find the best focus or not """ #Define annulus of source rays r0 = np.tan(4 * alpha) * z0 alphap = 2 * alpha / (1 + 1 / psi) r1 = PT.wsPrimRad(z0 + L1, 1., r0, z0) #np.tan(alphap/2.)*L1 + r0 PT.annulus(r0, r1, num) PT.transform(0, 0, 0, np.pi, 0, 0) PT.transform(0, 0, -10000., 0, 0, 0) pdb.set_trace() #Trace to primary PT.wsPrimary(r0, z0, psi) #Handle vignetting PT.vignette() ind = np.logical_and(PT.z < z0 + L1, PT.z > z0) PT.vignette(ind=ind) ## pdb.set_trace() #Apply pointing error PT.l = PT.l + np.sin(theta) PT.n = -np.sqrt(1 - PT.l**2) #Anything hitting backside goes away dot = PT.l * PT.ux + PT.m * PT.uy + PT.n * PT.uz ind = dot < 0. PT.vignette(ind=ind) if np.size(PT.x) < 1: return 0., 0., 0. #Reflect PT.reflect() N1 = np.size(PT.x) #Trace to secondary PT.wsSecondary(r0, z0, psi) #Vignette anything that did not converge PT.vignette() #Vignette anything hitting the backside dot = PT.l * PT.ux + PT.m * PT.uy + PT.n * PT.uz ind = dot < 0. PT.vignette(ind=ind) ## #Vignette anything outside the physical range of the mirror ## ind = np.logical_and(PT.z>z0-L1,PT.z<z0) ## PT.vignette(ind=ind) if np.size(PT.x) < 1: return 0., 0., 0. PT.reflect() #Trace to focal plane PT.flat() cx, cy = PT.centroid() r = np.sqrt(cx**2 + cy**2) #Find best focus delta = 0. if chaseFocus or bestFocus: delta = .0625 * (psi + 1) * (r**2 * L1 / z0**2) * (1 / np.tan(alpha))**2 PT.transform(0, 0, delta, 0, 0, 0) PT.flat() delta2 = 0. delta3 = 0. if bestFocus: try: delta2 = PT.findimageplane(20., 100) PT.transform(0, 0, delta2, 0, 0, 0) delta3 = PT.findimageplane(1., 100) PT.transform(0, 0, delta3, 0, 0, 0) except: pdb.set_trace() PT.flat() return PT.rmsCentroid() / z0, delta + delta2 + delta3, r
def SXperformance(theta,energy,rough,bestsurface=False,optsurface=False): """Go through a SMART-X prescription file and compute area weighted performance for a flat focal plane """ #Load in rx data ## rx = np.transpose(np.genfromtxt('/home/rallured/Dropbox/AXRO/WSTracing/' ## 'mirror-design-260sh-200mmlong-040mmthick' ## '-3mdiam-10mfl-10arcmin-fov-planarIntersept032713.csv',\ ## delimiter=',')) 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')) therm = np.transpose(np.genfromtxt('/home/rallured/Dropbox/AXRO/' 'WSTracing/thermal_shield_transmission_102711.txt')) f = np.sqrt(rx[1][-1]**2+10000.**2) z = np.sqrt(f**2-rx[1]**2) #spherical ## z = np.repeat(10000.,np.size(rx[1])) ## ind = rx[0] > 210. ## rx = rx[:,ind] Ns = np.shape(rx)[1] #Loop through and compute a resolution and a weight for each shell hpdTelescope = np.zeros(np.size(theta)) rmsTelescope = np.zeros(np.size(theta)) delta = np.zeros(np.size(theta)) cent = np.zeros(np.size(theta)) platefrac = np.zeros(np.size(theta)) #fig = plt.figure() for t in theta[:]: xi = np.array([]) yi = np.array([]) l = np.array([]) m = np.array([]) n = np.array([]) weights = np.array([]) #plt.clf() tstart = time.time() plate = np.zeros(Ns) for s in np.arange(0,Ns): if geo[1][s] > 0.: sys.stdout.write('Shell: %03i \r' % s) sys.stdout.flush() r,rays = traceWSShell(1000,t,rx[1][s],z[s],z[s]+225.,z[s]+25.,\ z[s]-25.,z[s]-225.,energy,rough) r = r*geo[1][s]*rx[9][s] #Reflectivity*area*alignmentbars*vign #Account for thermal shield in shells 220-321 if s > 219: r = r * therm[1][np.abs(energy/1000.-therm[0]).argmin()] r = np.repeat(r,np.size(rays[1])) weights = np.append(weights,r) PT.conic(1107.799202,-1.) xi = np.append(xi,rays[1]) yi = np.append(yi,rays[2]) l = np.append(l,rays[4]) m = np.append(m,rays[5]) n = np.append(n,rays[6]) if s%10==0: plt.plot(rays[1][:100],rays[2][:100],'.') plate[s] = anal.centroid(rays,weights=r)[0] print time.time()-tstart #Have list of photon positions and weights #Need to compute centroid and then FoM #Normalize weights weights = weights/np.sum(weights) xi = np.array(xi,order='F') yi = np.array(yi,order='F') zi = np.zeros(np.size(xi)).astype('float') li = np.array(l,order='F') mi = np.array(m,order='F') ni = np.array(n,order='F') uxi = np.zeros(np.size(xi)).astype('float') uyi = np.zeros(np.size(xi)).astype('float') uzi = np.zeros(np.size(xi)).astype('float') rays = [np.zeros(np.size(xi)).astype('float'),\ xi,yi,zi,\ li,mi,ni,\ uxi,uyi,uzi] if bestsurface: rays = tran.transform(rays,0,0,.25,0,0,0) surf.focusI(rays,weights=weights) if optsurface: PT.conic(1107.799202,-1.) #Emprically found best surface 1128.058314 #Compute FoM rmsTelescope[t==theta] = PT.rmsCentroid(weights=weights)/10000. hpdTelescope[t==theta] = PT.hpd(weights=weights)/10000. cx,cy = PT.centroid() cent[t==theta] = cx ind = geo[1] > 0. platefrac[t==theta] = np.std(plate[ind]/1e4)/rmsTelescope[t==theta] print hpdTelescope[t==theta],rmsTelescope[t==theta] return hpdTelescope,rmsTelescope,delta,cent,plate
def traceWSShell(num,theta,r0,z0,phigh,plow,shigh,slow,\ chaseFocus=False,bestFocus=False): """Trace a WS mirror pair with 10 m focal length and mirror axial cutoffs defined by phigh,plow """ #Define annulus of source rays a, p, d, e = con.woltparam(r0, z0) r1 = PT.wsPrimRad(plow, 1., r0, z0) #np.tan(a/2.)*(plow-10000.) + r0 r2 = PT.wsPrimRad(phigh, 1., r0, z0) #np.tan(a/2.)*(phigh-10000.) + r0 ## r2 = np.mean([r1,r2]) PT.annulus(r1, r2, num) PT.transform(0, 0, 0, np.pi, 0, 0) PT.transform(0, 0, z0, 0, 0, 0) ## pdb.set_trace() #Trace to primary PT.wsPrimary(r0, z0, 1.) #Handle vignetting PT.vignette() ind = np.logical_and(PT.z < phigh, PT.z > plow) PT.vignette(ind=ind) #Vignette rays hitting backside of mirror dot = PT.l * PT.ux + PT.m * PT.uy + PT.n * PT.uz ind = dot < 0. PT.vignette(ind=ind) #If all rays are vignetted, return if np.size(PT.x) < 1: return 0., 0., 0. #Apply pointing error PT.l = PT.l + np.sin(theta) PT.n = -np.sqrt(1 - PT.l**2) #Reflect PT.reflect() #Compute mean incidence angle for reflectivity ## ang = np.abs(np.mean(np.arcsin(dot))) #radians ## refl1 = CXCreflIr(ang,energy,rough) #Total rays entering primary aperture N1 = np.size(PT.x) #Trace to secondary PT.wsSecondary(r0, z0, 1.) #Vignette anything that did not converge PT.vignette() #Vignette anything outside the physical range of the mirror ind = np.logical_and(PT.z > slow, PT.z < shigh) PT.vignette(ind=ind) #Vignette anything hitting the backside dot = PT.l * PT.ux + PT.m * PT.uy + PT.n * PT.uz ind = dot < 0. PT.vignette(ind=ind) if np.size(PT.x) < 1: return 0., 0., 0. PT.reflect() #Compute mean incidence angle for reflectivity ## ang = np.abs(np.mean(np.arcsin(dot))) #radians ## refl2 = CXCreflIr(ang,energy,rough) #Trace to focal plane PT.flat() #Find Chase focus delta = 0. if chaseFocus or bestFocus: cx, cy = PT.centroid() r = np.sqrt(cx**2 + cy**2) delta = .0625*(1.+1)*(r**2*(phigh-plow)/10000.**2)\ *(1/np.tan(a))**2 PT.transform(0, 0, delta, 0, 0, 0) PT.flat() #Find best focus delta2 = 0. delta3 = 0. if bestFocus: try: delta2 = PT.findimageplane(20., 100) PT.transform(0, 0, delta2, 0, 0, 0) delta3 = PT.findimageplane(1., 100) PT.transform(0, 0, delta3, 0, 0, 0) except: pdb.set_trace() PT.flat() #return refl1*refl2 return PT.hpd(), PT.rmsCentroid(), delta