from ggg import * import threading import time import mmm class subc(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): print 'sleep 3s...\n' time.sleep(3) print 'sleep 3s end\n' print '%s set event...' % threading.currentThread().getName() event.set() print '%s set event end' % threading.currentThread().getName() t2 = mmm.mmm() t2.setDaemon(True) t2.start() t1 = subc() t1.setDaemon(True) t1.start() t2.join() print '---'
def calc_masked_aperture(ap, image, method='mmm', mask=None): positions = ap.positions extents = np.zeros((len(positions), 4), dtype=int) if isinstance(ap, EllipticalAnnulus): radius = ap.a_out elif isinstance(ap, CircularAnnulus): radius = ap.r_out elif isinstance(ap, CircularAperture): radius = ap.r elif isinstance(ap, EllipticalAperture): radius = ap.a extents[:, 0] = positions[:, 0] - radius + 0.5 extents[:, 1] = positions[:, 0] + radius + 1.5 extents[:, 2] = positions[:, 1] - radius + 0.5 extents[:, 3] = positions[:, 1] + radius + 1.5 ood_filter, extent, phot_extent = get_phot_extents(image, positions, extents) x_min, x_max, y_min, y_max = extent x_pmin, x_pmax, y_pmin, y_pmax = phot_extent bkg = np.zeros(len(positions)) area = np.zeros(len(positions)) for i in range(len(bkg)): if isinstance(ap, EllipticalAnnulus): fraction = elliptical_overlap_grid(x_pmin[i], x_pmax[i], y_pmin[i], y_pmax[i], x_max[i] - x_min[i], y_max[i] - y_min[i], ap.a_out, ap.b_out, ap.theta, 0, 1) b_in = ap.a_in * ap.b_out / ap.a_out fraction -= elliptical_overlap_grid(x_pmin[i], x_pmax[i], y_pmin[i], y_pmax[i], x_max[i] - x_min[i], y_max[i] - y_min[i], ap.a_in, b_in, ap.theta, 0, 1) elif isinstance(ap, CircularAnnulus): fraction = circular_overlap_grid(x_pmin[i], x_pmax[i], y_pmin[i], y_pmax[i], x_max[i] - x_min[i], y_max[i] - y_min[i], ap.r_out, 0, 1) fraction -= circular_overlap_grid(x_pmin[i], x_pmax[i], y_pmin[i], y_pmax[i], x_max[i] - x_min[i], y_max[i] - y_min[i], ap.r_in, 0, 1) elif isinstance(ap, CircularAperture): fraction = circular_overlap_grid(x_pmin[i], x_pmax[i], y_pmin[i], y_pmax[i], x_max[i] - x_min[i], y_max[i] - y_min[i], ap.r, 0, 1) elif isinstance(ap, EllipticalAperture): fraction = elliptical_overlap_grid(x_pmin[i], x_pmax[i], y_pmin[i], y_pmax[i], x_max[i] - x_min[i], y_max[i] - y_min[i], ap.a, ap.b, ap.theta, 0, 1) pixel_data = image[y_min[i]:y_max[i], x_min[i]:x_max[i]] * fraction if mask is not None: pixel_data[mask[y_min[i]:y_max[i], x_min[i]:x_max[i]]] = 0.0 good_pixels = pixel_data[pixel_data != 0.0].flatten() if method == 'mmm': skymod, skysigma, skew = mmm(good_pixels) bkg[i] = skymod elif method == 'sum': bkg[i] = np.sum(good_pixels) elif method == 'max': bkg[i] = np.nanmax(good_pixels) area[i] = len(good_pixels) return bkg, area
def aper(image,xc,yc, phpadu=1, apr=5, zeropoint=25, skyrad=[40,60], badpix=[0,0], setskyval = None, minsky=[], skyisempty=False, exact = False, readnoise = 0, verbose=True, debug=False,ignoreneg=False): """ Compute concentric aperture photometry on one ore more stars (adapted for IDL from DAOPHOT, then translated from IDL to Python). APER can compute photometry in several user-specified aperture radii. A separate sky value is computed for each source using specified inner and outer sky radii. By default, APER uses a magnitude system where a magnitude of 25 corresponds to 1 flux unit. APER returns both fluxes and magnitudes. REQUIRED INPUTS: image - input image array xc - scalar x value or 1D array of x coordinates. yc - scalar y value or 1D array of y coordinates OPTIONAL KEYWORD INPUTS: phpadu - Photons per Analog Digital Units, numeric scalar. Converts the data numbers in IMAGE to photon units. (APER assumes Poisson statistics.) apr - scalar or 1D array of photometry aperture radii in pixel units. zeropoint - zero point for converting flux (in ADU) to magnitudes skyrad - Two element list giving the inner and outer radii to be used for the sky annulus badpix - Two element list giving the minimum and maximum value of a good pix. If BADPIX[0] is equal to BADPIX[1] then it is assumed that there are no bad pixels. exact - By default, APER counts subpixels, but uses a polygon approximation for the intersection of a circular aperture with a square pixel (and normalize the total area of the sum of the pixels to exactly match the circular area). If the /EXACT keyword, then the intersection of the circular aperture with a square pixel is computed exactly. The /EXACT keyword is much slower and is only needed when small (~2 pixels) apertures are used with very undersampled data. print - if set and non-zero then APER will also write its results to a file aper.prt. One can specify the output file name by setting PRINT = 'filename'. verbose - Print warnings, status, and ancillary info to the terminal setskyval - Use this keyword to force the sky to a specified value rather than have APER compute a sky value. SETSKYVAL can either be a scalar specifying the sky value to use for all sources, or a 3 element vector specifying the sky value, the sigma of the sky value, and the number of elements used to compute a sky value. The 3 element form of SETSKYVAL is needed for accurate error budgeting. RETURNS: mags - NAPER by NSTAR array giving the magnitude for each star in each aperture. (NAPER is the number of apertures, and NSTAR is the number of stars). A flux of 1 digital unit is assigned a zero point magnitude of 25. magerr - NAPER by NSTAR array giving error in magnitude for each star. If a magnitude could not be deter- mined then ERRAP = 9.99. flux - NAPER by NSTAR array giving fluxes fluxerr - NAPER by NSTAR array giving error in each flux sky - NSTAR element array giving sky value for each star skyerr - NSTAR element array giving error in sky values outstr - string for each star and aperture reporting the mag and err PROCEDURES USED: MMM, PIXWT() NOTES: Reasons that a valid magnitude cannot be computed include the following: (1) Star position is too close (within 0.5 pixels) to edge of the frame (2) Less than 20 valid pixels available for computing sky (3) Modal value of sky could not be computed by the procedure MMM (4) *Any* pixel within the aperture radius is a "bad" pixel APER was modified in June 2000 in two ways: (1) the /EXACT keyword was added (2) the approximation of the intersection of a circular aperture with square pixels was improved (i.e. when /EXACT is not used) REVISON HISTORY: Adapted to IDL from DAOPHOT June, 1989 B. Pfarr, STX Adapted for IDL Version 2, J. Isensee, July, 1990 Code, documentation spiffed up W. Landsman August 1991 TEXTOUT may be a string W. Landsman September 1995 FLUX keyword added J. E. Hollis, February, 1996 SETSKYVAL keyword, increase maxsky W. Landsman, May 1997 Work for more than 32767 stars W. Landsman, August 1997 Converted to IDL V5.0 W. Landsman September 1997 Don't abort for insufficient sky pixels W. Landsman May 2000 Added /EXACT keyword W. Landsman June 2000 Allow SETSKYVAL = 0 W. Landsman December 2000 Set BADPIX[0] = BADPIX[1] to ignore bad pixels W. L. January 2001 Fix chk_badpixel problem introduced Jan 01 C. Ishida/W.L. February 2001 Converted from IDL to python D. Jones January 2014 Adapted for hstphot project S. Rodney July 2014 """ if verbose > 1: import time tstart = time.time() elif verbose: import time if debug : import pdb pdb.set_trace() # Set parameter limits if len(minsky) == 0: minsky = 20 #minsky = -1000. # Number of columns and rows in image array s = np.shape(image) ncol = s[1] nrow = s[0] if setskyval is not None : if not np.iterable(setskyval) : setskyval = [setskyval,0.,1.] assert len(setskyval)==3, 'Keyword SETSKYVAL must contain 1 or 3 elements' skyrad = [ 0., max(apr) + 1] skyrad = asfarray(skyrad) if not np.iterable( xc ): xc = np.array([xc]) yc = np.array([yc]) assert len(xc) == len(yc), 'xc and yc arrays must be identical length.' if not np.iterable( apr ) : apr = np.array( [ apr ] ) Naper = len( apr ) # Number of apertures Nstars = len( xc ) # Number of stars to measure # String array to display mags for all apertures in one line for each star outstr = [ '' for star in range(Nstars)] # Declare arrays mag = zeros( [ Nstars, Naper]) magerr = zeros( [ Nstars, Naper]) flux = zeros( [ Nstars, Naper]) fluxerr = zeros( [ Nstars, Naper]) badflag = zeros( [ Nstars, Naper]) sky = zeros( Nstars ) skyerr = zeros( Nstars ) area = np.pi*apr*apr # Area of each aperture if exact: bigrad = apr + 0.5 smallrad = apr/np.sqrt(2) - 0.5 if setskyval is None : rinsq = skyrad[0]**2 routsq = skyrad[1]**2 # Compute the limits of the submatrix. Do all stars in vector notation. lx = (xc-skyrad[1]).astype(int) # Lower limit X direction ly = (yc-skyrad[1]).astype(int) # Lower limit Y direction ux = (xc+skyrad[1]).astype(int) # Upper limit X direction uy = (yc+skyrad[1]).astype(int) # Upper limit Y direction lx[where(lx < 0)[0]] = 0 ux[where(ux > ncol-1)[0]] = ncol-1 nx = ux-lx+1 # Number of pixels X direction ly[where(ly < 0)[0]] = 0 uy[where(uy > nrow-1)[0]] = nrow-1 ny = uy-ly +1 # Number of pixels Y direction dx = xc-lx # X coordinate of star's centroid in subarray dy = yc-ly # Y coordinate of star's centroid in subarray # Find the edge of the subarray that is closest to each star # and then flag any stars that are too close to the edge or off-image edge = zeros(len(dx)) for i,dx1,nx1,dy1,ny1 in zip(range(len(dx)),dx,nx,dy,ny): edge[i] = min([(dx[i]-0.5),(nx[i]+0.5-dx[i]),(dy[i]-0.5),(ny[i]+0.5-dy[i])]) badstar = np.where( (xc<0.5) | (xc>ncol-1.5) | (yc<0.5) | (yc>nrow-1.5), 1, 0 ) if np.any( badstar ) : nbad = badstar.sum() print('WARNING - ' + str(nbad) + ' star positions outside image') if verbose : tloop = time.time() for i in range(Nstars): # Compute magnitudes for each star #print i,Nstars while True : # mimic GOTO statements : break out of this while block whenever # we decide this star is bad apflux = asarray([np.nan]*Naper) apfluxerr = asarray([np.nan]*Naper) apmag = asarray([np.nan]*Naper) apmagerr = asarray([np.nan]*Naper) skymod = 0. # Sky mode skysig = 0. # Sky sigma skyskw = 0. # Sky skew error1 = asarray([np.nan]*Naper) error2 = asarray([np.nan]*Naper) error3 = array([np.nan]*Naper) apbad = np.ones( Naper ) if badstar[i]: # star is bad, return NaNs for all values break rotbuf = image[ ly[i]:uy[i]+1,lx[i]:ux[i]+1 ] #Extract subarray from image shapey,shapex = np.shape(rotbuf)[0],np.shape(rotbuf)[1] # RSQ will be an array, the same size as ROTBUF containing the square of # the distance of each pixel to the center pixel. dxsq = ( arange( nx[i] ) - dx[i] )**2 # if ny[i] < 0: # if verbose: # print("WARNING : aperture extends outside the image!") # continue # if nx[i] < 0: # if verbose: # print("WARNING : aperture extends outside the image!") # continue try: rsq = np.ones( [ny[i], nx[i]] ) except: print 'negative dimension' break for ii in range(ny[i]): rsq[ii,:] = dxsq + (ii-dy[i])**2 if exact: nbox = range(nx[i]*ny[i]) xx = (nbox % nx[i]).reshape( ny[i], nx[i]) yy = (nbox/nx[i]).reshape(ny[i],nx[i]) x1 = np.abs(xx-dx[i]) y1 = np.abs(yy-dy[i]) else: r = np.sqrt(rsq) - 0.5 #2-d array of the radius of each pixel in the subarray rsq,rotbuf = rsq.reshape(shapey*shapex),rotbuf.reshape(shapey*shapex) if setskyval is None : # skypix will be 1-d array of sky pixels skypix = np.zeros( rsq.shape ) # Select pixels within sky annulus, skypix[where(( rsq >= rinsq ) & ( rsq <= routsq ))[0]] = 1 if badpix[0]!=badpix[1] : # Eliminate pixels above or below the badpix threshold vals skypix[where(((rotbuf < badpix[0]) | (rotbuf > badpix[1])) & (skypix == 1))[0]] = 0 sindex = where(skypix)[0] nsky = len(sindex) if ( nsky < minsky ): # Insufficient sky pixels? if verbose: print("ERROR: nsky=%i is fewer than minimum %i valid pixels in the sky annulus."%(nsky,minsky)) break skybuf = rotbuf[ sindex[0:nsky] ] if skyisempty : # The sky annulus is (nearly) empty of stars, (as in a diff image) # so we can simply compute the sigma-clipped mean of all pixels in # the annulus skybufclipped = sigmaclip( skybuf, low=4.0, high=4.0) try: skymod = np.mean( skybufclipped )[0] skysig = np.std( skybufclipped )[0] except: print 'sky buff excepted' skymod, skysig, skyskw = mmm.mmm(skybuf, readnoise=readnoise, minsky=minsky) skyskw = -999#skew( skybufclipped ) else: # Compute the sky mode, sigma and skewness using the # mean/median/mode algorithm in mmm.py, which assumes that # most of the outlier pixels are positive. skymod, skysig, skyskw = mmm.mmm(skybuf,readnoise=readnoise,minsky=minsky) skyvar = skysig**2 #Variance of the sky brightness sigsq = skyvar/nsky #Square of standard error of mean sky brightness if ( skysig < 0.0 ): # If the modal sky value could not be determined, then all # apertures for this star are bad. So skip to the next. break if skysig > 999.99: skysig = 999 #Don't overload output formats if skyskw < -99: skyskw = -99 if skyskw > 999.9: skyskw = 999.9 else: skymod = setskyval[0] skysig = setskyval[1] nsky = setskyval[2] skyvar = skysig**2 sigsq = skyvar/nsky skyskw = 0 for k in range(Naper): # Find pixels within each aperture thisapd = array([]) if ( edge[i] >= apr[k] ): #Does aperture extend outside the image? if exact: mask = zeros(ny[i]*nx[i]) x1,y1 = x1.reshape(ny[i]*nx[i]),y1.reshape(ny[i]*nx[i]) good = where( ( x1 < smallrad[k] ) & (y1 < smallrad[k] ))[-1] Ngood = len(good) if Ngood > 0: mask[good] = 1 bad = where( (x1 > bigrad[k]) | (y1 > bigrad[k] ))[-1] mask[bad] = -1 gfract = where(mask == 0.0)[0] Nfract = len(gfract) if Nfract > 0: yygfract = yy.reshape(ny[i]*nx[i])[gfract] xxgfract = xx.reshape(ny[i]*nx[i])[gfract] mask[gfract] = pixwt.Pixwt(dx[i],dy[i],apr[k],xxgfract,yygfract) mask[gfract[where(mask[gfract] < 0.0)[0]]] = 0.0 thisap = where(mask > 0.0)[0] thisapd = rotbuf[thisap] fractn = mask[thisap] else: # approximating the circular aperture shape rshapey,rshapex = np.shape(r)[0],np.shape(r)[1] thisap = where( r.reshape(rshapey*rshapex) < apr[k] )[0] # Select pixels within radius thisapd = rotbuf.reshape(rshapey*rshapex)[thisap] thisapr = r.reshape(rshapey*rshapex)[thisap] fractn = apr[k]-thisapr fractn[where(fractn > 1)[0]] = 1 fractn[where(fractn < 0)[0]] = 0 # Fraction of pixels to count full = zeros(len(fractn)) full[where(fractn == 1)[0]] = 1.0 gfull = where(full)[0] Nfull = len(gfull) gfract = where(1 - full)[0] factor = (area[k] - Nfull ) / np.sum(fractn[gfract]) fractn[gfract] = fractn[gfract]*factor else: if verbose : print("WARNING : aperture extends outside the image!") continue # END "if exact ... else ..." # Check for any bad pixel values (nan,inf) and those outside # the user-specified range of valid pixel values. If any # are found in the aperture, raise the badflux flag. apbad[k] = 0 if not np.all( np.isfinite(thisapd) ) : if verbose : print("WARNING : nan or inf pixels detected in aperture.\n" "We're setting these to 0, but the photometry" "may be biased.") thisapd[np.isfinite()==False] = 0 apbad[k] = 1 fractn = 0 if badpix[0] < badpix[1] : ibadpix = np.where((thisapd<=badpix[0]) | (thisapd>=badpix[1])) if len(ibadpix[0]) > 0 : if verbose : print("WARNING : pixel values detected in aperture" " that are outside of the allowed range " " [%.1f , %.1f] \n"%(badpix[0],badpix[1]) + "We're treating these as 0, but the " "photometry may be biased.") thisapd[ibadpix] = 0 apbad[k] = 1 # Sum the flux over the irregular aperture apflux[k] = np.sum(thisapd*fractn) # END for loop over apertures g = where(np.isfinite(apflux))[0] Ng = len(g) if Ng > 0: # Subtract sky from the integrated brightnesses apflux[g] = apflux[g] - skymod*area[g] # Compute flux error error1[g] = area[g]*skyvar #Scatter in sky values error2[g] = where( apflux[g]>=0, apflux[g]/phpadu, 0 ) #Random photon noise error3[g] = sigsq*area[g]**2 #Uncertainty in mean sky brightness apfluxerr[g] = np.sqrt(error1[g] + error2[g] + error3[g]) good = where (apflux > 0.0)[0] # Are there any valid integrated fluxes? Ngood = len(good) if ( Ngood > 0 ) : # convert valid fluxes to mags apmagerr[good] = 1.0857*apfluxerr[g]/apflux[g] #1.0857 = log(10)/2.5 apmag[good] = zeropoint-2.5*np.log10(apflux[g]) break # Closing the 'while True' loop. # TODO : make a more informative output string outstr[i] = '%.3f,%.3f :'%(xc[i],yc[i]) + \ ' '.join( [ '%.4f+-%.4f'%(apmag[ii],apmagerr[ii]) for ii in range(Naper) ] ) sky[i] = skymod skyerr[i] = skysig mag[i,:] = apmag magerr[i,:]= apmagerr flux[i,:] = apflux fluxerr[i,:]= apfluxerr badflag[i,:] = apbad if Nstars == 1 : sky = sky[0] skyerr = skyerr[0] mag = mag[0] magerr = magerr[0] flux = flux[0] fluxerr = fluxerr[0] badflag = badflag[0] outstr = outstr[0] if verbose>1: print('hstphot.aper took %.3f seconds'%(time.time()-tstart)) print('Each of %i loops took %.3f seconds'%(Nstars,(time.time()-tloop)/Nstars)) return(mag,magerr,flux,fluxerr,sky,skyerr,badflag,outstr)
def tv(self,img,min=None,max=None,cmap=None) : """ main display routine: displays image with optional scaling Args: img: a numpy array OR a fits HDU Keyword args: min=, max= : optional scaling arguments """ # load data array depending on input type if isinstance(img, (np.ndarray)) : data = img elif isinstance(img.data, (np.ndarray)) : data = img.data else : print('input must be numpy array or have data attribute that is') return # set figure and axes plt.figure(self.fig.number) plt.axes(self.ax) #self.ax.cla() #self.ax.axis('off') # make last image not visible so we don't see anything if new image is smaller if self.axlist[self.current] is not None: self.axlist[self.current].set_visible(False) # load new image data onto rolling stack current= (self.current+1) % 4 self.images += 1 if self.images > 4 : self.images = 4 self.current = current self.imglist.pop(current) self.imglist.insert(current,data) self.img = data # save the header if we have one if hasattr(img,'header') : self.hdrlist.pop(current) self.hdrlist.insert(current,img.header) self.hdr=img.header else : self.hdr=None # get autodisplay parameters if needed, and save display params if min is None : min = 0. if max is None : try : sky = mmm.mmm(data) min = sky[0]-5*sky[1] max = sky[0]+20*sky[1] except : min = np.median(data)-5*data.std() max = np.median(data)+20*data.std() self.scale = [min,max] self.scalelist.pop(current) self.scalelist.insert(current,self.scale) if cmap != None : self.cmap = cmap # display image and new colorbar dim=np.shape(self.img) size=np.max([dim[0],dim[1]]) self.ax.set_xlim(dim[1]/2.-size/2.,dim[1]/2.+size/2.) self.ax.set_ylim(dim[0]/2.-size/2.,dim[0]/2.+size/2.) #self.ax.set_xlim(-0.5,dim[1]-0.5) #self.ax.set_ylim(-0.5,dim[0]-0.5) #print('aspect: ', self.aspect,' xlim: ', self.ax.get_xlim(),' ylim: ',self.ax.get_ylim(), data.shape) self.aximage = self.ax.imshow(data,vmin=min,vmax=max,cmap=self.cmap,interpolation='nearest',aspect=self.aspect) old=self.axlist.pop(current) # if we had a previous image, reload the data with a single value # so we don't continually accumulate memory (matplotlib doesn't # describe how memory can be released z=np.zeros([1,1]) if old is not None : old.set_data(z) self.axlist.insert(current,self.aximage) if self.cb is None : #self.cb = self.fig.colorbar(self.aximage,orientation='horizontal',shrink=0.7,pad=0) self.cb = self.fig.colorbar(self.aximage,cax=self.cb_ax,orientation='horizontal') #plt.subplots_adjust(left=-0.15,right=1.15,bottom=-0.10,top=1.00) else : self.cb.ax.clear() self.cb = self.fig.colorbar(self.aximage,cax=self.cb.ax,orientation='horizontal') self.cblist.pop(current) self.cblist.insert(current,self.cb) plt.draw()
def aper(image,xc,yc, phpadu=1, apr=5, zeropoint=25, skyrad=[40,50], badpix=[0,0], setskyval = None, minsky=[], skyalgorithm='mmm', exact = False, readnoise = 0, verbose=True, debug=False): """ Compute concentric aperture photometry on one ore more stars (adapted for IDL from DAOPHOT, then translated from IDL to Python). APER can compute photometry in several user-specified aperture radii. A separate sky value is computed for each source using specified inner and outer sky radii. By default, APER uses a magnitude system where a magnitude of 25 corresponds to 1 flux unit. APER returns both fluxes and magnitudes. REQUIRED INPUTS: image - input image array xc - scalar x value or 1D array of x coordinates. yc - scalar y value or 1D array of y coordinates OPTIONAL KEYWORD INPUTS: phpadu - Photons per Analog Digital Units, numeric scalar. Converts the data numbers in IMAGE to photon units. (APER assumes Poisson statistics.) apr - scalar or 1D array of photometry aperture radii in pixel units. zeropoint - zero point for converting flux (in ADU) to magnitudes skyrad - Two element list giving the inner and outer radii to be used for the sky annulus badpix - Two element list giving the minimum and maximum value of a good pix. If BADPIX[0] is equal to BADPIX[1] then it is assumed that there are no bad pixels. exact - By default, APER counts subpixels, but uses a polygon approximation for the intersection of a circular aperture with a square pixel (and normalize the total area of the sum of the pixels to exactly match the circular area). If the /EXACT keyword, then the intersection of the circular aperture with a square pixel is computed exactly. The /EXACT keyword is much slower and is only needed when small (~2 pixels) apertures are used with very undersampled data. print - if set and non-zero then APER will also write its results to a file aper.prt. One can specify the output file name by setting PRINT = 'filename'. verbose - Print warnings, status, and ancillary info to the terminal setskyval - Use this keyword to force the sky to a specified value rather than have APER compute a sky value. SETSKYVAL can either be a scalar specifying the sky value to use for all sources, or a 3 element vector specifying the sky value, the sigma of the sky value, and the number of elements used to compute a sky value. The 3 element form of SETSKYVAL is needed for accurate error budgeting. skyalgorithm - set the algorithm by which the sky value is determined Valid options are 'sigmaclipping' or 'mmm'. RETURNS: mags - NAPER by NSTAR array giving the magnitude for each star in each aperture. (NAPER is the number of apertures, and NSTAR is the number of stars). A flux of 1 digital unit is assigned a zero point magnitude of 25. magerr - NAPER by NSTAR array giving error in magnitude for each star. If a magnitude could not be deter- mined then ERRAP = 9.99. flux - NAPER by NSTAR array giving fluxes fluxerr - NAPER by NSTAR array giving error in each flux sky - NSTAR element array giving sky value for each star skyerr - NSTAR element array giving error in sky values outstr - string for each star and aperture reporting the mag and err PROCEDURES USED: MMM, PIXWT() NOTES: Reasons that a valid magnitude cannot be computed include the following: (1) Star position is too close (within 0.5 pixels) to edge of the frame (2) Less than 20 valid pixels available for computing sky (3) Modal value of sky could not be computed by the procedure MMM (4) *Any* pixel within the aperture radius is a "bad" pixel APER was modified in June 2000 in two ways: (1) the /EXACT keyword was added (2) the approximation of the intersection of a circular aperture with square pixels was improved (i.e. when /EXACT is not used) REVISON HISTORY: Adapted to IDL from DAOPHOT June, 1989 B. Pfarr, STX Adapted for IDL Version 2, J. Isensee, July, 1990 Code, documentation spiffed up W. Landsman August 1991 TEXTOUT may be a string W. Landsman September 1995 FLUX keyword added J. E. Hollis, February, 1996 SETSKYVAL keyword, increase maxsky W. Landsman, May 1997 Work for more than 32767 stars W. Landsman, August 1997 Converted to IDL V5.0 W. Landsman September 1997 Don't abort for insufficient sky pixels W. Landsman May 2000 Added /EXACT keyword W. Landsman June 2000 Allow SETSKYVAL = 0 W. Landsman December 2000 Set BADPIX[0] = BADPIX[1] to ignore bad pixels W. L. January 2001 Fix chk_badpixel problem introduced Jan 01 C. Ishida/W.L. February 2001 Converted from IDL to python D. Jones January 2014 Adapted for hstphot project S. Rodney July 2014 """ if verbose > 1: import time tstart = time.time() elif verbose: import time if debug : import pdb pdb.set_trace() # Force np arrays if not np.iterable( xc ): xc = np.array([xc]) yc = np.array([yc]) assert len(xc) == len(yc), 'xc and yc arrays must be identical length.' if not np.iterable( apr ) : apr = np.array( [ apr ] ) Naper = len( apr ) # Number of apertures Nstars = len( xc ) # Number of stars to measure # Set parameter limits if len(minsky) == 0: minsky = 20 # Number of columns and rows in image array s = np.shape(image) ncol = s[1] nrow = s[0] if setskyval is not None : if not np.iterable(setskyval) : setskyval = [setskyval,0.,1.] assert len(setskyval)==3, 'Keyword SETSKYVAL must contain 1 or 3 elements' skyrad = [ 0., np.max(apr) + 1] #use np.max (max function does not work on scalars) skyrad = asfarray(skyrad) # String array to display mags for all apertures in one line for each star outstr = [ '' for star in range(Nstars)] # Declare arrays mag = zeros( [ Nstars, Naper]) magerr = zeros( [ Nstars, Naper]) flux = zeros( [ Nstars, Naper]) fluxerr = zeros( [ Nstars, Naper]) badflag = zeros( [ Nstars, Naper]) sky = zeros( Nstars ) skyerr = zeros( Nstars ) area = np.pi*apr*apr # Area of each aperture if exact: bigrad = apr + 0.5 smallrad = apr/np.sqrt(2) - 0.5 if setskyval is None : rinsq = skyrad[0]**2 routsq = skyrad[1]**2 # Compute the limits of the submatrix. Do all stars in vector notation. lx = (xc-skyrad[1]).astype(int) # Lower limit X direction ly = (yc-skyrad[1]).astype(int) # Lower limit Y direction ux = (xc+skyrad[1]).astype(int) # Upper limit X direction uy = (yc+skyrad[1]).astype(int) # Upper limit Y direction lx[where(lx < 0)[0]] = 0 ux[where(ux > ncol-1)[0]] = ncol-1 nx = ux-lx+1 # Number of pixels X direction ly[where(ly < 0)[0]] = 0 uy[where(uy > nrow-1)[0]] = nrow-1 ny = uy-ly +1 # Number of pixels Y direction dx = xc-lx # X coordinate of star's centroid in subarray dy = yc-ly # Y coordinate of star's centroid in subarray # Find the edge of the subarray that is closest to each star # and then flag any stars that are too close to the edge or off-image edge = zeros(len(dx)) for i,dx1,nx1,dy1,ny1 in zip(range(len(dx)),dx,nx,dy,ny): edge[i] = min([(dx[i]-0.5),(nx[i]+0.5-dx[i]),(dy[i]-0.5),(ny[i]+0.5-dy[i])]) badstar = np.where( (xc<0.5) | (xc>ncol-1.5) | (yc<0.5) | (yc>nrow-1.5), 1, 0 ) if np.any( badstar ) : nbad = badstar.sum() print('WARNING [aper.py] - ' + str(nbad) + ' star positions outside image') if verbose : tloop = time.time() for i in range(Nstars): # Compute magnitudes for each star while True : # mimic GOTO statements : break out of this while block whenever # we decide this star is bad apflux = asarray([np.nan]*Naper) apfluxerr = asarray([np.nan]*Naper) apmag = asarray([np.nan]*Naper) apmagerr = asarray([np.nan]*Naper) skymod = 0. # Sky mode skysig = 0. # Sky sigma skyskw = 0. # Sky skew error1 = asarray([np.nan]*Naper) error2 = asarray([np.nan]*Naper) error3 = array([np.nan]*Naper) apbad = np.ones( Naper ) if badstar[i]: # star is bad, return NaNs for all values break rotbuf = image[ ly[i]:uy[i]+1,lx[i]:ux[i]+1 ] #Extract subarray from image shapey,shapex = np.shape(rotbuf)[0],np.shape(rotbuf)[1] # RSQ will be an array, the same size as ROTBUF containing the square of # the distance of each pixel to the center pixel. dxsq = ( arange( nx[i] ) - dx[i] )**2 rsq = np.ones( [ny[i], nx[i]] ) for ii in range(ny[i]): rsq[ii,:] = dxsq + (ii-dy[i])**2 if exact: nbox = range(nx[i]*ny[i]) xx = (nbox % nx[i]).reshape( ny[i], nx[i]) yy = (nbox/nx[i]).reshape(ny[i],nx[i]) x1 = np.abs(xx-dx[i]) y1 = np.abs(yy-dy[i]) else: r = np.sqrt(rsq) - 0.5 #2-d array of the radius of each pixel in the subarray rsq,rotbuf = rsq.reshape(shapey*shapex),rotbuf.reshape(shapey*shapex) if setskyval is None : # skypix will be 1-d array of sky pixels skypix = np.zeros( rsq.shape ) # Select pixels within sky annulus, skypix[where(( rsq >= rinsq ) & ( rsq <= routsq ))[0]] = 1 if badpix[0]!=badpix[1] : # Eliminate pixels above or below the badpix threshold vals skypix[where(((rotbuf < badpix[0]) | (rotbuf > badpix[1])) & (skypix == 1))[0]] = 0 sindex = where(skypix)[0] nsky = len(sindex) if ( nsky < minsky ): # Insufficient sky pixels? if verbose: print("ERROR: nsky=%i is fewer than minimum %i valid pixels in the sky annulus."%(nsky,minsky)) break skybuf = rotbuf[ sindex[0:nsky] ] if skyalgorithm.startswith('sigmaclip'): # The sky annulus is (nearly) empty of stars, (as in a diff image) # so we can simply compute the sigma-clipped mean of all pixels in # the annulus skybufclipped,lothresh,hithresh = sigmaclip( skybuf, low=4.0, high=4.0) skymod = np.mean( skybufclipped ) skysig = np.std( skybufclipped ) skyskw = skew( skybufclipped ) else: # Compute the sky mode, sigma and skewness using the # mean/median/mode algorithm in mmm.py, which assumes that # most of the outlier pixels are positive. skymod, skysig, skyskw = mmm.mmm(skybuf,readnoise=readnoise,minsky=minsky) skyvar = skysig**2 #Variance of the sky brightness sigsq = skyvar/nsky #Square of standard error of mean sky brightness if ( skysig < 0.0 ): # If the modal sky value could not be determined, then all # apertures for this star are bad. So skip to the next. break if skysig > 999.99: skysig = 999 #Don't overload output formats if skyskw < -99: skyskw = -99 if skyskw > 999.9: skyskw = 999.9 else: skymod = setskyval[0] skysig = setskyval[1] nsky = setskyval[2] skyvar = skysig**2 sigsq = skyvar/nsky skyskw = 0 for k in range(Naper): # Find pixels within each aperture if ( edge[i] >= apr[k] ): #Does aperture extend outside the image? if exact: mask = zeros(ny[i]*nx[i]) x1,y1 = x1.reshape(ny[i]*nx[i]),y1.reshape(ny[i]*nx[i]) igoodmag = where( ( x1 < smallrad[k] ) & (y1 < smallrad[k] ))[-1] Ngoodmag = len(igoodmag) if Ngoodmag > 0: mask[igoodmag] = 1 bad = where( (x1 > bigrad[k]) | (y1 > bigrad[k] ))[-1] mask[bad] = -1 gfract = where(mask == 0.0)[0] Nfract = len(gfract) if Nfract > 0: yygfract = yy.reshape(ny[i]*nx[i])[gfract] xxgfract = xx.reshape(ny[i]*nx[i])[gfract] mask[gfract] = pixwt.Pixwt(dx[i],dy[i],apr[k],xxgfract,yygfract) mask[gfract[where(mask[gfract] < 0.0)[0]]] = 0.0 thisap = where(mask > 0.0)[0] thisapd = rotbuf[thisap] fractn = mask[thisap] else: # approximating the circular aperture shape rshapey,rshapex = np.shape(r)[0],np.shape(r)[1] thisap = where( r.reshape(rshapey*rshapex) < apr[k] )[0] # Select pixels within radius thisapd = rotbuf.reshape(rshapey*rshapex)[thisap] thisapr = r.reshape(rshapey*rshapex)[thisap] fractn = apr[k]-thisapr fractn[where(fractn > 1)[0]] = 1 fractn[where(fractn < 0)[0]] = 0 # Fraction of pixels to count full = zeros(len(fractn)) full[where(fractn == 1)[0]] = 1.0 gfull = where(full)[0] Nfull = len(gfull) gfract = where(1 - full)[0] factor = (area[k] - Nfull ) / np.sum(fractn[gfract]) fractn[gfract] = fractn[gfract]*factor else: if verbose : print("WARNING [aper.py]: aperture extends outside the image!") continue # END "if exact ... else ..." # Check for any bad pixel values (nan,inf) and those outside # the user-specified range of valid pixel values. If any # are found in the aperture, raise the badflux flag. apbad[k] = 0 if not np.all( np.isfinite(thisapd) ) : if verbose : print("WARNING : nan or inf pixels detected in aperture.\n" "We're setting these to 0, but the photometry" "may be biased.") thisapd[np.isfinite(thisapd)==False] = 0 apbad[k] = 1 fractn = 0 if badpix[0] < badpix[1] : ibadpix = np.where((thisapd<=badpix[0]) | (thisapd>=badpix[1])) if len(ibadpix[0]) > 0 : if verbose : print("WARNING : pixel values detected in aperture" " that are outside of the allowed range " " [%.1f , %.1f] \n"%(badpix[0],badpix[1]) + "We're treating these as 0, but the " "photometry may be biased.") thisapd[ibadpix] = 0 apbad[k] = 1 # Sum the flux over the irregular aperture apflux[k] = np.sum(thisapd*fractn) # END for loop over apertures igoodflux = where(np.isfinite(apflux))[0] Ngoodflux = len(igoodflux) if Ngoodflux > 0: if verbose > 2 : print(" SRCFLUX APFLUX SKYMOD AREA") for igf in igoodflux : print("%.4f %.4f %.4f %.4f "%(apflux[igf]-skymod*area[igf],apflux[igf],skymod,area[igf])) # Subtract sky from the integrated brightnesses apflux[igoodflux] = apflux[igoodflux] - skymod*area[igoodflux] # Compute flux error error1[igoodflux] = area[igoodflux]*skyvar #Scatter in sky values error2[igoodflux] = np.abs(apflux[igoodflux])/phpadu #Random photon noise error3[igoodflux] = sigsq*area[igoodflux]**2 #Uncertainty in mean sky brightness apfluxerr[igoodflux] = np.sqrt(error1[igoodflux] + error2[igoodflux] + error3[igoodflux]) igoodmag = where (apflux > 0.0)[0] # Are there any valid integrated fluxes? Ngoodmag = len(igoodmag) if ( Ngoodmag > 0 ) : # convert valid fluxes to mags apmagerr[igoodmag] = 1.0857*apfluxerr[igoodmag]/apflux[igoodmag] #1.0857 = log(10)/2.5 apmag[igoodmag] = zeropoint-2.5*np.log10(apflux[igoodmag]) break # Closing the 'while True' loop. # TODO : make a more informative output string outstr[i] = '%.3f,%.3f :'%(xc[i],yc[i]) + \ ' '.join( [ '%.4f+-%.4f'%(apmag[ii],apmagerr[ii]) for ii in range(Naper) ] ) sky[i] = skymod skyerr[i] = skysig mag[i,:] = apmag magerr[i,:]= apmagerr flux[i,:] = apflux fluxerr[i,:]= apfluxerr badflag[i,:] = apbad if Nstars == 1 : sky = sky[0] skyerr = skyerr[0] mag = mag[0] magerr = magerr[0] flux = flux[0] fluxerr = fluxerr[0] badflag = badflag[0] outstr = outstr[0] if verbose>1: print('hstphot.aper took %.3f seconds'%(time.time()-tstart)) print('Each of %i loops took %.3f seconds'%(Nstars,(time.time()-tloop)/Nstars)) return(mag,magerr,flux,fluxerr,sky,skyerr,badflag,outstr)
import time import mmm class subc(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): print 'sleep 3s...\n' time.sleep(3) print 'sleep 3s end\n' #global ggg.isflag print 'subc isflag id: ', id(ggg.isflag) ggg.isflag = True print 'subc isflag: ', ggg.isflag t2 = mmm.mmm() t2.setDaemon(True) t2.start() t1 = subc() t1.setDaemon(True) t1.start() t2.join() print '---'