Beispiel #1
0
def testwave():
    """
    Verify wavefront reconstruction is occurring properly
    Coefficients can be altered in zernsurf and then resulting
    wavefront can be examined for the appropriate structure.
    """
    #Set up Zernike wave
    rays = sources.circularbeam(1., 10000)
    surf.zernsurf(rays, [0, 0, 0, .00, .001], 1.)
    tran.reflect(rays)

    r = anal.wavefront(rays, 200, 200)
    return r
Beispiel #2
0
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
Beispiel #3
0
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()
Beispiel #4
0
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
Beispiel #5
0
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
# 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)

# Go to optic focus.
surfaces.focusX(rays)

# Define grating parameters.
d = 160.  # Groove period @ 3300 mm [nm]
L = 3250.  # Center of grating [mm]
d *= L / 3300  # Find groove period at center of grating.
Beispiel #7
0
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)
Beispiel #8
0
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)
Beispiel #9
0
    # Create new ray object with only these rays.
    ind_rays = [r[ind] for r in rays]

    # Propagate these photons to primary mirror.
    surfaces.wolterprimary(ind_rays, r_int[i], z0)

    # Find which photons interact with this mirror.
    ind = np.where((ind_rays[3] > (z0 + mirror_sep / 2))
                   & (ind_rays[3] < (z0 + mirror_sep / 2 + mirror_length)))[0]

    # Keep only the photons which interact with the actual size
    # of the mirror
    ind_rays = [r[ind] for r in ind_rays]

    # Reflect photons off of primary.
    trans.reflect(ind_rays)

    # # Add Beckmann + Gaussian scatter.
    # # ogre.beckmann_scatter(ind_rays, 0, 0, 2e-5)
    # ind_rays[4] = ind_rays[4] + np.random.normal(scale=1e-7, size=len(ind_rays[4]))
    # ind_rays[5] = ind_rays[5] + np.random.normal(scale=1e-6, size=len(ind_rays[5]))
    # ind_rays[6] = -np.sqrt(1. - ind_rays[5]**2 - ind_rays[4]**2)

    # Propagate photons to the secondary mirror.
    surfaces.woltersecondary(ind_rays, r_int[i], z0)

    # Find which photons will interact with hyperboloid.
    ind = np.where((ind_rays[3] < (z0 - mirror_sep / 2))
                   & (ind_rays[3] > (z0 - mirror_sep / 2 - mirror_length)))[0]

    # keep only photons which interact with mirror.