示例#1
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
示例#2
0
def depthoffocus(rays, weights):
    tran.transform(rays, 0, 0, -20, 0, 0, 0)
    surf.flat(rays)
    lsf = [convolveLSF(rays, .001, marg, weights=weights)]
    for i in range(80):
        tran.transform(rays, 0, 0, .5, 0, 0, 0)
        surf.flat(rays)
        lsf.append(convolveLSF(rays, .001, marg, weights=weights))
    return lsf
示例#3
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
示例#4
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
示例#5
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
示例#6
0
def placeWolterPair(rays, misalign=np.zeros(6)):
    """
    Place the X-ray test mirror pair in the beam path.
    Assume rays are at XY plane with -z mean direction
    Nominal position of intersection plane is 1.5 m
    past chamber entrance with mirror optical axis
    coincident with chamber optical axis.
    Can supply misalignment about X=0,Y=0 in intersection plane.
    """
    #Go to nominal intersection plane
    tran.transform(rays, 0, 0, -1500., 0, 0, 0)
    #Apply misalignments
    tran.transform(rays, *misalign)
    #Go to focus and place primary
    tran.transform(rays, 0, 0, -8400, 0, 0, 0)
    pdb.set_trace()
    surf.wolterprimary(rays, 220., 8400.)
    tran.reflect(rays)
    pdb.set_trace()
    #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
    pdb.set_trace()
    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 nominal intersection plane
    tran.transform(rays, 0, 0, 8400, 0, 0, 0)
    tran.itransform(rays, *misalign)
    return rays
示例#7
0
def alignTolerances(num,azwidth=60.,axwidth=60.,f=None,catalign=np.zeros(6),\
                    returnrays=False):
    """
    Set up perfect beam and insert CAT grating
    Mess with alignment and measure spot shift at focus
    """
    #Set up converging beam
    rays = sources.convergingbeam2(12e3,-azwidth/2.,azwidth/2.,\
                                   -axwidth/2.,axwidth/2.,num,0.)
    tran.transform(rays, 0, 0, 0, np.pi, 0, 0)
    tran.transform(rays, 0, 0, 12e3, 0, 0, 0)

    #Place CAT grating
    tran.transform(rays, *catalign)
    surf.flat(rays)
    tran.grat(rays, 200., 8, 1.)
    tran.itransform(rays, *catalign)

    #Go to focus
    if f is not None:
        try:
            tran.transform(rays, 0, 0, f, 0, 0, 0)
            surf.flat(rays)
        except:
            pdb.set_trace()

    cx, cy = anal.centroid(rays)

    if returnrays is True:
        return rays

    return cx, cy
示例#8
0
def createWavefront(rad, num, coeff, rorder=None, aorder=None):
    """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.
    """
    #Create set of rays
    rays = sources.circularbeam(rad, num)
    #Reflect to Zernike surface
    surf.zernsurf(rays, coeff, rad, nr=1., rorder=rorder, aorder=aorder)
    tran.reflect(rays)
    tran.transform(rays, 0, 0, 0, np.pi, 0, 0)
    surf.flat(rays, nr=1.)
    #Wavefront now has the proper Zernike form, rays pointing in
    #+z direction
    return rays
示例#9
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)
示例#10
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
示例#11
0
def sourceAlignment(dx, dy, dz):
    """
    Set up a trace of rays from the fiber source to
    the OAP. Determine wavefront error of collimated
    beam.
    """
    #Source
    rays = sources.circularbeam(125. / 4, 10000)
    tran.pointTo(rays, dx, dy, -775. / 2 + dz, reverse=1)
    rays[0] = np.sqrt((rays[1] + dx)**2 + (rays[2] + dy)**2 +
                      (775. / 2 + dz)**2)
    pdb.set_trace()

    #Go to focus
    tran.transform(rays, 0, 0, 0, np.pi / 2, 0, 0)
    tran.transform(rays, 0, -775. / 2, -775. / 2, 0, 0, 0)

    #Trace to parabola
    surf.conic(rays, 775., -1., nr=1.)
    tran.reflect(rays)

    #Restrict to 5" diameter
    ##    ind = np.logical_and(rays[3]>387.5-62.5,rays[3]<387.5+62.5)
    ##    tran.vignette(rays,ind=ind)

    #Reflect
    ##    for i in range(7,10):
    ##        rays[i] = -rays[i]
    tran.transform(rays, 0, 0, 775. / 2, 0, 0, 0)
    surf.flat(rays, nr=1.)

    pdb.set_trace()

    #Get OPD
    opd, dx0, dy0 = anal.interpolateVec(rays, 0, 200, 200)
    opd = man.remove2DLeg(opd, xo=1, yo=0)
    opd = man.remove2DLeg(opd, xo=0, yo=1)
    pv = ana.ptov(opd)

    plt.figure('OPD')
    plt.imshow(opd)
    plt.colorbar()

    wavesl = np.gradient(opd, dx0)
    resy = fit.legendre2d(wavesl[0], xo=2, yo=2)
    resx = fit.legendre2d(wavesl[1], xo=2, yo=2)
    resy[0][np.isnan(opd)] = np.nan
    resx[0][np.isnan(opd)] = np.nan

    plt.figure('Y')
    plt.imshow(resy[0] * 180 / np.pi * 60**2)
    plt.colorbar()

    plt.figure('X')
    plt.imshow(resx[0] * 180 / np.pi * 60**2)
    plt.colorbar()

    return pv * 1e6
示例#12
0
def rayBundle(N, div, az, height, rad):
    """
    Set up a diverging ray bundle on the 220 mm cylinder.
    """
    #Establish rays
    rays = sources.pointsource(div, N)
    #Go to cylindrical axis
    tran.transform(rays, 0, 0, rad, 0, 0, 0)
    #Apply height offset
    tran.transform(rays, -height, 0, 0, 0, 0, 0)
    #Apply azimuthal offset
    tran.transform(rays, 0, 0, 0, -az, 0, 0)
    #Go back to tangent plane
    tran.transform(rays, 0, 0, -rad, 0, 0, 0)
    surf.flat(rays, nr=1.)
    return rays
示例#13
0
def collectFocalPlaneRays(z):
    tra2 = np.dot(tr.translation_matrix([40,-100,0]),\
               tr.rotation_matrix(pi/2,[0,0,1,0]))
    rot2 = tr.rotation_matrix(pi / 2, [0, 0, 1, 0])
    tra3 = np.dot(tr.translation_matrix([1000,-1000,0]),\
               tr.rotation_matrix(-pi/2,[0,0,1,0]))
    rot3 = tr.rotation_matrix(-pi / 2, [0, 0, 1, 0])
    tra4 = np.dot(tr.translation_matrix([1020,920,0]),\
               tr.rotation_matrix(pi,[0,0,1,0]))
    rot4 = tr.rotation_matrix(pi, [0, 0, 1, 0])

    f = open(
        '/home/rallured/Dropbox/Arcus/Raytrace/FocalPlaneLayout/160412_Rays.pkl',
        'r')
    rays = pickle.load(f)
    f.close()

    rays2 = np.copy(rays)
    rays2 = [rays2[0],rays2[1],-rays2[2],rays2[3],\
             rays2[4],-rays2[5],rays2[6],\
             rays2[7],rays2[8],rays2[9]]
    rays3 = np.copy(rays)
    rays3 = [rays3[0],rays3[1],-rays3[2],rays3[3],\
             rays3[4],-rays3[5],rays3[6],\
             rays3[7],rays3[8],rays3[9]]
    rays4 = np.copy(rays)

    tran.itransform(rays2, 40, -100, 0, 0, 0, pi / 2)
    tran.itransform(rays3, 1000, 1000, 0, 0, 0, -pi / 2)
    tran.itransform(rays4, 1020, 920, 0, 0, 0, pi)

    #Plot to make sure
    plt.plot(rays[1], rays[2], '.')
    plt.plot(rays2[1], rays2[2], '.')
    plt.plot(rays3[1], rays3[2], '.')
    plt.plot(rays4[1], rays4[2], '.')

    #Transform everything up
    r = [rays, rays2, rays3, rays4]
    [tran.transform(ri, 0, 0, z, 0, 0, 0) for ri in r]
    [surf.flat(ri) for ri in r]
    plt.figure()
    [plt.plot(ri[1], ri[2], '.') for ri in r]
示例#14
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
示例#15
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
示例#16
0
def perfectCyl1m(rays, align=np.zeros(6)):
    """
    Trace rays from perfect cylinder with potential misalignment
    Assume rays are traced to tangent plane of nominal optic position
    +z points back toward CGH
    Leave with reference frame at tangent plane of nominal surface
    """
    #Rotate reference frame so rays impinge toward -z
    tran.transform(rays, 0, 0, 0, 0, pi, 0)
    #Apply misalignment
    tran.transform(rays, *align)
    #Trace cylinder
    tran.transform(rays, 0, 0, 1000., 0, 0, 0)
    #Get cylindrical axis in +x direction
    tran.transform(rays, 0, 0, 0, 0, 0, pi / 2)
    surf.cyl(rays, 1000., nr=1.)
    tran.reflect(rays)
    tran.itransform(rays, 0, 0, 0, 0, 0, pi / 2)
    tran.itransform(rays, 0, 0, 1000., 0, 0, 0)
    #Go back to nominal tangent plane
    tran.itransform(rays, *align)
    surf.flat(rays, nr=1.)

    return
示例#17
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
示例#18
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])
示例#19
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
示例#20
0
def traceToTestOptic220(N, app=75.):
    """Trace a set of rays from the point source to the nominal
    test optic location
    Return the rays at the plane tangent to the nominal source position.
    """
    #Set up source
    div = app / 1935.033
    rays = sources.pointsource(div, N)
    #Trace through collimator
    tran.transform(rays, 0, 0, 1935.033, 0, 0, 0)
    surf.flat(rays, nr=1.)
    lenses.collimator6(rays)
    #Trace to CGH
    tran.transform(rays, 0, 0, 100., 0, 0, 0)
    #Apply proper CGH misalignment
    pdb.set_trace()
    tran.transform(rays, 0, 0, 0, -1. * pi / 180, 0, 0)
    #Trace through CGH
    surf.flat(rays, nr=1.)
    tran.refract(rays, 1., nsil)
    tran.transform(rays, 0, 0, 6.35, 0, 0, 0)
    surf.flat(rays, nr=nsil)
    tran.refract(rays, nsil, 1.)
    surf.zernphase(rays, cghcoeff, 80., 632.82e-6)
    #Reverse CGH misalignment
    tran.itransform(rays, 0, 0, 0, -1. * pi / 180, 0, 0)
    #Go to line focus
    tran.transform(rays, 0, 0, 0, 0, 1. * pi / 180, 0)
    surf.flat(rays, nr=1.)
    tran.transform(rays, 0, 0, line, 0, 0, 0)
    surf.flat(rays, nr=1.)
    #Go to test optic
    tran.transform(rays, 0, 0, 220., 0, 0, 0)
    surf.flat(rays, nr=1.)
    #Rotate reference frame so rays impinge toward -z
    tran.transform(rays, 0, 0, 0, 0, pi, 0)

    return rays
示例#21
0
def backToWFS220(rays):
    """
    Trace rays from nominal test optic tangent plane back to WFS plane.
    This function can also be used with a point source to determine the
    Optimal focus positions of the field lenses.
    +z points toward CGH.
    """
    #Back to CGH
    tran.transform(rays, 0, 0, 220 + line, 0, 0, 0)
    surf.flat(rays, nr=1.)
    #Trace back through CGH
    tran.transform(rays, 0, 0, 0, 0, 1. * pi / 180, 0)
    tran.transform(rays, 0, 0, 0, 1. * pi / 180, 0, 0)
    surf.flat(rays, nr=1.)
    surf.zernphase(rays, cghcoeff, 80., 632.82e-6)
    tran.refract(rays, 1., nsil)
    tran.transform(rays, 0, 0, 6.35, 0, 0, 0)
    surf.flat(rays, nr=nsil)
    tran.refract(rays, nsil, 1.)
    tran.itransform(rays, 0, 0, 0, 1. * pi / 180, 0, 0)
    #Go to collimator
    tran.transform(rays, 0, 0, 100, 0, 0, 0)
    surf.flat(rays, nr=1.)
    lenses.collimator6(rays, reverse=True)
    #Go to focus
    tran.transform(rays, 0, 0, 1934.99719 - 100., 0, 0, 0)
    surf.flat(rays, nr=1.)
    #Place to AC-508-250
    lenses.AC508_250(rays, reverse=True)
    #Go to WFS location
    ##    tran.transform(rays,0,0,foc,0,0,0)
    ##    surf.flat(rays,nr=.1)
    tran.transform(rays, 0, 0, foc, 0, 0, 0)
    surf.flat(rays, nr=1.)

    #Go to cylindrical field lens
    tran.transform(rays, 0, 0, -cylz, 0, 0, 0)
    surf.flat(rays, nr=1.)
    tran.transform(rays, 0, 0, 0, 0, 0, pi / 2)
    lenses.LJ1516_L2(rays, reverse=False)
    tran.itransform(rays, 0, 0, 0, 0, 0, pi / 2)
    tran.itransform(rays, 0, 0, -cylz, 0, 0, 0)
    #Back to WFS
    surf.flat(rays, nr=1.)

    return anal.rmsY(rays)
示例#22
0
def backToWFS1m(rays, cghalign=np.zeros(6)):
    """
    Trace rays from nominal test optic tangent plane back to WFS plane.
    This function can also be used with a point source to determine the
    Optimal focus positions of the field lenses.
    +z points toward CGH.
    """
    #Reverse x,z misalignments
    for i in [0, 2, 3, 5]:
        cghalign[i] = -cghalign[i]
    #Back to CGH
    tran.transform(rays, 0, 0, 1000 + line1m, 0, 0, 0)
    surf.flat(rays, nr=1.)
    #Trace back through CGH
    tran.transform(rays, *cghalign)
    surf.zernphase(rays, -cgh1m, 80., 632.82e-6)
    tran.refract(rays, 1., nsil)
    tran.transform(rays, 0, 0, 6.35, 0, 0, 0)
    surf.flat(rays, nr=nsil)
    tran.refract(rays, nsil, 1.)
    tran.itransform(rays, *cghalign)
    tran.transform(rays, 0, 0, 0, -10. * pi / 180, 0, 0)
    #Go to collimator
    tran.transform(rays, 0, 0, 100, 0, 0, 0)
    surf.flat(rays, nr=1.)
    lenses.collimator6(rays, reverse=True)
    #Go to focus
    tran.transform(rays, 0, 0, 1934.90059 - 100., 0, 0, 0)
    surf.flat(rays, nr=1.)
    #Place to AC-508-250
    lenses.AC508_250(rays, reverse=True)
    #Go to WFS location
    ##    tran.transform(rays,0,0,foc,0,0,0)
    ##    surf.flat(rays,nr=.1)
    tran.transform(rays, 0, 0, foc1m, 0, 0, 0)

    #Go to cylindrical field lens
    tran.transform(rays, 0, 0, -cylz1m, 0, 0, 0)
    surf.flat(rays, nr=1.)
    tran.transform(rays, 0, 0, 0, 0, 0, pi / 2)
    lenses.LJ1144_L2(rays, reverse=False)
    tran.itransform(rays, 0, 0, 0, 0, 0, pi / 2)
    tran.itransform(rays, 0, 0, -cylz1m, 0, 0, 0)
    #Back to WFS
    surf.flat(rays, nr=1.)

    return anal.rmsY(rays)
示例#23
0
def traceToTestOptic1m(N, app=75., coloffset=0., cghalign=np.zeros(6)):
    """Trace a set of rays from the point source to the nominal
    test optic location
    Return the rays at the plane tangent to the nominal source position.
    """
    #Set up source
    div = app / 1935.033
    rays = sources.pointsource(div, N)
    #Trace through collimator
    tran.transform(rays, 0, 0, 1935.033 + coloffset, 0, 0, 0)
    surf.flat(rays, nr=1.)
    lenses.collimator6(rays)
    ##    tran.transform(rays,0,0,-coloffset,0,0,0)
    #Trace to CGH
    tran.transform(rays, 0, 0, 100., 0, 0, 0)
    #Apply proper CGH misalignment
    tran.transform(rays, 0, 0, 0, -10. * pi / 180, 0, 0)
    #Apply CGH misalignment
    tran.transform(rays, *cghalign)
    #Trace through CGH
    surf.flat(rays, nr=1.)
    tran.refract(rays, 1., nsil)
    tran.transform(rays, 0, 0, 6.35, 0, 0, 0)
    surf.flat(rays, nr=nsil)
    tran.refract(rays, nsil, 1.)
    surf.zernphase(rays, -cgh1m, 80., 632.82e-6)
    #Reverse CGH misalignment
    tran.itransform(rays, *cghalign)
    #Go to line focus
    line = surf.focusY(rays, nr=1.)
    #Go to test optic
    tran.transform(rays, 0, 0, 1000., 0, 0, 0)
    surf.flat(rays, nr=1.)
    #Go to 1m cylindrical radius of curvature
    px, py = anal.measurePower(rays, 200, 200)
    tran.transform(rays, 0, 0, 1000 + py, 0, 0, 0)
    surf.flat(rays, nr=1.)

    return rays, line
示例#24
0
def traceWedge(rays, t=25., wang=1. * np.pi / 180, pang=45. * np.pi / 180):
    """
    Make two copies of rays and trace through a wedged plate.
    Ignore multiple reflections.
    Interpolate one OPD onto the other, take difference
    modulo wavelength
    t = plate thickness (at narrow end)
    ang = wedge angle
    """
    #Make copy
    rays2 = np.copy(rays)

    #Trace first set
    ref1 = [tran.tr.identity_matrix()] * 4
    pdb.set_trace()
    tran.transform(rays, 0, 0, 300., pang, 0, 0, coords=ref1)
    surf.flat(rays, nr=1.)
    tran.reflect(rays)
    tran.transform(rays, 0, 0, 0, np.pi / 2 - pang, 0, 0, coords=ref1)
    tran.transform(rays, 0, 0, -300., 0, 0, 0, coords=ref1)
    ##    tran.steerY(rays,coords=ref1)
    surf.flat(rays, nr=1.)

    #Trace second set
    ref2 = [tran.tr.identity_matrix()] * 4
    pdb.set_trace()
    tran.transform(rays2, 0, 0, 300., pang, 0, 0, coords=ref2)
    surf.flat(rays2, nr=1.)
    #Refract into glass and reflect
    tran.refract(rays2, 1., nSiO2)
    tran.transform(rays2, 0, 0, t, 0, wang, 0, coords=ref2)
    surf.flat(rays2, nr=nSiO2)
    tran.reflect(rays2)
    #Refract out of glass
    ##    tran.itransform(rays2,0,0,t,wang,0,0,coords=ref2)
    tran.transform(rays2, 0, 0, 0, 0, -wang, 0, coords=ref2)
    tran.transform(rays2, 0, 0, -t, 0, 0, 0, coords=ref2)
    surf.flat(rays2, nr=nSiO2)
    tran.refract(rays2, nSiO2, 1.)
    #Go to focal plane
    rays2 = tran.applyT(rays2, ref2, inverse=True)
    rays2 = tran.applyT(rays2, ref1)
    surf.flat(rays2, nr=1.)

    #Both sets of rays at same plane, should have shear and tilt
    #Interpolate OPDs onto common grid
    opd1,dx,dy = anal.interpolateVec(rays,0,200,200,\
                               xr=[rays[1].min(),rays[1].max()],\
                               yr=[rays2[2].min(),rays[2].max()])
    opd2 = anal.interpolateVec(rays2,0,200,200,\
                               xr=[rays[1].min(),rays[1].max()],\
                               yr=[rays2[2].min(),rays[2].max()])[0]

    #Convert to complex phase
    opd1 = opd1 / .000635 * 2 * np.pi % (2 * np.pi)
    opd2 = opd2 / .000635 * 2 * np.pi % (2 * np.pi)
    opd1 = np.exp(1j * opd1)
    opd2 = np.exp(1j * opd2)

    #Compute intensity/interferogram
    return np.abs(opd1 + opd2)**2
示例#25
0
def test(N,rin=700.,rout=737.,azwidth=66.,srcdist=89.61e3+1.5e3,\
         hubdist=11832.911,yaw=0.,wave=6.,order=1,\
         opgalign=[0,0,0,0,0,0],f=None,\
         rrays=False,glob=False,rcen=False,\
         groll=0.,gyaw=0.,gpitch=0.,\
         scatter=False,coordin=None,\
         radapprox=False):
    """
    Trace through the SPO module, then place the OPG module
    at its nominal position, allowing for misalignments about the
    center of the OPG module. The module tolerances can be
    investigated by a coordinate transformation around the
    OPG module placement.
    """
    #Trace through SPO module
    rays = traceSPO(N,rin=rin,rout=rout,azwidth=azwidth,srcdist=srcdist,\
                    scatter=scatter)

    #Find the nominal OPG module location using formalism
    #from Flanagan's SPIE paper
    #Go to focus, steer out X and Y, then go up a distance
    #defined using Flangan formula, this should leave you
    #at the center of the beam, therefore the center of the
    #OPG module
    if coordin is None:
        coords = [tran.tr.identity_matrix()]*4
        tran.transform(rays,0,0,0,0,-np.mean(rays[4]),0,coords=coords)
        #tran.steerX(rays,coords=coords)
        #tran.steerY(rays,coords=coords)
        tran.transform(rays,0,0,0,pi-np.mean(rays[5]),0,0,coords=coords)
        f0 = surf.focusI(rays,coords=coords)
        tran.transform(rays,np.mean(rays[1]),np.mean(rays[2]),0,0,0,0,\
                       coords=coords)
        tran.transform(rays,0,0,0,0,pi,0,coords=coords)
        tran.transform(rays,0,0,11832.911*np.cos(1.5*np.pi/180),0,0,0,coords=coords)
        tran.transform(rays,0,0,0,0,1.5*np.pi/180,0,coords=coords)
    else:
        rays = tran.applyT(rays,coordin)
        coords = np.copy(coordin)
    surf.flat(rays)
    #Now at center of central grating, with -z pointing toward hub
    tran.transform(rays,*opgalign,coords=coords)
    rays,record = traceOPG(rays,hubdist=hubdist,yaw=yaw,wave=wave,order=order,\
                           gyaw=gyaw,groll=groll,gpitch=gpitch,\
                           radapprox=radapprox)
    tran.itransform(rays,*opgalign,coords=coords)
    #Should be at same reference frame, with rays now diffracted
    if np.sum(record)==0:
        pdb.set_trace()
    rays = tran.vignette(rays,ind=record>0)
    record = record[record>0]

    #Trace to detector and determine LSF
    rays = tran.applyT(rays,coords,inverse=True)
    #surf.focusI(rays)
    if f is not None:
        try:
            tran.transform(rays,0,0,-f,0,0,0)
            surf.flat(rays)
        except:
            pdb.set_trace()

    if rcen is True:
        return anal.centroid(rays)

    if rrays is True:
        if glob is True:
            tran.transform(rays,0,0,f,0,0,0)
        return rays,record

    #Return LSF in arcseconds
    return anal.hpdY(rays)/12e3*180/pi*60**2
示例#26
0
def testRadApprox(num,order=1,wave=1.,radapprox=False,N=3,f=None,yaw=0.,\
                  azwidth=66.*.68,autofocus=False,returnMet=False,axwidth=2.5):
    """

    """
    #Set up converging source
    rays = source.convergingbeam2(12e3,-azwidth/2,azwidth/2,\
                                  -axwidth/2,axwidth/2,num,0.)
    tran.transform(rays,0,0,12e3,0,0,0)
    tran.transform(rays,0,0,0,88.5*np.pi/180.,0,0)
    tran.transform(rays,0,0,0,0,0,yaw)
    surf.flat(rays)

    #Place grating
    if radapprox is False:
        tran.reflect(rays)
        tran.transform(rays,0,-12e3,0,0,0,0)
        tran.radgrat(rays,160./12e3,order,wave)
        tran.transform(rays,0,12e3,0,0,0,0)
        tran.transform(rays,0,0,0,0,0,-yaw)
    else:
        tran.reflect(rays)
        gratedges = np.linspace(-50.,50.,N+1)
        for i in range(N):
            ind = np.logical_and(rays[2]>gratedges[i],\
                             rays[2]<gratedges[i+1])
            d = (12e3+np.mean(gratedges[i:i+2]))/12e3*160.
            if np.sum(ind)>0:
                tran.grat(rays,d,-order,wave,ind=ind)
        tran.transform(rays,0,0,0,0,0,-yaw)


    #Go to focal plane
    tran.transform(rays,0,0,0,-88.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)/12e3*180/np.pi*60**2
    
    return rays
示例#27
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
示例#28
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
示例#29
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
示例#30
0
def traceOPG(rays,hubdist=11832.911,yaw=0.,order=1,wave=1.,ang=2.5/11832.911,\
             gpitch=0.,gyaw=0.,groll=0.,\
             radapprox=False):
    """
    Trace the OPG module. Probably ignore vignetting again.
    Place perfect OPG surfaces at the correct angular distance
    to make this a reasonable approximation.
    Assume reference frame is in center of module with -z
    pointing toward hub - achieved with steerX/steerY and
    rotate inc before this function call
    Create vector to keep track of which grating each ray
    diffracts from. Separate LSFs can be identified using
    this vector.
    """
    #Establish starting coordinate system
    coords = [tran.tr.identity_matrix()]*4
    #Get -x pointing to hub
    #Question whether to rotate about z to swap x and y
    tran.transform(rays,0,0,0,0,0,-pi/2,coords=coords)
    tran.transform(rays,0,0,0,pi/2,0,0,coords=coords)
    #Go to hub, then rotate to extreme grating surface
    tran.transform(rays,0,0,0,0,0,yaw,coords=coords) #possible blaze
    tran.transform(rays,0,-11832.911,0,0,0,0,coords=coords)
    tran.transform(rays,0,0,0,-ang*7,0,0,coords=coords) #minus sign ambiguity
    #Loop through gratings, tracing rays
    left = np.repeat(True,len(rays[1]))
    record = np.zeros(len(rays[1]))
    for i in range(15):
        #If no rays left, we are done
        if np.sum(left) == 0:
            continue
        #Rays with small incidence angle removed
        indg = np.abs(np.arcsin(rays[6])) > .001
        ind = np.logical_and(left,indg)
        if np.sum(ind)==0:
            tran.transform(rays,0,0,0,ang,0,0,coords=coords)
            continue
        #Trace rays to surface
        tyaw = np.random.uniform(low=-gyaw,high=gyaw)
        tpitch = np.random.uniform(low=-gpitch,high=gpitch)
        troll = np.random.uniform(low=-groll,high=groll)
        tran.transform(rays,0,11832.911,0,0,0,0,ind=ind)
        tran.transform(rays,0,0,0,tpitch,troll,tyaw,ind=ind)
        surf.flat(rays,ind=ind)
        tran.itransform(rays,0,0,0,tpitch,troll,tyaw,ind=ind)
        tran.itransform(rays,0,11832.911,0,0,0,0,ind=ind)
        #Identify relevant rays
        ind = np.logical_and(rays[2]>11832.911-96./2,rays[2]<11832.911+96./2)
        ind = np.logical_and(ind,left)
        #Remove these rays from the set that remain
        left = np.logical_and(left,np.invert(ind))
        if np.sum(ind)==0:
            tran.transform(rays,0,0,0,ang,0,0,coords=coords)
            continue
        #Record which grating these rays diffracted from
        record[ind] = i+1
        #Diffract this set of rays
        tran.reflect(rays,ind=ind)
        tran.transform(rays,0,11832.911-hubdist,0,0,0,0,coords=coords)
        
        if radapprox is False:
            tran.radgrat(rays,160./hubdist,order,wave,ind=ind)
        else:
            ind3 = np.logical_and(rays[2]<11832.911+48.,\
                                 rays[2]>11832.911+48-9.282)
            ind4 = np.logical_and(ind3,ind)
            if np.sum(ind4)>0:
                tran.grat(rays,160.,order,wave,ind=ind4)

            ind3 = np.logical_and(rays[2]<11832.911+48.-9.282,\
                                 rays[2]>11832.911+48-9.282-18.564)
            ind4 = np.logical_and(ind3,ind)
            if np.sum(ind4)>0:
                tran.grat(rays,159.75,order,wave,ind=ind4)

            ind3 = np.logical_and(rays[2]<11832.911+48.-9.282-18.564,\
                                 rays[2]>11832.911+48-9.282-18.564*2)
            ind4 = np.logical_and(ind3,ind)
            if np.sum(ind4)>0:
                tran.grat(rays,159.5,order,wave,ind=ind4)

            ind3 = np.logical_and(rays[2]<11832.911+48.-9.282-18.564*2,\
                                 rays[2]>11832.911+48-9.282-18.564*3)
            ind4 = np.logical_and(ind3,ind)
            if np.sum(ind4)>0:
                tran.grat(rays,159.25,order,wave,ind=ind4)

            ind3 = np.logical_and(rays[2]<11832.911+48.-9.282-18.564*3,\
                                 rays[2]>11832.911+48-9.282-18.564*4)
            ind4 = np.logical_and(ind3,ind)
            if np.sum(ind4)>0:
                tran.grat(rays,159.,order,wave,ind=ind4)

            ind3 = np.logical_and(rays[2]<11832.911+48.-9.282-18.564*4,\
                                 rays[2]>11832.911+48-9.282-18.564*4-12.462)
            ind4 = np.logical_and(ind3,ind)
            if np.sum(ind4)>0:
                tran.grat(rays,158.75,order,wave,ind=ind4)
            #pdb.set_trace()
            
        tran.transform(rays,0,hubdist-11832.911,0,0,0,0,coords=coords)
        #Rotate to next grating
        tran.transform(rays,0,0,0,ang,0,0,coords=coords)
    #Go back to original coordinate system
    rays = tran.applyT(rays,coords,inverse=True)

    return rays,record