Beispiel #1
0
def traceThroughPrimary(rays,mask,primalign=np.zeros(6),\
                        detalign=np.zeros(6),primCoeffs=None,cenSig=0.):
    """
    Trace rays through the primary mirror and then down to a focus.
    Need to simulate an initial misalignment and then applying
    an optimization algorithm to align primary to beam.
    Merit function should include the random error in spot centroiding
    primCoeffs is a list of coefficients, axial orders, and azimuthal orders
    Use global coordinate systems to determine sign conventions
    """
    #Move to primary reference frame - rays 200 mm above node
    tran.transform(rays, 0, 0, -200., 0, 0, 0)
    glo = [tran.tr.identity_matrix()] * 4
    #Move to mirror tangent point and apply misalignment
    tran.transform(rays,
                   conic.primrad(8450., 220., 8400.),
                   0,
                   50,
                   0,
                   0,
                   0,
                   coords=glo)
    tran.transform(rays, 0, 0, 0, *primalign[3:], coords=glo)
    tran.itransform(rays,
                    conic.primrad(8450., 220., 8400.),
                    0,
                    50,
                    0,
                    0,
                    0,
                    coords=glo)
    tran.transform(rays, 0, 0, -8400., 0, 0, 0, coords=glo)
    #Trace to Wolter surface
    if primCoeffs is None:
        surf.wolterprimary(rays, 220., 8400.)
    else:
        surf.primaryLL(rays,220.,8400.,8500.,8400.,100./220.,\
                       *primCoeffs)
    rays = tran.applyT(rays, glo, inverse=True)
    #Rays are now at primary in global coordinate system
    #(origin on optical axis and at nominal node height)
    #Now reflect and trace down to the detector
    tran.reflect(rays)
    tran.transform(rays, 0, 0, -conic.primfocus(220., 8400.), 0, 0, 0)
    #Apply detector misalignment
    tran.transform(rays, *detalign)
    surf.flat(rays)
    #Pick out spot centroids
    cen = [anal.centroid(rays, weights=mask == i) for i in range(mask[-1] + 1)]
    cen = np.transpose(np.array(cen))
    #Add centroiding error
    if cenSig > 0:
        cen = cen + np.random.normal(scale=cenSig, size=np.shape(cen))

    return cen
Beispiel #2
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])
Beispiel #3
0
def findGratingPosition(N, hubdist=11832.911, order=1, wave=4.4, disp=0.):
    """Place the SPO pair, find the focus, and then go back
    up to grating placement
    """
    #Set up SPO
    rays = traceSource(N)
    placeSPO(rays)
    #SPO intersection plane is global coordinate system

    #Go to focus
    gratc = [tran.tr.identity_matrix()] * 4
    surf.focusI(rays, coords=gratc)
    #Go back up to grating point
    tran.transform(rays,
                   0,
                   0,
                   np.mean(-11828.856 * rays[6]),
                   0,
                   0,
                   0,
                   coords=gratc)
    surf.flat(rays)

    #Place grating
    #Get to XY centroid of beam, now at center of grating
    tran.transform(rays, np.mean(rays[1]), 0, 0, 0, 0, 0, coords=gratc)
    gratc2 = np.copy(gratc)
    #Rotate to proper incidence angle
    tran.steerX(rays, coords=gratc2)
    tran.transform(rays, 0, 0, 0, 0, pi / 2 - 1.5 * pi / 180, 0, coords=gratc2)
    surf.flat(rays)
    tran.transform(rays, 0, 0, 0, 0, 0, pi / 2, coords=gratc2)
    #Go to hub and diffract
    #Add yaw
    yaw = grat.blazeYaw(1.5 * pi / 180, 2.4, 3, 160.)
    tran.transform(rays, 0, 0, 0, 0, 0, yaw, coords=gratc2)
    tran.transform(rays, 0, -hubdist + disp, 0, 0, 0, 0, coords=gratc2)
    tran.reflect(rays)
    tran.radgrat(rays, 160. / hubdist, order, wave)
    pdb.set_trace()
    #Go back to reference frame of grating
    rays = tran.applyT(rays, gratc2, inverse=True)  #Back to global
    #rays = tran.applyT(rays,gratc) #forward to grating

    #Go to focus
    focusc = [tran.tr.identity_matrix()] * 4
    surf.focusY(rays, coords=focusc)
    #Get rid of mean X and Y
    tran.transform(rays,np.mean(rays[1]),np.mean(rays[2]),0,0,0,0,\
                   coords=focusc)

    return rays,[gratc[1][i][-1] for i in range(3)],\
           [focusc[1][i][-1] for i in range(3)]
Beispiel #4
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
Beispiel #5
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
Beispiel #6
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
Beispiel #7
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
Beispiel #8
0
def gratArray(rays,outerrad,hubdist,angle,inc,l=95.,bestFocus=None,\
              weights=None,order=0,blazeYaw=0.,wave=1.,offX=0.,\
              coords=None,vis=False):
    """Trace rays leaving SPO petal to the fanned grating array.
    Start with outermost radius and rotate grating array about
    the hub. Define outermost grating position by max ray radius
    at desired axial height.
    Rays have been traced to bottom of outermost grating.
    """
    #Visualization bookkeeping
    xg, yg, zg = [np.zeros(len(rays[1]))] * 3

    x, y = rays[1:3]
    #Dummy rays to ensure return of reference frame
    ##    rays2 = sources.subannulus(220.,223.,10.*pi/180,100)
    #Put origin at bottom of outermost grating
    tran.transform(rays, outerrad, 0, 0, 0, 0, 0, coords=coords)
    ##    PT.transform(rays2,outerrad,0,0,0,0,0)
    #Go to proper incidence angle of grating
    tran.transform(rays, 0, 0, 0, 0, 0, -pi / 2, coords=coords)
    tran.transform(rays, 0, 0, 0, -pi / 2 - angle + inc, 0, 0, coords=coords)
    ##    PT.transform(rays2,0,0,0,0,0,-pi/2)
    ##    PT.transform(rays2,0,0,0,-pi/2-angle+inc,0,0)
    #Go to hub
    tran.transform(rays, 0, 0, 0, 0, 0, blazeYaw, coords=coords)  #Put in blaze
    tran.transform(rays, 0, hubdist, 0, 0, 0, 0, coords=coords)
    ##    PT.transform(rays2,0,0,0,0,0,blazeYaw) #Put in blaze
    ##    PT.transform(rays2,0,hubdist,0,0,0,0)
    #Trace out gratings until no rays hit a grating
    #Flat
    #Indices
    #Reflect
    #Apply Grating
    #Next
    #Edit to only flat rays with a substantial incidence angle
    indg = np.abs(np.arcsin(rays[6])) > .001
    surf.flat(rays, ind=indg)
    rho = -sqrt(x**2 + y**2) * np.sign(y)
    ind = np.logical_and(rho > hubdist, rho < l + hubdist)
    ##    pdb.set_trace()
    ind2 = np.copy(ind)
    #offx subtracted to prevent numerical vignetting...this
    #is accounted for with numerical factors, so don't want
    #any rays to be missed
    ang = l * sin(inc - offX) / hubdist * .95

    i = 0
    prev = np.copy(ind)
    #Loop condition needs to be rays not diffracted > 0
    while np.sum(prev) < len(rays[1]):
        i = i + 1
        if np.sum(ind2) > 0:
            tran.reflect(rays, ind=ind2)
            tran.radgrat(rays, 160. / hubdist, order, wave, ind=ind2)
        tran.transform(rays, 0, 0, 0, ang, 0, 0, coords=coords)
        ##        PT.transform(rays2,0,0,0,ang,0,0)
        indg = np.abs(np.arcsin(rays[6])) > .001
        indg = np.logical_and(np.invert(prev), indg)
        surf.flat(rays, ind=indg)
        ##        pdb.set_trace()
        #Determine rays hitting new grating
        rho = -sqrt(x**2 + y**2) * np.sign(y)
        ind = np.logical_and(rho > hubdist, rho < l + hubdist)
        ind2 = np.logical_and(np.invert(prev), ind)  #Remove previous rays
        prev = np.logical_or(prev, ind)  #Add rays hitting new grating
        #sys.stdout.write('%i \r' % i)
        #sys.stdout.flush()
    tran.reflect(rays, ind=ind2)
    tran.radgrat(rays, 160. / hubdist, order, wave, ind=ind2)

    ##    #Go to focal plane
    ##    PT.transform(rays,0,-hubdist,0,0,0,0)
    ##    PT.transform(rays,0,0,0,0,0,-blazeYaw) #Reverse blaze
    ##    #Currently at bottom point of innermost grating
    ##    pdb.set_trace()

    if vis is True:
        #Get hub position
        hub = tran.applyTPos(0, 0, 0, coords, inverse=True)
        pyfits.writeto('HubPos.fits', np.array(hub), clobber=True)

    #Get back to original outermost grating reference frame
    tran.transform(rays, 0, 0, 0, -ang * i, 0, 0, coords=coords)
    tran.transform(rays, 0, -hubdist, 0, 0, 0, 0, coords=coords)
    tran.transform(rays, 0, 0, 0, 0, 0, -blazeYaw, coords=coords)
    tran.transform(rays, 0, 0, 0, pi / 2 + angle - inc, 0, 0, coords=coords)
    tran.transform(rays, 0, 0, 0, 0, 0, pi / 2, coords=coords)
    tran.transform(rays, -outerrad, 0, 0, 0, 0, 0, coords=coords)

    ##    PT.transform(rays2,0,0,0,-ang*i,0,0)
    ##    PT.transform(rays2,0,-hubdist,0,0,0,0)
    ##    PT.transform(rays2,0,0,0,0,0,-blazeYaw)
    ##    PT.transform(rays2,0,0,0,pi/2+angle-inc,0,0)
    ##    PT.transform(rays2,0,0,0,0,0,pi/2)
    ##    PT.transform(rays2,-outerrad,0,0,0,0,0)

    #Export grating ray positions
    if vis is True:
        rays2 = tran.applyT(rays, coords, inverse=True)
        pyfits.writeto('GratingPos.fits',\
                       np.array([rays2[1],rays2[2],rays2[3]]),\
                       clobber=True)
        pdb.set_trace()

    #Should be there
    surf.flat(rays)

    ##    PT.transform(rays,0,hubdist,0,0,0,0)
    ##    PT.transform(rays,0,0,0,-ang*i+pi/2+angle-inc,0,0)
    ##    PT.transform(rays,0,0,0,0,0,pi/2)
    ##    PT.flat(rays)

    #Find focus
    if bestFocus is None:
        return surf.focusY(rays, weights=weights)


##
##    #Focus already found, tracing diffracted line
##    PT.transform(rays,0,0,bestFocus,0,0,0)
##    PT.flat(rays)

    return None