Exemple #1
0
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)
Exemple #2
0
def traceSource(N):
    """Trace rays from PANTER point source to position of
    SPO optics
    """
    #Set up subannulus
    r0 = 737.
    F = 12e3
    L = 4 * F * .605 / r0
    tg = .25 * np.arctan(r0 / F)
    r1 = r0 + L * tg
    dphi = 50. / r0 / 2
    rays = sources.subannulus(r0, r1, dphi, N)

    #Shift annulus to zero x coordinate
    tran.transform(rays, r0, 0, 0, 0, 0, 0)
    #Set ray cosines
    srcdist = 119471.
    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 = [
        rays[0], rays[1], rays[2], rays[3], l, m, n, rays[7], rays[8], rays[9]
    ]

    #Go to optical axis
    tran.transform(rays, -r0, 0, 0, 0, 0, 0)

    return rays
Exemple #3
0
def fullShellPair(ang=2 * np.pi, secalign=[0, 0, 0, 0, 0, 0]):
    """
    Trace a full shell optic with misalignments of the secondary
    with respect to primary. Allow azimuthal extent to be a variable.
    """
    #Set up ray bundle
    rays = sources.subannulus(220., 220.6, ang, 100000, zhat=-1.)
    tran.transform(rays, 0, 0, -8400., 0, 0, 0)
    theta = np.arctan2(rays[2], rays[1])

    #Trace through optics
    surf.wolterprimary(rays, 220., 8400.)
    tran.reflect(rays)
    tran.transform(rays, 0, 0, 8400., 0, 0, 0)
    tran.transform(rays, *secalign)
    tran.transform(rays, 0, 0, -8400., 0, 0, 0)
    surf.woltersecondary(rays, 220., 8400.)
    tran.reflect(rays)
    tran.transform(rays, 0, 0, 8400., 0, 0, 0)
    tran.itransform(rays, *secalign)

    #Go to focus
    tran.transform(rays, 0, 0, -8400., 0, 0, 0)
    surf.flat(rays)

    #Plot misalignment curves
    ##    plt.plot(theta,rays[1],'.')
    ##    plt.plot(theta,rays[2],'.')
    plt.plot(rays[1], rays[2], '.')

    return rays, theta
Exemple #4
0
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
Exemple #5
0
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])
Exemple #6
0
def sourceToChamber(N, misalign=np.zeros(6)):
    """
    Trace randomly sampled rays from the TruFocus X-ray source
    to the 1.22 m diameter entrance to the test chamber.
    A-B from Jeff K.'s memo is 89.61
    Use oversized sub-apertured annulus, applying translations
    """
    #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)
    #Place secondary
    surf.woltersecondary(rays, 220., 8400.)
    tran.reflect(rays)
    #Vignette rays not landing in active mirror area
    indz = np.logical_and(rays[3] > 8276., rays[3] < 8376.)
    ind = np.logical_and(np.abs(rays[2]) < 50., indz)
    rays = tran.vignette(rays, ind=ind)
    #Go back up to intersection plane
    tran.transform(rays, 0, 0, 8400, 0, 0, 0)
    #Reverse misalignments
    tran.itransform(rays, -220., 0, 0, 0, 0, 0)
    tran.itransform(rays, 0, 0, 0, misalign[3], misalign[4], misalign[5])
    tran.itransform(rays, 220, 0, 0, 0, 0, 0)
    #Now back in nominal intersection coordinate system
    #Go to focus
    f = -9253.3858232
    tran.transform(rays, 0, 0, f, 0, 0, 0)
    surf.flat(rays)

    return rays  #anal.hpd(rays)/abs(f)*60**2*180/pi
Exemple #7
0
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
Exemple #8
0
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
Exemple #9
0
def tracePrimary(primCoeffs=None, primalign=np.zeros(6)):
    """
    Trace rays from focus to primary, off retroreflector,
    then back to focus. Return spot centroids.
    """
    #Set up source
    primfoc = conic.primfocus(220., 8400.)
    r1 = conic.primrad(8500., 220., 8400.)
    rays = sources.subannulus(220., r1, 100. / 220, 100000, zhat=1.)
    tran.pointTo(rays, 0., 0., -primfoc, reverse=1.)
    theta = np.arctan2(rays[2], rays[1])

    #Trace to primary
    tran.transform(rays, *primalign)
    tran.transform(rays, 0., 0, -8400., 0, 0, 0)
    if primCoeffs is None:
        surf.wolterprimary(rays, 220., 8400.)
    else:
        surf.primaryLL(rays,220.,8400.,8500.,8400.,100./220.,\
                       *primCoeffs)
    tran.transform(rays, 0, 0, 8400., 0, 0, 0)
    tran.itransform(rays, *primalign)
    tran.reflect(rays)

    #Reflect and come back
    tran.transform(rays, 0, 0, 400., 0, 0, 0)
    surf.flat(rays)
    tran.reflect(rays)
    tran.transform(rays, 0, 0, -400., 0, 0, 0)

    #Trace to primary
    tran.transform(rays, *primalign)
    tran.transform(rays, 0., 0, -8400., 0, 0, 0)
    if primCoeffs is None:
        surf.wolterprimary(rays, 220., 8400.)
    else:
        surf.primaryLL(rays,220.,8400.,8500.,8400.,100./220.,\
                       *primCoeffs)
    ind = np.logical_and(rays[3] > 8400., rays[3] < 8500.)
    tran.vignette(rays, ind=ind)
    tran.transform(rays, 0, 0, 8400., 0, 0, 0)
    tran.itransform(rays, *primalign)
    tran.reflect(rays)

    #Go to primary focus
    tran.transform(rays, 0, 0, -primfoc, 0, 0, 0)
    surf.flat(rays)

    return rays, theta
Exemple #10
0
def traceSPO(N,rin=700.,rout=737.,azwidth=66.,srcdist=89.61e3+1.5e3,\
             scatter=False):
    """
    Trace a set of rays through an SPO module using a
    finite source distance. Ignore vignetting, we are
    only interested in aberrations.
    Set up a subannulus, apply finite source effect,
    and then simply translate to inner SPO radius and
    trace outward.
    Let x be the radial direction, y the azimuthal
    """
    #Establish subannulus of rays
    rays = source.subannulus(rin,rout,azwidth/rin,N,zhat=-1.)
    #Transform to node position
    mx = np.mean([rin,rout])
    tran.transform(rays,mx,0,0,0,0,0)
    #Set up finite source distance
    raydist = np.sqrt(srcdist**2+rays[1]**2+rays[2]**2)
    l = rays[1]/raydist
    m = rays[2]/raydist
    n = -np.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)
    tran.transform(rays,0,0,0,0,-np.mean(rays[4]),0)
    
    #Move to SPO optical axis and trace through shells
    tran.transform(rays,-mx,0,0,0,0,0)
    R = np.arange(rin,rout+.605,.605)
    rad = np.sqrt(rays[1]**2+rays[2]**2)
    for r in R:
        #Collect relevant rays
        ind = np.logical_and(rad>r,rad<r+.605)
        if np.sum(ind)==0:
            continue
        #Trace them through system
        surf.spoPrimary(rays,r,12e3,ind=ind)
        tran.reflect(rays,ind=ind)
        surf.spoSecondary(rays,r,12e3,ind=ind)
        tran.reflect(rays,ind=ind)
    #Rays are now at secondary surfaces,
    #Add scatter
    if scatter is True:
        rays[4] = rays[4] + np.random.normal(scale=15./2.35*5e-6,size=N)
        rays[5] = rays[5] + np.random.normal(scale=1.5/2.35*5e-6,size=N)
        rays[6] = -np.sqrt(1.-rays[5]**2-rays[4]**2)
    return rays
Exemple #11
0
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
Exemple #12
0
def createWavefront(rad,num,coeff,rorder=None,aorder=None,\
                    slitwidth=3.,masknum=15,trans=np.zeros(2)):
    """Bounce rays off of Zernike surface. Use flat to
    bring rays to a common plane, leaving the OPD as twice
    the figure error of the Zernike surface.
    Use subannulus so as not to waste rays in beginning
    of simulation
    Group rays for a given mask slit together using a
    Hartmann vector. Vignette everything else.
    Assume masknum slits 3 mm wide distributed evenly
    over the mirror aperture
    """
    #Create set of rays
    r1 = conic.primrad(8500., 220., 8400.)
    #Loop through Hartmann mask
    maskcenters = np.linspace(-48.5 / 220., 48.5 / 220., masknum)
    for i in range(masknum):
        trays = sources.subannulus(220., r1, slitwidth / 220.,
                                   round(num / masknum))
        tran.transform(trays, 0, 0, 0, 0, 0, maskcenters[i])
        try:
            rays = [np.concatenate([rays[ti], trays[ti]]) for ti in range(10)]
            mask = np.concatenate([mask, np.repeat(i, round(num / masknum))])
        except:
            rays = trays
            mask = np.repeat(i, round(num / masknum))

    tran.transform(rays, 220.3 + trans[0], trans[1], 0, 0, 0, 0)
    #Reflect to Zernike surface
    surf.zernsurf(rays, coeff, rad, nr=1., rorder=rorder, aorder=aorder)
    tran.reflect(rays)
    surf.flat(rays, nr=1.)
    tran.transform(rays, -220.3, 0, 0, 0, 0, 0)
    #Wavefront now has the proper Zernike form, rays pointing in
    #-z direction
    return rays, mask
Exemple #13
0
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
Exemple #14
0
def traceSPO(R,L,focVec,N,M,spanv,wave,d=.605,t=.775,offX=0.,offY=0.,\
             vis=None,ang=None,coords=None):
    """Trace SPO surfaces sequentially. Collect rays from
    each SPO shell and set them to the PT rays at the end.
    Start at the inner radius, use the wafer and pore thicknesses
    to vignette and compute the next radius, loop while
    radius is less than Rout.
    """
    #Ray bookkeeping arrays
    trays = [np.zeros(M * N) for n in range(10)]
    if vis is True:
        xp, yp, zp = [], [], []
        xs, ys, zs = [], [], []

    #Loop through shell radii and collect rays
    ref = np.zeros(M * N)
    for i in range(M):
        #Set up source annulus
        rays = sources.subannulus(R[i], R[i] + d, spanv[i], N, zhat=-1.)
        z, n = rays[3], rays[6]
        ##        #Transform rays to be above xy plane
        ##        tran.transform(rays,0,0,-100.,0,0,0,coords=coords)
        #Apply angular offset
        tran.transform(rays, 0, 0, 0, 0, 0, ang)
        #Get initial positions
        glob = None
        if vis is True:
            #Initial ray positions
            x0, y0, z0 = np.copy(rays[1]), np.copy(rays[2]), np.copy(rays[3])


##
##            #Establish 3d figure
##            fig = plt.figure('vis')
##            ax = fig.add_subplot(111,projection='3d')
#Trace to primary
        surf.spoPrimary(rays, R[i], focVec[i])

        #Export primary ray positions in global reference frame
        if vis is True:
            tran.transform(rays, 0, 0, -focVec[i], 0, 0, 0)
            xp = np.concatenate((xp, rays[1]))
            yp = np.concatenate((yp, rays[2]))
            zp = np.concatenate((zp, rays[3]))
            tran.transform(rays, 0, 0, focVec[i], 0, 0, 0)

        #Add offsets if they apply
        rays = [rays[0],rays[1],rays[2],rays[3],\
                rays[4]+offX,rays[5]+offY,\
                -np.sqrt(rays[6]**2-offX**2-offY**2),\
                rays[7],rays[8],rays[9]]
        tran.reflect(rays)

        #Compute reflectivity
        inc = anal.grazeAngle(rays)  #np.arcsin(l*ux+m*uy+n*uz)
        if np.size(wave) == 1:
            refl = sporef(inc * 180 / np.pi, 1239.8 / wave)
        else:
            refl = np.diag(
                sporef(inc * 180 / np.pi, 1239.8 / wave[i * N:(i + 1) * N]))

        #Trace to secondary
        surf.spoSecondary(rays, R[i], focVec[i])
        tran.reflect(rays)

        #Compute reflectivity
        inc = anal.grazeAngle(rays)  #inc = np.arcsin(l*ux+m*uy+n*uz)
        if np.size(wave) == 1:
            ref[i*N:(i+1)*N] = refl * sporef(inc*180/np.pi\
                                             ,1239.8/wave)
        else:
            ref[i*N:(i+1)*N] = refl * np.diag(sporef(inc*180/np.pi\
                                             ,1239.8/wave[i*N:(i+1)*N]))

        #Set plane to be at focus
        tran.transform(rays, 0, 0, -focVec[i], 0, 0, 0, coords=coords)
        #Collect rays
        try:
            for t in range(1, 7):
                temp = trays[t]
                temp[i * N:(i + 1) * N] = rays[t]
        except:
            pdb.set_trace()

    #Export secondary ray positions in global coordinate frame
    if vis is True:
        return trays, ref, [xp, yp, zp], [trays[1], trays[2], trays[3]]

    return trays, ref
Exemple #15
0
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