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 aligntocat(cube,catalogue): """ Take a cube and compare the sources in the field to the positions in the reference catalogue. Return offsets in ra/dec that can be used for re-projecting the cube This makes use of pyguide to find stars and centroid on them """ import PyGuide import numpy as np from astropy import wcs print("Processing cube {} for offsets".format(cube)) #first project the cube to create a white image with wcs img, var, wcsimg = cube2img(cube) #load the reference stars starcat=np.loadtxt(catalogue,dtype={'names': ('ra','dec'),'formats': ('f4', 'f4')}) #loop on reference stars and centroid nref=len(starcat['ra']) #space for offsets raoffcurrent=[] decoffcurrent=[] for sr in range(nref): #find first guess pix = wcsimg.wcs_world2pix(starcat['ra'][sr],starcat['dec'][sr],0) #centroid within 20 pixels ccd=PyGuide.CCDInfo(0,0,1) #handle weird errors for bas pixels usethis=True try: centroid=PyGuide.centroid(img,None,None,[pix[0],pix[1]],20,ccd) except: usethis=False #back to ra/dec if centroid is good if ((centroid.isOK) & (usethis)): coord = wcsimg.wcs_pix2world(centroid.xyCtr[0],centroid.xyCtr[1],0) raoffcurrent.append(coord[0]-starcat['ra'][sr]) decoffcurrent.append(coord[1]-starcat['dec'][sr]) #stack offsets raoff=np.median(np.array(raoffcurrent)) decoff=np.median(np.array(decoffcurrent)) print("Offsets for cube {} RA: {} Dec: {}".format(cube,raoff*3600.,decoff*3600.)) print("Error offsets for cube {} RA: {} Dec: {}".format(cube,np.std(np.array(raoffcurrent))*3600., np.std(np.array(decoffcurrent))*3600.)) return raoff,decoff
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 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 centroid(self, xyPos, data): """check to see if there is valid signal at xpos, ypos, on image data if so return the centroid. """ # default to 5 px search rad? return PyGuide.centroid(data, None, None, xyPos, rad = 3, #pixels ccdInfo = self.config.ccdInfo)
def timeCentroid(data, mask, xyGuess, niter, rad=20): print "timeCentroid: xyGuess=%3.0f, %3.0f; niter=%2d; rad=%3d;" % \ (xyGuess[0], xyGuess[1], niter, rad), begTime = time.time() for ii in range(niter): PyGuide.centroid( data=data, mask=mask, satMask=None, xyGuess=xyGuess, rad=rad, thresh=Thresh, ccdInfo=CCDInfo, ) dTime = time.time() - begTime print "time/iter=%.3f" % (dTime / niter, )
def aligntocat(cube,catalogue): """ Take a cube and compare the sources in the field to the positions in the reference catalogue. Return offsets in ra/dec that can be used for re-projecting the cube This makes use of pyguide to find stars and centroid on them """ import PyGuide import numpy as np from astropy import wcs print "Processing cube {} for offsets".format(cube) #first project the cube to create a white image with wcs img, var, wcsimg = cube2img(cube) #load the reference stars starcat=np.loadtxt(catalogue,dtype={'names': ('ra','dec'),'formats': ('f4', 'f4')}) #loop on reference stars and centroid nref=len(starcat['ra']) #space for offsets raoffcurrent=[] decoffcurrent=[] for sr in range(nref): #find first guess pix = wcsimg.wcs_world2pix(starcat['ra'][sr],starcat['dec'][sr],0) #centroid within 20 pixels ccd=PyGuide.CCDInfo(0,0,1) #handle weird errors for bas pixels usethis=True try: centroid=PyGuide.centroid(img,None,None,[pix[0],pix[1]],20,ccd) except: usethis=False #back to ra/dec if centroid is good if ((centroid.isOK) & (usethis)): coord = wcsimg.wcs_pix2world(centroid.xyCtr[0],centroid.xyCtr[1],0) raoffcurrent.append(coord[0]-starcat['ra'][sr]) decoffcurrent.append(coord[1]-starcat['dec'][sr]) #stack offsets raoff=np.median(np.array(raoffcurrent)) decoff=np.median(np.array(decoffcurrent)) print "Offsets for cube {} RA: {} Dec: {}".format(cube,raoff*3600.,decoff*3600.) print "Error offsets for cube {} RA: {} Dec: {}".format(cube,np.std(np.array(raoffcurrent))*3600., np.std(np.array(decoffcurrent))*3600.) return raoff,decoff
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 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 doStarShape( imName=None, maskName=None, xyCtr=None, rad=rad, invertMask=False, verbosity=verbosity, ): """Shape-fit a star Inputs: - Most of the arguments for loadFiles plus rad, xyCtr and verbosity. """ global im, imFits, mask, maskFits im, mask, satMask = loadFiles(imName, maskName, None, invertMask) if xyCtr is None: print("xyCtr is required") return if rad is None: print("rad argument is required because the default is presently None") return shapeData = PyGuide.starShape( data=im, mask=mask, xyCtr=xyCtr, rad=rad, verbosity=verbosity, ) print(" xctr yctr ampl bkgnd fwhm rad chiSq") try: print("%7.2f %7.2f %13.1f %9.1f %7.1f %7d %7.1f" % ( xyCtr[0], xyCtr[1], shapeData.ampl, shapeData.bkgnd, shapeData.fwhm, rad, shapeData.chiSq, )) except (ValueError, TypeError) as e: print("(printing free-form due to format error: %s)" % (e, )) print(xyCtr[0], xyCtr[1], shapeData.ampl, shapeData.bkgnd, shapeData.fwhm, rad, shapeData.chiSq) if not shapeData.isOK: print("starShape failed:", shapeData.msgStr)
def centroidImage(image,xyguess,radiusOfSearch = 6,doDS9=True,usePsfFit=False): ''' ABW This function finds the centroid of a star in the image ''' #remove any undefined values image[np.invert(np.isfinite(image))]=0. #Assume anywhere with 0 counts is a dead pixel deadMask = 1.0*(image==0) #ignore saturated mask satMask = np.zeros((len(deadMask),len(deadMask[0]))) # Specify CCDInfo (bias,readNoise,ccdGain,satLevel) ccd = pg.CCDInfo(0,0.00001,1,2500) xyguessPyguide = np.subtract(xyguess,(0.5,0.5)) #account for how pyguide puts pixel coordinates pyguide_output = pg.centroid(image,deadMask,satMask,xyguess,radiusOfSearch,ccd,0,False,verbosity=0, doDS9=doDS9) #Added by JvE May 31 2013 # Use PyGuide centroid positions, if algorithm failed, use xy guess center positions instead try: xycenterGuide = [float(pyguide_output.xyCtr[0]),float(pyguide_output.xyCtr[1])] np.add(xycenterGuide,(0.5,0.5))#account for how pyguide puts pixel coordinates flag = 0 except TypeError: xycenterGuide = xyguess flag = 1 xycenter=xycenterGuide if usePsfFit: psfPhot = PSFphotometry(image,centroid=[xycenterGuide],verbose=True) psfDict = psfPhot.PSFfit(aper_radius=radiusOfSearch) xycenterPsf = [psfDict['parameters'][2],psfDict['parameters'][3]] if psfDict['flag'] == 0: xycenter = xycenterPsf flag = 0 else: print 'PSF fit failed with flag: ', psfDict['flag'] #xycenter = xycenterGuide flag = 1 outDict = {'xycenter':xycenter,'flag':flag} if usePsfFit: outDict['xycenterGuide'] = xycenterGuide outDict['xycenterPsf'] = xycenterPsf return outDict
def doStarShape( imName = None, maskName = None, xyCtr = None, rad = rad, invertMask = False, verbosity = verbosity, ): """Shape-fit a star Inputs: - Most of the arguments for loadFiles plus rad, xyCtr and verbosity. """ global im, imFits, mask, maskFits im, mask, satMask = loadFiles(imName, maskName, None, invertMask) if xyCtr is None: print("xyCtr is required") return if rad is None: print("rad argument is required because the default is presently None") return shapeData = PyGuide.starShape( data = im, mask = mask, xyCtr = xyCtr, rad = rad, verbosity = verbosity, ) print(" xctr yctr ampl bkgnd fwhm rad chiSq") try: print("%7.2f %7.2f %13.1f %9.1f %7.1f %7d %7.1f" % ( xyCtr[0], xyCtr[1], shapeData.ampl, shapeData.bkgnd, shapeData.fwhm, rad, shapeData.chiSq, )) except (ValueError, TypeError) as e: print("(printing free-form due to format error: %s)" % (e,)) print(xyCtr[0], xyCtr[1], shapeData.ampl, shapeData.bkgnd, shapeData.fwhm, rad, shapeData.chiSq) if not shapeData.isOK: print("starShape failed:", shapeData.msgStr)
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 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)
2004-08-04 ROwen Modified to work with 2004-08-03 findStars. 2004-08-06 ROwen Modified to work with 2004-08-06 findStars. 2005-02-07 ROwen Modified for PyGuide 1.2. Modified to show shape info for all found stars. 2005-04-19 ROwen Modified for PyGuide 2.0 2005-10-14 ROwen Supply null satMask for PyGuide 2.1. """ import os.path import sys import PyGuide import pyfits # these values are probably wrong for the given test image CCDInfo = PyGuide.CCDInfo( bias=200, # image bias, in ADU readNoise=21.391, # read noise, in e- ccdGain=1.643, # ccd gain, in e-/pixel ) UseDS9 = True if len(sys.argv) > 1: filename = sys.argv[1] else: testDir = os.path.dirname(__file__) filename = os.path.join(testDir, "test.fits") testimg = pyfits.open(filename) data = testimg[0].data if UseDS9:
numpy.random.seed(1) for ii in range(NumTries): actCtr = numpy.random.uniform(-fwhm/2.0, fwhm/2.0, size=(2,)) + nomCtr cleanData = PyGuide.FakeData.fakeStar(imShape, actCtr, sigma, ampl) data = PyGuide.FakeData.addNoise( data = cleanData, sky = Sky, ccdInfo = CCDInfo, ) ctrData = PyGuide.centroid( data = data, mask = mask, satMask = None, xyGuess = nomCtr, rad = fwhm * 3.0, ccdInfo = CCDInfo, thresh = Thresh, doSmooth = DoSmooth, ) if not ctrData.isOK: print "%s %s %s NaN NaN NaN NaN NaN NaN NaN %s %r" % ( fwhm, ampl, maskWidth, ctrData.rad, ctrData.msgStr, ) nBad += 1 continue xyMeasErr = [ctrData.xyCtr[ii] - actCtr[ii] for ii in (0,1)] print "%s %s %s %.3f %.3f %.3f %.3f %.3f %s %s %s %r" % ( fwhm, ampl, maskWidth, xyMeasErr[0], xyMeasErr[1],
2005-02-07 ROwen Modified for PyGuide 1.2. Modified to show estimated error. 2005-05-19 ROwen Updated for PyGuide 2.0. 2005-10-14 ROwen Supply null satMask for PyGuide 2.1. 2008-01-02 ROwen Added DoSmooth constant. 2009-11-20 ROwen Modified to use numpy. """ import numpy import PyGuide import RO.DS9 DoSmooth = True Sky = 1000, # sky level, in ADU CCDInfo = PyGuide.CCDInfo( bias = 2176, # image bias, in ADU readNoise = 19, # read noise, in e- ccdGain = 2.1, # inverse ccd gain, in e-/ADU ) # test data format: # arrShape, actual center, sigma, ampl, scanRad factor, maskLim testData = ( [(51, 51), (27.0, 28.6), 2, 1000, 3, (23,29)], [(51, 51), (27.1, 28.6), 2, 1000, 3, (23,29)], [(51, 51), (27.1, 28.6), 2, 1000, 4, (23,29)], [(51, 51), (27.2, 28.7), 2, 1000, 3, (23,29)], [(51, 51), (27.3, 28.8), 2, 1000, 3, (23,29)], [(51, 51), (27.4, 28.9), 2, 1000, 3, (23,29)], [(51, 51), (27.5, 28.9), 2, 1000, 3, (23,29)], [(51, 51), (27.6, 28.9), 2, 1000, 3, (23,29)], [(51, 51), (27.7, 28.9), 2, 1000, 3, (23,29)],
def doCentroid( imName = None, maskName = None, satMaskName = None, xyGuess = None, invertMask = False, **kargs ): """Centroid and shape-fit a star Inputs: - all the arguments for loadFiles plus most values shown by showDef """ global im, imFits, mask, maskFits, satMask, satMaskFits, isSat, sd im, mask, satMask = loadFiles(imName, maskName, satMaskName, invertMask) if xyGuess is None: print("xyGuess is required") return # check keyword arguments for paramName in kargs: if paramName not in CentroidParamNames: raise RuntimeError("Invalid argument: %s" % (paramName,)) # fill in defaults globalDict = globals() for paramName in CentroidParamNames: 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) if kargs["rad"] is None: print("rad argument is required because the default is presently None") return verbosity = kargs["verbosity"] # centroid ctrData = PyGuide.centroid( data = im, mask = mask, satMask = satMask, xyGuess = xyGuess, ccdInfo = ccdInfo, **kargs) if not ctrData.isOK: print("centroid failed:", ctrData.msgStr) return shapeData = PyGuide.starShape( data = im, mask = mask, xyCtr = ctrData.xyCtr, rad = ctrData.rad, verbosity = verbosity, ) # print results printStarHeader() printStarData(ctrData, shapeData) if not shapeData.isOK: print("starShape failed:", shapeData.msgStr)
def performCentroiding(self): ''' # Function for converting arcseconds to radians. def arcsec_to_radians(total_arcsec): total_degrees = total_arcsec/3600.0 total_radians = total_degrees*d2r return total_radians # Function for converting radians to arcseconds. def radians_to_arcsec(total_radians): total_degrees = total_radians*r2d total_arcsec = total_degrees*3600.0 return total_arcsec print 'Not currently implemented...' d2r = np.pi/180.0 r2d = 180.0/np.pi # Load data out of display stack h5 file centroid_RA = self.headerInfo[self.headerTitles.index('RA')] centroid_DEC = self.headerInfo[self.headerTitles.index('Dec')] original_lst = self.headerInfo[self.headerTitles.index('lst')] exptime = self.headerInfo[self.headerTitles.index('exptime')] integrationTime = self.headerInfo[self.headerTitles.index('integrationTime')] deadPixelFilename = self.headerInfo[self.headerTitles.index('deadPixFileName')] HA_offset = self.headerInfo[self.headerTitles.index('HA_offset')] nRow = self.headerInfo[self.headerTitles.index('nRow')] nCol = self.headerInfo[self.headerTitles.index('nCol')] centroid_RA_radians = ephem.hours(centroid_RA).real centroid_RA_arcsec = radians_to_arcsec(centroid_RA_radians) centroid_DEC_radians = ephem.degrees(centroid_DEC).real centroid_DEC_arcsec = radians_to_arcsec(centroid_DEC_radians) original_lst_radians = ephem.hours(original_lst).real original_lst_seconds = radians_to_arcsec(original_lst_radians)/15.0 ''' # Load up dead pixel mask. Invert for PyGuide format. #deadFile = np.load(self.deadPixelFilename) #deadMask = deadFile['deadMask'] #deadMask = -1*deadMask + 1 # Saturated pixels already taken care of by hot pixel code. satMask = np.zeros((46,44)) # Specify CCDInfo (bias,readNoise,ccdGain,satLevel) ccd = pg.CCDInfo(0,0.00001,1,2500) # Initialize arrays that will be saved in h5 file. 1 array element per centroid frame. timeList=[] xPositionList=[] yPositionList=[] hourAngleList=[] flagList=[] flag=0 print 'Centroiding a total of ' + str(self.totalFrames) + ' frames...' for iFrame in range(self.totalFrames): apertureRadius = self.apertureRadii[iFrame] image = np.array(self.stackData[:,:,iFrame]) nanMask = np.isnan(image) image[nanMask] = 0. deadMask = np.zeros((self.nRow,self.nCol)) deadMask[np.where(image==0)] = 1 xyguess = np.array(self.centerPositions[iFrame]) pyguide_output = pg.centroid(image,deadMask,satMask,xyguess,apertureRadius,ccd,0,False,verbosity=2, doDS9=True) # Use PyGuide centroid positions, if algorithm failed, use xy guess center positions instead print pyguide_output try: xycenter = [float(pyguide_output.xyCtr[0]),float(pyguide_output.xyCtr[1])] print 'Frame ' + str(iFrame) +': Calculated [x,y] center = ' + str((xycenter)) + '.' flag = 0 except TypeError: print 'Cannot centroid frame' + str(iFrame) + ', using guess instead' xycenter = xyguess flag = 1 # Calculate lst for a given frame, at midpoint of frame current_lst_seconds = self.original_lst_seconds + (iFrame+0.5)*self.integrationTime current_lst_radians = self.arcsec_to_radians(current_lst_seconds*15.0) # Calculate hour angle for a given frame. Include a constant offset for instrumental rotation. HA_variable = current_lst_radians - self.centroid_RA_radians HA_static = self.HA_offset*self.d2r HA_current = HA_variable + HA_static # Make lists to save to h5 file timeList.append((iFrame+0.5)*self.integrationTime) xPositionList.append(xycenter[0]) yPositionList.append(xycenter[1]) hourAngleList.append(HA_current) flagList.append(flag) self.objectIdentifier = self.loadStackName[0:self.loadStackName.index('ImageStacks/ImageStack_')] self.obsIdentifier = self.loadStackName[self.loadStackName.rindex('ImageStacks/ImageStack_') + len('ImageStacks/ImageStack_'):-3] fullCentroidListFileName = self.objectIdentifier + 'CentroidLists/Centroid_' + self.obsIdentifier + '.h5' print 'Saving to ' + fullCentroidListFileName # Write data to new h5 file centroidListFile = tables.openFile(fullCentroidListFileName,mode='w') centroidHeaderGroupName = 'header' centroidHeaderTableName = 'header' centroidDataGroupName = 'centroidlist' centroidDataGroup = centroidListFile.createGroup(centroidListFile.root,centroidDataGroupName,'Table of times, x positions, y positions, hour angles, and flags') #paramstable = tables.Array(centroidgroup,'params', object=paramsList, title = 'Object and array params') timestable = tables.Array(centroidDataGroup,'times',object=timeList,title='Times at which centroids were calculated') xpostable = tables.Array(centroidDataGroup,'xPositions',object=xPositionList,title='X centroid positions') ypostable = tables.Array(centroidDataGroup,'yPositions',object=yPositionList,title='Y centroid positions') hatable = tables.Array(centroidDataGroup,'hourAngles',object=hourAngleList,title='Hour angles at specified times') flagtable = tables.Array(centroidDataGroup,'flags',object=flagList,title='Flags whether or not guess had to be used, 1 for guess used') # Should probably just copy original header information over, more info this way!!! centroidHeaderGroup = centroidListFile.createGroup("/", centroidHeaderGroupName, 'Header') centroidHeaderTable = centroidListFile.createTable(centroidHeaderGroup, centroidHeaderTableName, DisplayStack.DisplayStack.headerDescription, 'Header Info') centroidHeader = centroidHeaderTable.row for iItem in range(len(self.headerInfo)): centroidHeader[self.headerTitles[iItem]] = self.headerInfo[iItem] centroidHeader.append() centroidListFile.flush() centroidListFile.close() print 'Done performing centroiding...'
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
rad2.append(float(larr[4])) elif rtype[i] == 'circle': xcen.append(float(larr[1])) ycen.append(float(larr[2])) rad.append(float(larr[3])) rad2.append(float(larr[3] * numpy.sqrt(2))) else: print "Error: region type is not recognized (or possibly you are specifying an unrecognized coordinate system)" if float(rad2[i]) > float(rad[i]): outerrad = rad2[i] else: outerrad = float(rad[i])*numpy.sqrt(2) # subimage = image[:,ycen[i]-rad[i]:ycen[i]+rad[i],xcen[i]-rad[i]:xcen[i]+rad[i]] subimage = image[:,ycen[i]-outerrad:ycen[i]+outerrad,xcen[i]-outerrad:xcen[i]+outerrad] # center = PyGuide.centroid(subimage[0],None,None,[outerrad,outerrad],rad[i],ccdinf) center = PyGuide.centroid(subimage[0],None,None,[rad[i],rad[i]],rad[i],ccdinf,thresh=1,verbosity=0,smooth=0) innerradius = PyGuide.starShape(subimage[0],None,center.xyCtr,rad[i]).fwhm outerradius = innerradius * numpy.sqrt(2) if center.isOK: (newxcen,newycen)=center.xyCtr # print "%s %s" % (str(center.xyCtr),str(center.xyErr)) else: print "Error: %s. Using the point you selected instead of the star center." % str(center.msgStr) (newxcen,newycen)=[outerrad,outerrad] inner = core(subimage,newxcen,newycen,innerradius) equalarea = core(subimage,newxcen,newycen,outerradius) - inner vspec = inner - equalarea for j in xrange(1,vspec.shape[0]): print "%f %f" % (j,vspec[j]) break i=i+1
for y in range(grid_height): for x in range(grid_width): badMask[y][x] = mask[y][x][t] for i in range(integration_time): pltmat[y][x]+=flux_cube[y][x][int(t*integration_time+i)]/integration_time map.ax = map.fig.add_subplot(111) map.ax.set_title('Object 1') map.ax.matshow(pltmat,cmap = plt.cm.gray, origin = 'lower') map.connect() plt.show() try: xyguess = map.xyguess except AttributeError: pass print 'Guess = ' + str(xyguess) pyguide_output = pg.centroid(pltmat,badMask,satMask,xyguess,3,ccd,0,False) try: xycenter = [float(pyguide_output.xyCtr[0]),float(pyguide_output.xyCtr[1])] print 'Calculated = ' + str((xycenter)) except TypeError: print 'Cannot centroid, using guess' xycenter = xyguess map = MouseMonitor() map.fig = plt.figure() pltmat = np.zeros((grid_height,grid_width)) for y in range(grid_height): for x in range(grid_width): for i in range(integration_time): pltmat[y][x]+=flux_cube[y][x][int(t*integration_time+i)]/integration_time map.ax = map.fig.add_subplot(111)
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 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()
#filePath = input("Enter path to file (eg. ~/Pictures/SX_CCD): ") #dataFile = input("Enter desired output file (eg. data.csv): ") if filePath[0] == '~': filePath = os.path.expanduser('~') + filePath[1:] if dataFile[0] == '~': dataFile = os.path.expanduser('~') + dataFile[1:] #print(filePath) #print(dataFile) CCDInfo = PyGuide.CCDInfo( bias=BIAS_LEVEL, # image bias, in ADU readNoise=READ_NOISE, # read noise, in e- ccdGain=GAIN, # inverse ccd gain, in e-/ADU ) if filePath[len(filePath) - 5:] == '.fits': dataListTemp = single_image(filePath) dataList = [] dataList.append(dataListTemp) write_to_csv(dataFile, dataList) else: if filePath[len(filePath) - 1] != '/': filePath = filePath + '/' if not os.path.exists(filePath): print("ERROR: That file path does not exist.")
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
# import pdb; pdb.set_trace() 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')
2004-08-06 ROwen Modified for new centroid. 2005-02-07 ROwen Modified for PyGuide 1.2. 2005-05-19 ROwen Modified for PyGuide 2.0. 2005-10-14 ROwen Supply null satMask for PyGuide 2.1. 2009-11-20 ROwen Modified to use numpy. """ import time import numpy import PyGuide # settings ImWidth = 1024 # image width Sky = 1000 # sky level, in ADU CCDInfo = PyGuide.CCDInfo( bias=2176, # image bias, in ADU readNoise=19, # read noise, in e- ccdGain=2.1, # inverse ccd gain, in e-/ADU ) Thresh = 3.0 FWHM = 2.5 Ampl = 5000 def timeCentroid(data, mask, xyGuess, niter, rad=20): print "timeCentroid: xyGuess=%3.0f, %3.0f; niter=%2d; rad=%3d;" % \ (xyGuess[0], xyGuess[1], niter, rad), begTime = time.time() for ii in range(niter): PyGuide.centroid( data=data, mask=mask,
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
def muse_combine(pixtab,cubes,wcslist,lmin=4600,lmax=10000): """ Take a list of reduced pixel table and cubes and combine them. pixtab = reduced pixel table for alignment wcslist = list of ra dec of bright sources in the field for centroid that can be used for relative source alignment. cubes = reduced cubes, which are not directly combined, but they are used to compute alignemnt lmin,lmax = min max wave interval for combining Make sure filter list is in working directory """ import astropy from astropy.table import Table from astropy.io import fits import PyGuide import numpy as np from astropy import wcs from astropy.coordinates import SkyCoord import subprocess #load the wcs wcstab = Table.read(wcslist,format='ascii') raoff=[] decoff=[] #loop over the pixel table to compute the offsets for cb in cubes: print "Processing cube {} for offsets".format(cb) #project a cube header='' fov=project_cube(cb,[4800,8000],False) #load the wcs w = wcs.WCS(fov['header']) raoffcurrent=[] decoffcurrent=[] #loop over reference stars for sr in range(len(wcstab)): #go to pixels pix = w.wcs_world2pix(wcstab['col1'][sr],wcstab['col2'][sr],0,1) #centroid ccd=PyGuide.CCDInfo(0,0,1) centroid=PyGuide.centroid(fov["img"],None,None,[pix[0],pix[1]],20,ccd) #back to ra/dec if centroid.isOK: coord = w.wcs_pix2world(centroid.xyCtr[0],centroid.xyCtr[1],0,1) raoffcurrent.append(coord[0]-wcstab['col1'][sr]) decoffcurrent.append(coord[1]-wcstab['col2'][sr]) #stack offsets thisdra=np.mean(np.array(raoffcurrent)) thisdde=np.mean(np.array(decoffcurrent)) raoff.append(thisdra) decoff.append(thisdde) print "Offsets for this cube RA: {} Dec: {}".format(thisdra,thisdde) #print offsets print "All Delta RA ", raoff print "All Delta Dec ", decoff rastring = ','.join(str(e) for e in raoff) decstring = ','.join(str(e) for e in decoff) #now prepare script for stacking and run the pipeline sof=open("combine.sof","w") for pxtb in pixtab: sof.write(pxtb+' PIXTABLE_REDUCED\n') sof.write('filter_list.fits FILTER_LIST') sof.close() #Write the command file scr=open("make_combine.sh","w") scr.write('MUSE_XCOMBINE_RA_OFFSETS="'+rastring+'"\n') scr.write('MUSE_XCOMBINE_DEC_OFFSETS="'+decstring+'"\n') scr.write("esorex --log-file=exp_combine.log muse_exp_combine --lambdamin={0:f} --lambdamax={1:f} combine.sof".format(lmin,lmax)) scr.close() #Run pipeline subprocess.call(["sh", "make_combine.sh"]) return
2005-10-14 ROwen Supply null satMask for PyGuide 2.1. 2008-01-02 ROwen Added DoSmooth constant. 2009-11-20 ROwen Modified to use numpy. """ import numpy import PyGuide from Stats import Stats # settings DoSmooth = True ImWidth = 64 Sky = 1000, # sky level, in ADU CCDInfo = PyGuide.CCDInfo( bias=2176, # image bias, in ADU readNoise=19, # read noise, in e- ccdGain=2.1, # inverse ccd gain, in e-/ADU ) Thresh = 2.5 imShape = (ImWidth, ImWidth) nomCtr = (ImWidth // 2, ImWidth // 2) mask = numpy.zeros(imShape, numpy.bool) NaN = float("NaN") # settings AmplValues = (100, 1000, 10000) FWHMValues = (2.0, 3.0, 4.0) MaskWidthsPerFWHM = (0.0, 0.5, 1.0, 1.5, 2.0) # fractions of a FWHM NumTries = 20
"""it's a test, ok? """ import pyfits import numpy import PyGuide import autoPhot from autoPhot.config import flareCam ccdInfo = PyGuide.CCDInfo(0, flareCam.readNoise, flareCam.ccdGain) img = pyfits.open('/Users/csayres/data/arcsat/GJ1243/gFilter/oneNight/ccs20120520.00001139.LUMINANCE.FIT') data = img[0].data img.close() coord1 = numpy.array([197.66827757, 209.33221882]) coord2 = numpy.array([ 343.39379969, 210.25893067]) cent1 = PyGuide.centroid(data, None, None, coord1, rad = 2, #pixels ccdInfo = ccdInfo) cent2 = PyGuide.centroid(data, None, None, coord2, rad = 2, #pixels ccdInfo = ccdInfo) diff1 =
import calendar import time import timeit import cv2 DEBUG = True #add path to PyGuide, I think it is some weirdness going on with using #Anaconda and what paths are set. sys.path.append("/usr/local/lib/python2.7/dist-packages") import PyGuide # Default Parameters # these settings will need to be updated once we have the real guide camera # in order, bias (ADU), readnoise (e-), gain (e-/ADU), saturation level (ADU) ccdInfo = PyGuide.CCDInfo(10.0, 4.01, 1.5, 256) # these are general settings thresh = 5.0 radMult = 3.0 rad = 20 satLevel = (2**8) - 1 verbosity = 0 doDS9 = False mask = None satMask = None def imageList(fpath): """Find all images with a given extention and return their names as a list""" flist = raw_input("What is the file identifier? (*.?) >")
Shows centroid and star shape warning messages. 2005-10-14 ROwen Supply null satMask for PyGuide 2.1. 2009-11-20 ROwen Modified to use numpy. """ import sys import traceback import numpy import PyGuide from Stats import Stats # image data info ImWidth = 512 Sky = 1000 # sky level, in ADU CCDInfo = PyGuide.CCDInfo( bias = 2176, # image bias, in ADU readNoise = 19, # read noise, in e- ccdGain = 2.1, # inverse ccd gain, in e-/ADU ) # other settings DoCentroid = True Thresh = 2.0 # allow marginal cases through to exercise starShape harder # though as of 2005-05-18 a threshold of 2.0 does not give significantly # worse star fits than a threshold of 2.5. AmplValues = (100, 1000, 10000) FWHMValues = (2.0, 3.0, 4.0) MaskWidthsPerFWHM = (0.0, 0.5, 1.0, 1.5, 2.0) # fractions of a FWHM NumTries = 10 imShape = (ImWidth, ImWidth) nomCtr = (ImWidth // 2, ImWidth // 2)
def presskey(self, event): """ Do stuff when press key """ #quit on q if (event.key == "q"): self.OnExit() #centroid on c elif (event.key == "c"): ccd = PyGuide.CCDInfo(0, 0, 1) centroid = PyGuide.centroid(self.fitimg, None, None, [event.xdata, event.ydata], 20, ccd) self.starx.append(centroid.xyCtr[0]) self.stary.append(centroid.xyCtr[1]) thisra, thisdec = self.wcs.wcs_pix2world( centroid.xyCtr[0], centroid.xyCtr[1], 1) self.starra.append(thisra) self.stardec.append(thisdec) self.starid.append(self.find_id(thisra, thisdec)) self.nstars = self.nstars + 1 self.update_twodimage(update=True) #store bottom left corner on L elif (event.key == "n"): try: check = float(event.xdata) + float(event.ydata) self.boxlx.append(event.xdata) self.boxly.append(event.ydata) self.warning.set("STATUS: Now mark top/right corner!") except: self.boxlx.append(event.xdata) self.boxly.append(event.ydata) self.warning.set( "STATUS: Missed data region... try again!") elif (event.key == "m"): try: check = float(event.xdata) + float(event.ydata) self.boxrx.append(event.xdata) self.boxry.append(event.ydata) self.nbox = self.nbox + 1 self.update_twodimage(update=True) self.warning.set("STATUS: All good!") except: self.warning.set( "STATUS: Missed data region... try again!") elif (event.key == "d"): if (self.nbox > 0): self.boxlx = self.boxlx[0:-1] self.boxly = self.boxly[0:-1] self.boxrx = self.boxrx[0:-1] self.boxry = self.boxry[0:-1] self.nbox = self.nbox - 1 if (self.nstars > 0): self.starra = self.starra[0:-1] self.stardec = self.stardec[0:-1] self.starid = self.starid[0:-1] self.starx = self.starx[0:-1] self.stary = self.stary[0:-1] self.nstars = self.nstars - 1 self.update_twodimage(update=True)
def doCentroid(imName=None, maskName=None, satMaskName=None, xyGuess=None, invertMask=False, **kargs): """Centroid and shape-fit a star Inputs: - all the arguments for loadFiles plus most values shown by showDef """ global im, imFits, mask, maskFits, satMask, satMaskFits, isSat, sd im, mask, satMask = loadFiles(imName, maskName, satMaskName, invertMask) if xyGuess is None: print("xyGuess is required") return # check keyword arguments for paramName in kargs: if paramName not in CentroidParamNames: raise RuntimeError("Invalid argument: %s" % (paramName, )) # fill in defaults globalDict = globals() for paramName in CentroidParamNames: 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) if kargs["rad"] is None: print("rad argument is required because the default is presently None") return verbosity = kargs["verbosity"] # centroid ctrData = PyGuide.centroid(data=im, mask=mask, satMask=satMask, xyGuess=xyGuess, ccdInfo=ccdInfo, **kargs) if not ctrData.isOK: print("centroid failed:", ctrData.msgStr) return shapeData = PyGuide.starShape( data=im, mask=mask, xyCtr=ctrData.xyCtr, rad=ctrData.rad, verbosity=verbosity, ) # print results printStarHeader() printStarData(ctrData, shapeData) if not shapeData.isOK: print("starShape failed:", shapeData.msgStr)