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'
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)
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
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)
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
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
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
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) ))
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
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:
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
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)
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:
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:
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()
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