def sky2pix(self, coordinate, origin=0): r""" Calculates the Pixel corresponding to a given coordinate. Parameters ---------- coordinate : list Either ['RA','DEC'], e.g. ['1:34:7.00', '+30:47:52.00'] in equatorial coordinates or [RA, DEC] in GRAD. origin : int ``0`` or ``1``; this steers how the first pixel is counted ``0`` is for usage with python as it starts to count from zero. ``1`` is the fits standart. Returns ------- pixel : List [x, y]; the pixel coordinates of the map. """ # Equatorial_to_degrees is only possible to execute if coordinate is in # the correct form for RA DEC. self.log.debug("Calculate map pixel for coord. {}".format(coordinate)) try: self.log.debug("Test trying to convert coord. to degrees") coordinate = astFunc.equatorial_to_degrees(coordinate) self.log.debug("Calculated coordinate in "\ "Degrees: {}".format(coordinate)) except AttributeError: self.log.debug("Conversion to degrees failed. "\ "This does not have to be a problem.") coordinate = np.array([[coordinate[0], coordinate[1]]], np.float_) self.log.debug("Retrieving the pixels of the map at given coordinate") sky2pix_result = self.wcs.wcs_world2pix(coordinate, origin) pixel = sky2pix_result[0] # The pixels are floats. To get integers we get the floor value # of the floats pixel = [int(math.floor(float(pixel[0]))), int(math.floor(float(pixel[1])))] self.log.debug("Output pixel {}".format(pixel)) return pixel
def read_aperture(self, position, apertureSize=0, backgroundSize=0, output=False, annotation=False, newAnnotation=False): # TODO: needs better scheme for the header keywords. Migth not work # with all maps. r""" Extract the sum and mean flux inside an aperture of a given size and at a given position.. This function can be used to read the flux in the area of a circular aperture, as well as to correct for the background flux. Parameters ---------- position : list The position in RA,DEC where the aperture is to be applied. The Format has to be either: * ['RA','DEC'] with strings representing equatorial coordinates, e.g. ['01:34:32.8', '+30:47:00.6']. or: * [RA, DEC] where RA and DEC being the coordinates in Grad. apertureSize : float [arcsec] The diameter of the aperture to be applied. backgroundSize : float [arcsec] The Size of the Anulli in which the background is to be estimated. The number to be given here correspond to the diameter of the circle in [arcsec ] descibing the outer border of the annuli, measured from the position given in position. Thus, the background is measurd in the ring described by apertureSize and backgroundSize. Default is 0 and thus **no background substaction** is applied. output : True or False If True the function reports the calculated values during execution. annotion : logical If True a kvis annotation file ``"apertures.ann"`` containing the aperture used to integrate the flux is created. Default is False, i.e. not to create the aperture. newAnnotation : logical If True ``"apertures.ann"`` is overwritten. If False an old ``"apertures.ann"`` is used to append the new apertures. If it not exists a new one is created. The latter is the default. Returns ------- List : [Sum, Mean, Number of pixels] Notes ----- The pixel sizes have to be quadratic for the algorithm to work. It measures a circle by counting the pixels from the central pixel corresponding to the given coordinate. """ self.log.debug( "Determining the Flux at position: {}; "\ "in aperture of size {} and background of {}".format( position, apertureSize, backgroundSize) ) # Calculate the x,y Pixel coordinate of the position. xCenter, yCenter = self.sky2pix(position) # Read the pixel Size (normaly in Grad FITS-Standard) try: self.pixSize1 = float(self.header['CDELT1']) self.pixSize2 = float(self.header['CDELT2']) except: # sometimes the header keywords are different. try: self.pixSize1 = float(self.header['XPIXSIZE']) self.pixSize2 = float(self.header['YPIXSIZE']) self.pixSize1 = self.pixSize1 / 60 / 60 self.pixSize2 = self.pixSize2 / 60 / 60 except: print 'No Header keyword for the pixsize found' sys.exit() # Check if the pixel size is quadratic, if not the function does not # work correctly (yet) if ((((self.pixSize1) ** 2 - (self.pixSize2) ** 2) ** 2 < ((self.pixSize1) ** 2) * 0.01)): if output is True: print ('Pixel Size X: ' + str(self.pixSize1 / (1. / 60 / 60)) + ' arcsec') print ('Pixel Size Y: ' + str(self.pixSize2 / (1. / 60 / 60)) + ' arcsec') print ('Pixel Size quadratic to 1%, Go on with ' 'calculation of Apertures') else: if output is True: print self.pixSize1, self.pixSize2 print ('Pixel Size *NOT* quadratic: Exit the program, ' 'please regrid!') sys.exit() # Convert the apertureSizes to Grad f apertureSizeInGrad = (1. / 60 / 60) * (apertureSize) / 2 # Calculate how many pixels are needed to cover the radius of the # aperture apertureSteps = math.sqrt(math.floor(apertureSizeInGrad / self.pixSize1) ** 2) # same for the backround annuli if backgroundSize != 0: backgroundSizeInGrad = (1. / 60 / 60) * (backgroundSize) / 2 backgroundSteps = math.sqrt(math.floor(backgroundSizeInGrad / self.pixSize1) ** 2) x_max, x_min = xCenter + backgroundSteps, xCenter - backgroundSteps y_max, y_min = yCenter + backgroundSteps, yCenter - backgroundSteps else: x_max, x_min = xCenter + apertureSteps, xCenter - apertureSteps y_max, y_min = yCenter + apertureSteps, yCenter - apertureSteps # calculate the x and y range in Pixel coordinates that are needed at # most for the calculation of the aperture and background # Now: Initialize variables sum = 0 # will store the sum of all Pixels in the aperture N = 0 # counts the number of pixels in the aperture to be able to # calculate the mean sumBackgnd = 0 # the sum of all pixels in the background NBackgnd = 0 # number of pixels in the background # calculate the background if backgroundSize != 0: for x in range(int(x_min), int(x_max)): for y in range(int(y_min), int(y_max)): if ((math.floor(math.sqrt((xCenter - x) ** 2 + (yCenter - y) ** 2)) < backgroundSteps and math.floor(math.sqrt((xCenter - x) ** 2 + (yCenter - y) ** 2)) > apertureSteps)): sumBackgnd += self.data[y][x] NBackgnd += 1 backgndMean = sumBackgnd / NBackgnd print backgndMean # caclulate the sum in the aperture for x in range(int(x_min), int(x_max)): for y in range(int(y_min), int(y_max)): if (math.floor(math.sqrt((xCenter - x) ** 2 + (yCenter - y) ** 2)) < apertureSteps): if backgroundSize != 0: sum += self.data[y][x] - backgndMean else: sum += self.data[y][x] N += 1 if backgroundSize != 0: mean = (sum / N) - backgndMean sumcorrected = sum - (N * backgndMean) result = [sum, mean, N] if backgroundSize == 0: mean = (sum / N) result = [sum, mean, N] if output is True: print ('Sum:', result[0], 'Mean:', result[1], 'Number of Pixel:', result[2]) if newAnnotation is False: fileout = open('apertures.ann', 'a') if newAnnotation is True: fileout = open('apertures.ann', 'w') if annotation is True: position = astFunc.equatorial_to_degrees(position) apertureString = ('CROSS ' + str(position[0]) + ' ' + str(position[1]) + ' 0.0008 0.001 \n' 'circle ' + str(position[0]) + ' ' + str(position[1]) + ' ' + str(apertureSize * (1. / 60 / 60) / 2) + ' \n' 'text ' + str(position[0] + (1. / 60 / 60)) + ' ' + str(position[1] + (1. / 60 / 60)) + '\n') fileout.write(apertureString) fileout.close() return result