예제 #1
0
def CenterStar(filename, camera='GUIDE'):
    """Determine pixel location of a star that is supposed to be centered in the field
    of view, camera type selects between GUIDE camera and FRINGE camera."""
    if camera=='GUIDE':
        print 'Centroid GUIDE'
        hdu = pyfits.open(filename)
        data = hdu[0].data
        stars = PyGuide.findStars(data, mask, satMask, ccdInfo, thresh, radMult, rad, verbosity, doDS9)
        initialxy = stars[0][0].xyCtr
        centroid = PyGuide.Centroid.centroid(data, mask, satMask, initialxy, rad, ccdInfo)
        #put centroids into x,y
        xy = centroid.xyCtr
        print xy
        
    if camera=='FRINGE':
        import Image, numpy
        rad = 150
        ccdInfo = PyGuide.CCDInfo(2.0, 1.5, 1.5, 256)
        
        im = Image.open(filename)
        imarray = numpy.array(im)
        stars = PyGuide.findStars(imarray, mask, satMask, ccdInfo, thresh, radMult, rad, verbosity, doDS9)
        initialxy = stars[0][0].xyCtr
        centroid = PyGuide.Centroid.centroid(imarray, mask, satMask, initialxy, rad, ccdInfo)
        #put centroids into x,y
        xy = centroid.xyCtr
        print xy
        im.show()
        print 'Centroid FRINGE'
예제 #2
0
def doFindStars(
    imName = None,
    maskName = None,
    satMaskName = None,
    invertMask = False,
    **kargs
):
    """Find stars and centroid and shape-fit them.
    
    Inputs:
    - all the arguments for loadFiles plus values shown by showDef
    """
    global isSat, sd
    im, mask, satMask = loadFiles(imName, maskName, satMaskName, invertMask)
    
    # check keyword arguments
    for paramName in kargs:
        if paramName not in FindParamNames:
            raise RuntimeError("Invalid argument: %s" % (paramName,))
    
    # fill in defaults
    globalDict = globals()
    for paramName in FindParamNames:
        if paramName not in kargs:
            kargs[paramName] = globalDict[paramName]
    
    # split off ccd info
    ccdInfoDict = {}
    for paramName in CCDInfoNames:
        ccdInfoDict[paramName] = kargs.pop(paramName)
    ccdInfo = PyGuide.CCDInfo(**ccdInfoDict)
    
    # find stars and centroid
    print("Calling PyGuide.findStars")
    ctrDataList, imStats = PyGuide.findStars(
        data = im,
        mask = mask,
        satMask = satMask,
        ccdInfo = ccdInfo,
    **kargs)

    print("%s stars found:" % (len(ctrDataList),))
    printStarHeader()
    for ctrData in ctrDataList:
        # measure star shape
        try:
            shapeData = PyGuide.starShape(
                data = im,
                mask = mask,
                xyCtr = ctrData.xyCtr,
                rad = ctrData.rad,
            )
        except RuntimeError as e:
            print("starShape failed: %s" % (e,))
            shapeData = PyGuide.StarShapeData()

        printStarData(ctrData, shapeData)
예제 #3
0
파일: flow.py 프로젝트: csayres/autoPhot
 def findSources(self, imgData):
     """get a list of automatically detected sources
     """
     # Set up Hash Table for the 1st image (which all others will be compared to)
     refCoords, stats = PyGuide.findStars(imgData, None, None, self.ccd)
     #refCoords = numpy.asarray(refCoords) - 0.5 # origin is offset by half a pixel width
     # extract xy centers and just keep the NBRIGHTSTARS
     num = min(len(refCoords), NBRIGHTSTARS)
     refCoords = numpy.asarray([refCoords[j].xyCtr for j in range(num)])
     return refCoords
예제 #4
0
def doFindStars(imName=None,
                maskName=None,
                satMaskName=None,
                invertMask=False,
                **kargs):
    """Find stars and centroid and shape-fit them.
    
    Inputs:
    - all the arguments for loadFiles plus values shown by showDef
    """
    global isSat, sd
    im, mask, satMask = loadFiles(imName, maskName, satMaskName, invertMask)

    # check keyword arguments
    for paramName in kargs:
        if paramName not in FindParamNames:
            raise RuntimeError("Invalid argument: %s" % (paramName, ))

    # fill in defaults
    globalDict = globals()
    for paramName in FindParamNames:
        if paramName not in kargs:
            kargs[paramName] = globalDict[paramName]

    # split off ccd info
    ccdInfoDict = {}
    for paramName in CCDInfoNames:
        ccdInfoDict[paramName] = kargs.pop(paramName)
    ccdInfo = PyGuide.CCDInfo(**ccdInfoDict)

    # find stars and centroid
    print("Calling PyGuide.findStars")
    ctrDataList, imStats = PyGuide.findStars(data=im,
                                             mask=mask,
                                             satMask=satMask,
                                             ccdInfo=ccdInfo,
                                             **kargs)

    print("%s stars found:" % (len(ctrDataList), ))
    printStarHeader()
    for ctrData in ctrDataList:
        # measure star shape
        try:
            shapeData = PyGuide.starShape(
                data=im,
                mask=mask,
                xyCtr=ctrData.xyCtr,
                rad=ctrData.rad,
            )
        except RuntimeError as e:
            print("starShape failed: %s" % (e, ))
            shapeData = PyGuide.StarShapeData()

        printStarData(ctrData, shapeData)
예제 #5
0
파일: imgutils.py 프로젝트: sdss/dewarp
def centeredcentroids(data, mask=None):
    """Finds centroids in an image, with (0,0) at the center of the image
    Parameters:
        data (ndarray):
            a 2d numpy array containing image data, assumed to be x row major
        mask (ndarray):
            a 2d numpy array containing binary image data (0 for do process and 1 for don't)
    
    Returns:
        xys (list):
            a list of interleaved xy positions
            these are the positions of the centroids in the image
    """
    centroids, stats = PyGuide.findStars(data, mask, None, PyGuide.CCDInfo(2176, 19, 2.1), thresh=10, radMult=1.0, rad=None, verbosity=0, doDS9=False)
    out = []
    for centroid in centroids:
        out.append(centroid.xyCtr[0]-data.shape[1]/2)
        out.append(centroid.xyCtr[1]-data.shape[0]/2)
    return out
예제 #6
0
파일: imgutils.py 프로젝트: sdss/dewarp
def unitdiskcentroids(data, mask=None):
    """Finds centroids in an image, with (0,0) at the center of the image and the largest possible circle around this (0,0) having magnitude 1
    Parameters:
        data (ndarray):
            a 2d numpy array containing image data, assumed to be x row major
        mask (ndarray):
            a 2d numpy array containing binary image data (0 for do process and 1 for don't)
    
    Returns:
        xys (list):
            a list of interleaved xy positions
            these are the positions of the centroids in the image
    """
    centroids, stats = PyGuide.findStars(data, mask, None, PyGuide.CCDInfo(2176, 19, 2.1), thresh=10, radMult=1.0, rad=None, verbosity=0, doDS9=False)
    out = []
    scale = min(data.shape[0],data.shape[1])/2
    for centroid in centroids:
        out.append((centroid.xyCtr[0]-data.shape[1]/2)/scale)
        out.append((centroid.xyCtr[1]-data.shape[0]/2)/scale)
    return out
예제 #7
0
파일: Guider.py 프로젝트: UWMRO/Guider
    def analyze(self,im): 
        output=[]
        hdulist = fits.open(im)
        data = hdulist[0].data

        ccd = PyGuide.CCDInfo(200,21.3,1.6) # Since we're using it on one CCD, these should be constants
        ctr,imstat = PyGuide.findStars(data,None,None,ccd,1,False)[0:2]

        size= len(ctr)
        xcoord = ['XCoord']
        ycoord = ['YCoord']
        names = ['StarName']

        for x in range(size):
            xcoord = ctr[x].xyCtr[0]
            ycoord = ctr[x].xyCtr[1]
            name = x
            star_out = [name, xcoord, ycoord]
            self.l.logStr('StarPos\t'+str(star_out), self.logType)
            output.append(star_out)
        return output
예제 #8
0
    def processImage(self, fScanFrame):
        """! Process a single image

        @param[in] fScanFrame: an FScanFrame obj

        """
        # print("processing img: ", os.path.split(imageFile)[-1])
        if fScanFrame.frame % 100 == 0:
            print("frame %i   %.2f done"%(fScanFrame.frame, float(fScanFrame.frame+1)/float(len(self.scanMovie.frames))*100))
        imgData = fScanFrame.getImg()
        # if fScanFrame.frame > 0:
        #     imgData = imgData - self.scanMovie.frames[fScanFrame.frame-1].getImg()#/ self.scanMovie.flatFile
        imageFile = "%i.fscanframe"%fScanFrame.frame
        motorPos = fScanFrame.motorpos
        counts = None
        xyCtr = None
        rad = None
        totalCounts = numpy.sum(imgData)
        # k = numpy.array([[.1,.1,.1],[.1,1,.1],[.1,.25,.1]])
        # imgData = scipy.ndimage.convolve(imgData, k)
        # imgData = scipy.ndimage.filters.median_filter(imgData, 3)
        try:
            pyGuideCentroids = PyGuide.findStars(imgData, None, None, CCDInfo)[0]
            # did we get any centroids?
            if pyGuideCentroids:
                counts = pyGuideCentroids[0].counts
                xyCtr = pyGuideCentroids[0].xyCtr
                rad = pyGuideCentroids[0].rad
        except Exception:
            print("some issue with pyguide on img (skipping): ", imageFile)
            traceback.print_exc()
        return dict((
                        ("imageFile", imageFile),
                        ("counts", counts),
                        ("xyCtr", xyCtr),
                        ("rad", rad),
                        ("motorPos", motorPos),
                        ("frame", fScanFrame.frame),
                        ("totalCounts", totalCounts)
                    ))
예제 #9
0
def findSpots(data):
    """Find the initial guess location of all spots to be tracked."""
    stars = PyGuide.findStars(data, mask, satMask, ccdInfo, thresh, radMult,
                              rad, verbosity, doDS9)
    return stars
예제 #10
0
def findSpots(data):
    """Find the initial guess location of all spots to be tracked."""
    stars = PyGuide.findStars(data, mask, satMask, ccdInfo, thresh, radMult, rad, verbosity, doDS9)
    return stars
if UseDS9:
    ds9Win = PyGuide.ImUtil.openDS9Win("testStarShape")
    if ds9Win:
        ds9Win.showArray(data)

mask = None
# use for image /Test\ Images/ecam/2004-04-27/gimg0170.fits
#mask = data < 0
#mask[64:101, 78:92] = 1

print "searching for stars"
ctrDataList, imStats = PyGuide.findStars(
    data = data,
    mask = mask,
    satMask = None,
    ccdInfo = CCDInfo,
    verbosity = 0,
    doDS9 = False,
)[0:2]
for ctrData in ctrDataList:
    xyCtr = ctrData.xyCtr
    rad = ctrData.rad
    print "star xyCtr=%.2f, %.2f, radius=%s" % (xyCtr[0], xyCtr[1], rad)
    
    shapeData = PyGuide.starShape(
        data,
        mask = mask,
        xyCtr = xyCtr,
        rad = rad,
    )
    if not shapeData.isOK:
예제 #12
0
def pyguide_checking(imgArray):
    """
    Uses PyGuide to find stars, get counts, and determine if new exposure time is necessary.

    Input:
    - imgArray  numpy array from the CCD

    Output:
    - True if exposure was good, False if bad
    - True if exposure time should be decreased, False if increased
    """
    # search image for stars
    centroidData, imageStats = PyGuide.findStars(imgArray,
                                                 mask=None,
                                                 satMask=None,
                                                 ccdInfo=CCDInfo)

    # keep track of targets
    goodTargets = []
    lowTargets = 0
    highTargets = 0

    print(
        "these are the %i stars pyguide found in descending order of brightness:"
        % len(centroidData))
    for centroid in centroidData:
        # for each star, measure its shape
        shapeData = PyGuide.starShape(
            np.asarray(
                imgArray,
                dtype="float32"),  # had to explicitly cast for some reason
            mask=None,
            xyCtr=centroid.xyCtr,
            rad=centroid.rad)
        if not shapeData.isOK:
            print("starShape failed: %s" % (shapeData.msgStr, ))
        else:
            print("xyCenter=[%.2f, %.2f] CCD Pixel Counts=%.1f, FWHM=%.1f, BKGND=%.1f, chiSq=%.2f" %\
                (centroid.xyCtr[0], centroid.xyCtr[1], shapeData.ampl,shapeData.fwhm, shapeData.bkgnd, shapeData.chiSq))
            #if shapeData.ampl < 0.2*MAX_COUNTS:
            #    lowTargets+=1
            #elif shapeData.ampl > 0.9*MAX_COUNTS:
            #    highTargets+=1
            #else:
            #    goodTargets.append([centroid,shapeData])
            goodTargets.append([centroid, shapeData])
    print()

    print(
        str(len(goodTargets)) +
        " targets are in the linear (20-90%) range --- " + str(lowTargets) +
        " low targets --- " + str(highTargets) + " high targets")

    ### highlight detections
    ### size of green circle scales with total counts
    ### bigger circles for brigher stars
    if DISPLAY_TARGETS:
        plt.clf()
        plt.imshow(imgArray, cmap="gray", vmin=200,
                   vmax=MAX_COUNTS)  # vmin/vmax help with contrast
        plt.ion()
        plt.show()
        for centroid in centroidData:
            xyCtr = centroid.xyCtr + np.array(
                [-0.5, -0.5]
            )  # offset by half a pixel to match imshow with 0,0 at pixel center rather than edge
            counts = centroid.counts
            plt.scatter(xyCtr[0],
                        xyCtr[1],
                        s=counts / MAX_COUNTS,
                        marker="o",
                        edgecolors="lime",
                        facecolors="none")
        plt.gca().invert_yaxis()
        plt.draw()
        plt.pause(0.1)

    # Successful exposure, return True. The False is thrown away
    #if len(goodTargets) >= 1:
    #    goodTargets = [goodTargets[0]]
    return goodTargets
예제 #13
0
def processImage(imageFile):
    """! Process a single image

    @param[in] imageFile. String

    """
    try:
        # global TZERO
        global MOTORSPEED
        global MOTORSTART
        global MOTOREND
        motorDirection = numpy.sign(MOTOREND-MOTORSTART)
        # frame = int(imageFile.split(IMGBASENAME)[-1].split(".")[0])
        # timestamp = os.path.getmtime(imageFile) - TZERO
        frame = None
        timestamp = None
        counts = None
        xyCtr = None
        rad = None
        totalCounts = None

        # put some filtering here
        # try:

        fitsImg = fits.open(imageFile)
        timestamp = fitsImg[0].header["TSTAMP"]
        frame = fitsImg[0].header["FNUM"]
        imgData = fitsImg[0].data
        fitsImg.close()

        if frame % 100 == 0:
            print("processing frame number %i"%frame)
        flatImg = imgData.flatten()
        thresh = flatImg[numpy.nonzero(flatImg>ROUGH_THRESH)]
        # print("median %.4f thresh %.4f  %i pixels over thresh"%(medianValue, sigma, len(thresh)))
        totalCounts = numpy.sum(thresh)

        pyGuideCentroids = PyGuide.findStars(imgData, PyGuideMask, None, CCDInfo)[0]
        # did we get any centroids?
        if pyGuideCentroids:
            counts = pyGuideCentroids[0].counts
            xyCtr = pyGuideCentroids[0].xyCtr
            rad = pyGuideCentroids[0].rad
        del imgData # paranoia

        # except Exception:
        #     print("some issue with pyguide on img (skipping): ", imageFile)
        #     traceback.print_exc()

        return dict((
                        ("imageFile", imageFile),
                        ("counts", counts),
                        ("xyCtr", xyCtr),
                        ("rad", rad),
                        ("motorPos", MOTORSTART + motorDirection*MOTORSPEED*timestamp),
                        ("frame", frame),
                        ("totalCounts", totalCounts),
                    ))
    except Exception:
        print("process Image failed:")
        traceback.print_exc(file=sys.stderr)
예제 #14
0
if UseDS9:
    ds9Win = PyGuide.ImUtil.openDS9Win("testStarShape")
    if ds9Win:
        ds9Win.showArray(data)

mask = None
# use for image /Test\ Images/ecam/2004-04-27/gimg0170.fits
#mask = data < 0
#mask[64:101, 78:92] = 1

print "searching for stars"
ctrDataList, imStats = PyGuide.findStars(
    data=data,
    mask=mask,
    satMask=None,
    ccdInfo=CCDInfo,
    verbosity=0,
    doDS9=False,
)[0:2]
for ctrData in ctrDataList:
    xyCtr = ctrData.xyCtr
    rad = ctrData.rad
    print "star xyCtr=%.2f, %.2f, radius=%s" % (xyCtr[0], xyCtr[1], rad)

    shapeData = PyGuide.starShape(
        data,
        mask=mask,
        xyCtr=xyCtr,
        rad=rad,
    )
    if not shapeData.isOK:
예제 #15
0
gray = img[:,:,2]

gray = numpy.sum(img, axis=2)
# plt.figure()
# plt.hist(gray.flatten())
# plt.show()

# import pdb; pdb.set_trace()

CCDInfo = PyGuide.CCDInfo(
    bias = 1,    # image bias, in ADU
    readNoise = 1, # read noise, in e-
    ccdGain = 2,  # inverse ccd gain, in e-/ADU
)

centroids, stats = PyGuide.findStars(gray, None, None, CCDInfo)
# import pdb; pdb.set_trace()
centroids = centroids[10:-10]
for centroid in centroids:
    centroid.xyCtr[0] = centroid.xyCtr[0] - 0.5
    centroid.xyCtr[1] = centroid.xyCtr[1] - 0.5
    centroid.got = False

plt.figure(figsize=(10,10))
plt.xlim([0,imgSize])
plt.ylim([0, imgSize])
plt.axis('off')
plt.imshow(img)#, vmax=1.75)#, cmap='gray_r')
plt.savefig("gray.png", dpi=250)

for cent in centroids:
예제 #16
0
def FindCircle(numfiles):
    """Fit a circle to the centroids of a star image at different k-mirror orientations."""
    centroids = []
    names = []
    hdus = []
    data = []
    x = r_[0.0]
    y = r_[0.0]
    for i in range(numfiles-1):
        x = append(x, 0.0)
        y = append(y, 0.0)
    #open series of files
    for i in range(numfiles):
        names.append(str(i)+'out.fits')
        hdus.append(str(i)+'hdu')
        data.append(str(i)+'data')
        
    
    print names, hdus, data      
    #find centroids
    j=0
    for imgs in names:
        imHDU = pyfits.open(imgs)
        imData = imHDU[0].data
        stars = PyGuide.findStars(imData, mask, satMask, ccdInfo, thresh, radMult, rad, verbosity, doDS9)
        initialxy = stars[0][0].xyCtr
        centroid = PyGuide.Centroid.centroid(imData, mask, satMask, initialxy, rad, ccdInfo)
        #put centroids into x,y
        xy = centroid.xyCtr
        x[j] = xy[0]
        y[j] = xy[1]
        j+=1
        
    print x
    print y
    #find circle

    basename = 'circle'

    
    # basename = 'arc'

    # # Code to generate random data points
    # R0 = 25
    # nb_pts = 40
    # dR = 1
    # angle =10*pi/5
    # theta0 = random.uniform(0, angle, size=nb_pts)
    # x = (10 + R0*cos(theta0) + dR*random.normal(size=nb_pts)).round()
    # y = (10 + R0*sin(theta0) + dR*random.normal(size=nb_pts)).round()


    # == METHOD 1 ==
    method_1 = 'algebraic'

    # coordinates of the barycenter
    x_m = mean(x)
    y_m = mean(y)

    # calculation of the reduced coordinates
    u = x - x_m
    v = y - y_m

    # linear system defining the center in reduced coordinates (uc, vc):
    #    Suu * uc +  Suv * vc = (Suuu + Suvv)/2
    #    Suv * uc +  Svv * vc = (Suuv + Svvv)/2
    Suv  = sum(u*v)
    Suu  = sum(u**2)
    Svv  = sum(v**2)
    Suuv = sum(u**2 * v)
    Suvv = sum(u * v**2)
    Suuu = sum(u**3)
    Svvv = sum(v**3)

    # Solving the linear system
    A = array([ [ Suu, Suv ], [Suv, Svv]])
    B = array([ Suuu + Suvv, Svvv + Suuv ])/2.0
    uc, vc = linalg.solve(A, B)

    xc_1 = x_m + uc
    yc_1 = y_m + vc

    # Calculation of all distances from the center (xc_1, yc_1)
    Ri_1      = sqrt((x-xc_1)**2 + (y-yc_1)**2)
    R_1       = mean(Ri_1)
    residu_1  = sum((Ri_1-R_1)**2)
    residu2_1 = sum((Ri_1**2-R_1**2)**2)

    # Decorator to count functions calls
    import functools
    def countcalls(fn):
        "decorator function count function calls "

        @functools.wraps(fn)
        def wrapped(*args):
            wrapped.ncalls +=1
            return fn(*args)

        wrapped.ncalls = 0
        return wrapped

    #  == METHOD 2 ==
    # Basic usage of optimize.leastsq
    from scipy      import optimize

    method_2  = "leastsq"

    def calc_R(xc, yc):
        """ calculate the distance of each 2D points from the center (xc, yc) """
        return sqrt((x-xc)**2 + (y-yc)**2)

    @countcalls
    def f_2(c):
        """ calculate the algebraic distance between the 2D points and the mean circle centered at c=(xc, yc) """
        Ri = calc_R(*c)
        return Ri - Ri.mean()

    center_estimate = x_m, y_m
    center_2, ier = optimize.leastsq(f_2, center_estimate)

    xc_2, yc_2 = center_2
    Ri_2       = calc_R(xc_2, yc_2)
    R_2        = Ri_2.mean()
    residu_2   = sum((Ri_2 - R_2)**2)
    residu2_2  = sum((Ri_2**2-R_2**2)**2)
    ncalls_2   = f_2.ncalls

    # == METHOD 2b ==
    # Advanced usage, with jacobian
    method_2b  = "leastsq with jacobian"

    def calc_R(xc, yc):
        """ calculate the distance of each 2D points from the center c=(xc, yc) """
        return sqrt((x-xc)**2 + (y-yc)**2)

    @countcalls
    def f_2b(c):
        """ calculate the algebraic distance between the 2D points and the mean circle centered at c=(xc, yc) """
        Ri = calc_R(*c)
        return Ri - Ri.mean()

    @countcalls
    def Df_2b(c):
        """ Jacobian of f_2b
        The axis corresponding to derivatives must be coherent with the col_deriv option of leastsq"""
        xc, yc     = c
        df2b_dc    = empty((len(c), x.size))

        Ri = calc_R(xc, yc)
        df2b_dc[ 0] = (xc - x)/Ri                   # dR/dxc
        df2b_dc[ 1] = (yc - y)/Ri                   # dR/dyc
        df2b_dc       = df2b_dc - df2b_dc.mean(axis=1)[:, newaxis]

        return df2b_dc

    center_estimate = x_m, y_m
    center_2b, ier = optimize.leastsq(f_2b, center_estimate, Dfun=Df_2b, col_deriv=True)

    xc_2b, yc_2b = center_2b
    Ri_2b        = calc_R(xc_2b, yc_2b)
    R_2b         = Ri_2b.mean()
    residu_2b    = sum((Ri_2b - R_2b)**2)
    residu2_2b   = sum((Ri_2b**2-R_2b**2)**2)
    ncalls_2b    = f_2b.ncalls

    print """
    Method 2b :
    print "Functions calls : f_2b=%d Df_2b=%d""" % ( f_2b.ncalls, Df_2b.ncalls)



    # Summary
    fmt = '%-22s %10.5f %10.5f %10.5f %10d %10.6f %10.6f %10.2f'
    print ('\n%-22s' +' %10s'*7) % tuple('METHOD Xc Yc Rc nb_calls std(Ri) residu residu2'.split())
    print '-'*(22 +7*(10+1))
    print  fmt % (method_1 , xc_1 , yc_1 , R_1 ,        1 , Ri_1.std() , residu_1 , residu2_1 )
    print  fmt % (method_2 , xc_2 , yc_2 , R_2 , ncalls_2 , Ri_2.std() , residu_2 , residu2_2 )

    # plotting functions
    from matplotlib                 import pyplot as p, cm, colors
    p.close('all')

    def plot_all(residu2=False):
        """ Draw data points, best fit circles and center for the three methods,
        and adds the iso contours corresponding to the fiel residu or residu2
        """

        f = p.figure( facecolor='white')  #figsize=(7, 5.4), dpi=72,
        p.axis('equal')

        theta_fit = linspace(-pi, pi, 180)

        x_fit1 = xc_1 + R_1*cos(theta_fit)
        y_fit1 = yc_1 + R_1*sin(theta_fit)
        p.plot(x_fit1, y_fit1, 'b-' , label=method_1, lw=2)

        x_fit2 = xc_2 + R_2*cos(theta_fit)
        y_fit2 = yc_2 + R_2*sin(theta_fit)
        p.plot(x_fit2, y_fit2, 'k--', label=method_2, lw=2)

        p.plot([xc_1], [yc_1], 'bD', mec='y', mew=1)
        p.plot([xc_2], [yc_2], 'gD', mec='r', mew=1)
     
        # draw
        p.xlabel('x')
        p.ylabel('y')

        # plot the residu fields
        nb_pts = 100

        p.draw()
        xmin, xmax = p.xlim()
        ymin, ymax = p.ylim()

        vmin = min(xmin, ymin)
        vmax = max(xmax, ymax)

        xg, yg = ogrid[vmin:vmax:nb_pts*1j, vmin:vmax:nb_pts*1j]
        xg = xg[..., newaxis]
        yg = yg[..., newaxis]

        Rig    = sqrt( (xg - x)**2 + (yg - y)**2 )
        Rig_m  = Rig.mean(axis=2)[..., newaxis]

        if residu2 : residu = sum( (Rig**2 - Rig_m**2)**2 ,axis=2)
        else       : residu = sum( (Rig-Rig_m)**2 ,axis=2)

        lvl = exp(linspace(log(residu.min()), log(residu.max()), 15))

        p.contourf(xg.flat, yg.flat, residu.T, lvl, alpha=0.4, cmap=cm.Purples_r) # , norm=colors.LogNorm())
        cbar = p.colorbar(fraction=0.175, format='%.f')
        p.contour (xg.flat, yg.flat, residu.T, lvl, alpha=0.8, colors="lightblue")

        if residu2 : cbar.set_label('Residu_2 - algebraic approximation')
        else       : cbar.set_label('Residu')

        # plot data
        p.plot(x, y, 'ro', label='data', ms=8, mec='b', mew=1)
        p.legend(loc='best',labelspacing=0.1 )

        p.xlim(xmin=vmin, xmax=vmax)
        p.ylim(ymin=vmin, ymax=vmax)

        p.grid()
        p.title('Least Squares Circle')
        p.savefig('%s_residu%d.png' % (basename, 2 if residu2 else 1))

    plot_all(residu2=False)
    plot_all(residu2=True )

    p.show()
    def __init__(self,fitsImageName,fitsTableName=None,manual=False,fitsCatalogName=None,caldir='./cal/',fdir='./origin/',sedir='./config/',manCat=None,manCatFile=None):
        """
        Keyword arguments:
        fitsImageName -- the input fits image file
        fitsTableName -- the input fits table file from catalog.py. Note that it has to be in the default format(asu-fits)
        manual -- if False, the program uses Sextractor to extract stars in the image, else, the program uses ds9 and PyGuide 
                  to manually calibrate the image. Also, if True, fitsCatalogName must be specified.
        fitsCatalogName -- the catalog image from catalog for manual calibration
        """

        self.fitsImageName = fitsImageName
        self.fitsTableName = fitsTableName
        self.fitsCatalogName = fitsCatalogName
        self.catalog = []
        self.starList = []
        self.sedir = sedir
        self.fdir = fdir
        self.caldir = caldir
        self.fitsdir = self.fdir + self.fitsImageName
        self.manual = manual
        self.minError = 2000
        self.calibrate = True
        self.manCat = manCat
        self.manCatFile = manCatFile
        
        #test to see if calibration is necessary
        imageList = pyfits.open(self.fitsdir)
        header = imageList[0].header
        
        try:
            #if calibrated file with suffix _offCal_rotCal already exists, skip the calibration 
            imageListCal = pyfits.open(self.caldir+self.fitsImageName[:-5]+'_offCal_rotCal.fits')
            headerCal = imageListCal[0].header
            CALERR = headerCal['CALERR']
            print 'CALERR:' + str(CALERR)  
            if CALERR > self.minError:
                raise
            self.calibrate = False
        except:
            pass
        
        if self.manual and self.calibrate :
            #defining basic parameters for PyGuide.findStars. More info can be found on help(pyGuide.findStars)
            ccd = pg.CCDInfo(0,0.00001,1,2500)

            satMask = np.zeros(image.shape)
            mask = np.zeros(image.shape)

            #this returns Centroid class instance in PyGuide
            centroidData = pg.findStars(image,mask=mask,satMask=satMask,rad=30,ccdInfo=ccd,doDS9=False)[0]

            #sort stars and discard the one that does not make sense, e.g, the stars that are out of array
            starList = []
            _count = 0
            for data in range(len(centroidData)):    
                if centroidData[_count].xyCtr[0] > 0 and centroidData[_count].xyCtr[1] > 0:
                    starList.append(centroidData[_count].xyCtr)
                _count += 1    
            
        if not self.manual and self.calibrate:
            
            #use source extractor to extractor sources, visit man page for more info
            catName = self.caldir + self.fitsImageName[:-5] + '.cat'
            paramdir = self.sedir + 'default.sex'
            checkimg = self.caldir + self.fitsImageName[:-5] + '.check'
            proc = subprocess.Popen(['sex',self.fdir+fitsImageName,'-c',paramdir,'-CATALOG_NAME',catName,'-CHECKIMAGE_NAME',checkimg])
            proc.communicate()
            #read cat file to extract stars
            starList = readCat(catName)
        
        #coordinates in pixels
        if self.calibrate:
            self.starList = np.array(starList)
    
        #if fits table is provided, loading fits table and convert the list of star into standard numpy array
        if self.manCat == 'full':
            catalog = []
            catalogAppend = readCat(self.manCatFile)
            for star in catalogeAppend:
                catalog.append([star[0],star[1]])
        
        elif self.fitsTableName != None:
            tableList = pyfits.open(self.fitsTableName)
            
            h1 = tableList[1]
            catalog = h1.data
            catalog_x = []
            catalog_y = []
            for i in range(len(catalog)):
                catalog_x.append(catalog[i][0])
                catalog_y.append(catalog[i][1])
            
            #if semi manual catalog is used, add stars in manCatFile into the existing catalog
            if self.manCat == 'semi':
                for star in readCat(self.manCatFile):
                    catalog_x.append(star[0])
                    catalog_y.append(star[1])
            catalog = zip(catalog_x,catalog_y)
        
        self.catalog = np.array(catalog)
        print len(self.catalog)
                
        #always remember to close the file to avoid memory leakage
        imageList.close()
예제 #18
0
def centroid(imgData, positionerTargetsMM, plot=False):
    # xy center in mm kaiju coord sys
    imgData = imgData[::-1, :]
    numCols, numRows = imgData.shape
    mask = numpy.zeros(imgData.shape) + 1
    # build the mask, draw squares around expected positions
    positionerTargetsPx = OrderedDict()
    for posID, xyKaijuMM in positionerTargetsMM.items():
        # take abs value of positioner because it's y axis is defined
        # negative (loic's positions are measured from top left)
        xyImageMM = numpy.dot(xyKaijuMM, rot2image) + numpy.abs(centerXYMM)
        xTargetPx, yTargetPx = xyImageMM / scaleFac
        positionerTargetsPx[posID] = numpy.array([xTargetPx, yTargetPx])
        # rotate into reference frame with 0,0 at bottom left
        xROI = numpy.int(numpy.floor(xTargetPx))
        yROI = numpy.int(numpy.floor(yTargetPx))
        startRow = xROI - roiRadiusPx
        if startRow < 0:
            startRow = 0
        endRow = xROI + roiRadiusPx
        if endRow > imgData.shape[1]:
            endRow = imgData.shape[1]

        startCol = yROI - roiRadiusPx
        if startCol < 0:
            startCol = 0
        endCol = yROI + roiRadiusPx
        if endCol > imgData.shape[0]:
            endCol = imgData.shape[0]

        mask[startCol:endCol, startRow:endRow] = 0

    # imshow defaults to -0.5, -0.5 for origin, set this to 0,0
    # plot the mask used too make it positive valued so it shows up
    plt.imshow(imgData + numpy.abs(mask - 1) * 200,
               origin="lower",
               extent=(0, numRows, 0, numCols))

    # find all the centroids, and loop through and plot them
    ctrDataList, imStats = PyGuide.findStars(
        data=imgData,
        mask=mask,
        satMask=None,
        thresh=detectThresh,
        ccdInfo=CCDInfo,
        verbosity=0,
        doDS9=False,
    )[0:2]
    centroidsPx = []
    for ctrData in ctrDataList:
        # need to index explicity because ctrData is actually an object
        centroidsPx.append(ctrData.xyCtr)
        xyCtr = ctrData.xyCtr
        rad = ctrData.rad
        counts = ctrData.counts
        plt.plot(xyCtr[0], xyCtr[1], 'or', markersize=10,
                 fillstyle="none")  #, alpha=0.2)
        # print("star xyCtr=%.2f, %.2f, radius=%s counts=%.2f" % (xyCtr[0], xyCtr[1], rad, counts))
    # plot the desired targets
    centroidsPx = numpy.asarray(centroidsPx)
    nTargs = len(positionerTargetsPx.values())
    nCentroids = len(centroidsPx)

    for posID, (xTargetPx, yTargetPx) in positionerTargetsPx.items():
        plt.plot(xTargetPx, yTargetPx, 'xr', markersize=10)

    if plot:
        plt.show()
    # calculate distances between all targets and all centroids
    if nCentroids > nTargs:
        # don't allow false positives
        raise RuntimeError("more centroids than targets")
    if nCentroids < nTargs:
        #allow missing centroids
        print("warning: more targets than centroids")
    if nCentroids == 0:
        raise RuntimeError("didn't find any centroids")

    # print("distMat shappe", distMat.shape)
    targArrayPx = numpy.array(list(positionerTargetsPx.values()))
    targIdArray = list(positionerTargetsPx.keys())
    # for each centroid give it a target
    cent2target = [
    ]  # holds centroidIndex, targetIndex, and distance to target in px
    for centInd, cent in enumerate(centroidsPx):
        # a row of disntances for this target
        distArr = numpy.array(
            [numpy.linalg.norm(targ - cent) for targ in targArrayPx])
        targInd = numpy.argmin(distArr)
        cent2target.append([centInd, targInd, distArr[targInd]])
    cent2target = numpy.array(cent2target)
    # for paranoia, remove any targets with distance greater than the ROI,
    # not sure this could happen but check anyways
    cent2target = cent2target[cent2target[:, 2] < roiRadiusPx]

    for cInd, tInd, dist in cent2target:
        print("centroid %i gets target %i at distance %.2f pixels" %
              (cInd, tInd, dist))

    # calculate the offsets (vector from centroid to target)
    # in kaiju's reference frame in mm
    positionerOffsets = OrderedDict()
    for cInd, tInd, dist in cent2target:
        tInd = int(tInd)
        cInd = int(cInd)
        posID = targIdArray[tInd]
        targPix = targArrayPx[tInd]
        centPix = centroidsPx[cInd]
        offPx = targPix - centPix
        offMM = numpy.dot(offPx * scaleFac, rot2kaiju)
        positionerOffsets[posID] = offMM
        # print("dist %i %.2f precomputed %.2f"%(posID, numpy.linalg.norm(targPix-centPix), dist))

    plt.close()
    return positionerOffsets