示例#1
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
示例#2
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
示例#3
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
示例#4
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
示例#5
0
def sensitivityPlots(dof, mag):
    """
    Mark the RMS spread and centroid shift of focus
    as function of DoF
    """
    align = np.repeat(0., 6)
    misalign = np.linspace(0, mag, 100)
    cx = []
    rms = []
    for m in misalign:
        align[dof] = m
        rays = distortTrace(*align)
        cx.append(anal.centroid(rays)[0])
        rms.append(anal.rmsCentroid(rays))

    return cx, rms
示例#6
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
示例#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
示例#8
0
def traceArcus(N,span=20.,d=.605,t=.775,gap=50.,\
                inc=1.5*pi/180,l=95.,bestFocus=bestfoc,order=0,\
                blazeYaw=yaw,wave=1.,marg=marg,findMargin=False,\
                analyzeLine=True,offX=0.,offY=0.,calcCentroid=False,\
               vis=False):
    """Trace Arcus sector
    """

    sys.stdout.write(str(wave) + '\t' + str(order) + '\r')
    sys.stdout.flush()

    if wave is not 'uniform':
        #Compute efficiency and determine whether to proceed
        geff = gratEff(order)
        #Add in grating efficiency and CCD QE
        #geff and ccdQE need to be arrays if wave is array
        g = geff(wave)
        det = ccdQE(wave)
        if g * det == 0.:
            return 0, 0
        g = g.reshape(np.size(g))

    #Assign random wavelength to each ray
    if wave == 'uniform':
        rays,weights,minfoc,lmax,wave,coords = defineSPOaperture(N,wave,\
                                offX=offX,offY=offY,\
                                vis=vis)

    else:
        rays,weights,minfoc,lmax,coords = defineSPOaperture(N,wave,offX=offX,\
                                offY=offY,\
                                vis=vis)

    #Trace rays through SPO modules

##    rays = plotting.pload('/home/rallured/Dropbox/Arcus/'
##                 'Raytrace/Performance/160516_SPORays.pkl')
##    weights = pyfits.getdata('/home/rallured/Dropbox/Arcus/'
##                             'Raytrace/Performance/160516_Weights.fits')
##    minfoc = 11972.53195
##    lmax = 115.97497
##    pdb.set_trace()

#Determine outermost radius of grating array
#outerrad should be fixed
    outerrad = outerradNom  #np.max(sqrt(rays[1]**2+rays[2]**2))
    foc = tran.applyTPos(0, 0, 0, coords, inverse=True)
    hubdist = sqrt(outerrad**2 + foc[2]**2)
    angle = np.arctan(outerrad / (minfoc - (lmax + gap + 95.)))
    thetag = angle - 1.5 * pi / 180.

    ##    print 'Outerrad: %f\nHubdist: %f\nLmax: %f\nOuter Focus: %f\n' % \
    ##          (outerrad,hubdist,L.max(),focVec[-1])

    #Trace grating array - need to add in grating efficiency and
    #CCD quantum efficiency
    if bestFocus is None:
        return gratArray(rays,outerrad,hubdist,angle,inc,l=l,\
                         weights=weights,order=-3,blazeYaw=blazeYaw,\
                         wave=2.4,coords=coords)
##        return traceSector(Rin,Rout,F,N,span=span,d=d,t=t,gap=gap,\
##                inc=inc,l=l,bestFocus=bestFocus,order=order,\
##                blazeYaw=blazeYaw,wave=wave,marg=marg)

    gratArray(rays,outerrad,hubdist,angle,inc,l=l,bestFocus=bestFocus,\
                  weights=weights,order=order,blazeYaw=blazeYaw,wave=wave,\
              offX=offX,vis=vis,coords=coords)

    #Grating vignetting
    weights = weights * (1 - abs(offX) / inc)

    if np.size(wave) == 1:
        #Account for grating efficiency
        weights = weights * g * det

    #Vignette rays with no weight (evanescence)
##    rays = tran.vignette(rays,weights>0.)
##    if len(rays[1])==0:
##        return 0.,0.

#Go to focal plane
    tran.transform(rays, 0, 0, bestFocus, 0, 0, 0, coords=coords)
    surf.flat(rays)

    if vis is True:
        pyfits.writeto('FocalPlanePos.fits',\
                       np.array([rays[1],rays[2],rays[3]]),\
                       clobber=True)
        pyfits.writeto('Wavelengths.fits',\
                       wave,clobber=True)

    if analyzeLine is False:
        return rays, weights

    #Get rid of outliers
    ind = np.abs(rays[2] - np.average(rays[2])) < 10.
    rays = PT.vignette(rays, ind=ind)
    weights = weights[ind]

    if calcCentroid is True:
        cent = anal.centroid(rays, weights=weights)
        if cent[0] < 100 or cent[1] < 100:
            pdb.set_trace()
        return anal.centroid(rays, weights=weights)

    #Get rid of rays that made it through


##    ind = rays[1] > 0
##    rays = PT.vignette(rays,ind=ind)
##    weights = weights[ind]

#If no rays made it through
    if np.size(rays[1]) == 0:
        return 0, 0, 0, 0

    #Look at resolution of this line
    try:
        cy = np.average(rays[2], weights=weights)
    except:
        pdb.set_trace()
    if findMargin is True:
        #Compute FWHM after Gaussian convolution
        fwhms = np.linspace(1, 3, 201) / 60.**2 * pi / 180 * 12e3
        tot = np.array([convolveLSF(rays,.001,m,weights=weights)\
                        for m in fwhms/2.35])
        #Convert to arcsec, return std of margin convolution
        marg = fwhms[np.argmin(
            np.abs(tot / 12e3 * 180 / pi * 60**2 - 3.))] / 2.35
        return marg, rays
    fwhm = convolveLSF(rays, .001, marg, weights=weights)
    resolution = cy / fwhm
    weights = weights**.799 * .83 * .8 * .9  #Grat plates, azimuthal ribs, packing
    area = np.sum(weights)
    #print resolution
    #print area
    #print sqrt((cy/3000)**2 - lsf**2)/F * 180/pi*60**2
    ##    print 'Order: %i, Wave: %.2f\n'%(order,wave)
    return resolution, area, np.nanmean(rays[1]), np.nanmean(rays[2]),fwhm,\
           rays,weights