def determine_imageOverlap(f1, f2, plotsave=False, verbose=False, debugmode=False, quietmode=False): ''' Determine the max number of pixels in AXIS1 and AXIS2 of the input fits images, print to screen unless suppressed. Plot up the footprint if -p option is on. Right now, only takes in 2 fits images (YOLO).''' # Read in f1,f2 d1, h1 = fits.getdata(f1, header=True) d2, h2 = fits.getdata(f2, header=True) w1 = wcs.WCS(h1) w2 = wcs.WCS(h2) # Get the RA and DEC coordinates of the four corners of each image four_corners_RADECs1 = get_cornerRADECs(f1) four_corners_RADECs2 = get_cornerRADECs(f2) # Get polygon of each image corners poly1 = Polygon(four_corners_RADECs1) poly2 = Polygon(four_corners_RADECs2) # Get intersection polygon poly_intersect = poly1.intersection(poly2) # Get RA DEC of corners of the intersection (overlapping) polygon x_intersect, y2_intersect = poly_intersect.exterior.xy # Get intersection RA and DEC. # Note that the last coordinate is a repeat of the first, so remove it. corner_RADECs_intersect = np.transpose( np.array([x_intersect[0:-1], y2_intersect[0:-1]])) # Do pixel scale checks: are pixels square, are pixel scales of two images similar enough # Exits if input images found to be outside what this is coded for; Prints warnings if in debugmode but not exiting. perform_pixelscaleChecks(w1, w2, verbose=verbose, debugmode=debugmode) # Get XLEN and YLEN- Diff pix scales give diff XLEN, YLEN for same RA,DEC range # Get the average XLEN and YLEN for the two input image pixscales XLEN1, YLEN1 = get_imagesize(corner_RADECs_intersect, w1) XLEN2, YLEN2 = get_imagesize(corner_RADECs_intersect, w2) if verbose: print(f'XLEN1,YLEN1: {XLEN1},{YLEN1}') print(f'XLEN2,YLEN2: {XLEN2},{YLEN2}') #XLEN = int(np.average([XLEN1,XLEN2])) # auto floor #YLEN = int(np.average([YLEN1,YLEN2])) # auto floor XLEN = min([XLEN1, XLEN2]) # Take the smallest YLEN = min([YLEN1, YLEN2]) # Take the smallest # Print information if not quiet mode, or if verbose if not quietmode and not verbose: print(f'-IMAGE_SIZE option in SWarp can be set to: {XLEN},{YLEN}') printme = f'SWarp Command to align two images: swarp {f1} {f2} -SUBTRACT_BACK N -RESAMEPLE Y -COMBINE N -CENTER_TYPE MOST -IMAGE_SIZE {XLEN},{YLEN} -RESAMPLE_DIR ./' print_verbose_string(printme, verbose=verbose) # If plotsave, plot and save. if plotsave: plot_polygonOverlap(poly1, poly2, quietmode=quietmode) return XLEN, YLEN
def test_spectralnorm(): cube = SpectralCube(data, wcs.WCS(h), mask=BooleanArrayMask(mask, wcs=wcs.WCS(h))) noiseobj = noise.Noise(cube) noiseobj.estimate_noise() expected = np.array([ 1.14898322, 0.71345272, 1.21989125]) assert np.allclose(noiseobj.spectral_norm, expected)
def test_spatialnorm(): cube = SpectralCube(data, wcs.WCS(h), mask=BooleanArrayMask(mask, wcs=wcs.WCS(h))) noiseobj = noise.Noise(cube) noiseobj.estimate_noise() print noiseobj.spatial_norm expected = np.array([[ 0.04430196, 0.78314449, 0.07475047, 0.5494684 , 0.05790756], [ 0.32931213, 0.76450342, 1.33944507, 1.06416389, 0.27999452], [ 0.65174339, 0.24128143, 0.27692018, 0.0244925 , 0.11167775], [ 0.60682872, 0.42536813, 0.20018275, 0.78523107, 0.95516435]]) assert np.allclose(noiseobj.spatial_norm, expected)
def mask_file(regionfile, infile, outfile, negate=False): """ Created a masked version of file, using a region. Parameters ---------- regionfile : str A file which can be loaded as a :class:`AegeanTools.regions.Region`. The image will be masked according to this region. infile : str Input FITS image. outfile : str Output FITS image. negate : bool If True then pixels *outside* the region are masked. Default = False. See Also -------- :func:`AegeanTools.MIMAS.mask_plane` """ # Check that the input file is accessible and then open it if not os.path.exists(infile): raise AssertionError("Cannot locate fits file {0}".format(infile)) im = pyfits.open(infile) if not os.path.exists(regionfile): raise AssertionError( "Cannot locate region file {0}".format(regionfile)) region = Region.load(regionfile) try: wcs = pywcs.WCS(im[0].header, naxis=2) except: # TODO: figure out what error is being thrown wcs = pywcs.WCS(str(im[0].header), naxis=2) if len(im[0].data.shape) > 2: data = np.squeeze(im[0].data) else: data = im[0].data print(data.shape) if len(data.shape) == 3: for plane in range(data.shape[0]): mask_plane(data[plane], wcs, region, negate) else: mask_plane(data, wcs, region, negate) im[0].data = data im.writeto(outfile, overwrite=True) logging.info("Wrote {0}".format(outfile)) return
def add_plot(fn: Path, cm, ax, alpha=1): """Astrometry.net makes file ".new" with the image and the WCS SIP 2-D polynomial fit coefficients in the FITS header We use DECL as "x" and RA as "y". pcolormesh() is used as it handles arbitrary pixel shapes. Note that pcolormesh() cannot tolerate NaN in X or Y (NaN in C is OK). This is handled in https://github.com/scivision/pcolormesh_nan.py. """ with fits.open(fn, mode='readonly', memmap=False) as f: img = f[0].data yPix, xPix = f[0].shape[-2:] x, y = np.meshgrid(range(xPix), range(yPix)) # pixel indices to find RA/dec of xy = np.column_stack((x.ravel(order='C'), y.ravel(order='C'))) radec = wcs.WCS(f[0].header).all_pix2world(xy, 0) ra = radec[:, 0].reshape((yPix, xPix), order='C') dec = radec[:, 1].reshape((yPix, xPix), order='C') ax.set_title(fn.name) ax.pcolormesh(ra, dec, img, alpha=alpha, cmap=cm, norm=LogNorm()) ax.set_ylabel('Right Ascension [deg.]') ax.set_xlabel('Declination [deg.]')
def test_header_parse(): from astropy.io import fits with get_pkg_data_fileobj('data/header_newlines.fits', encoding='binary') as test_file: hdulist = fits.open(test_file) w = wcs.WCS(hdulist[0].header) assert w.wcs.ctype[0] == 'RA---TAN-SIP'
def format_coord(x, y): x = int(x + 0.5) y = int(y + 0.5) if x < 0 or y < 0: return " " try: self.img try: hdr = self.hdr mywcs = wcs.WCS(hdr) pixcrd = np.array([[x, y]]) world = mywcs.wcs_pix2world(pixcrd, 1) try: object = self.hdr['object'] except: object = None return "[x,y]=[%4d, %4d] val=%8.5g [%s %s]=[%10.6f,%10.6f] OBJECT: %s" % ( x, y, self.img[y, x], mywcs.wcs.ctype[0], mywcs.wcs.ctype[1], world[0, 0], world[0, 1], object) except: mywcs = None try: return "[x,y]\n [%4i, %4i] val=%8.5g OBJECT: %s" % ( x, y, self.img[y, x], object) except IndexError: return "" except: return " [%4i, %4i]" % (x, y)
def test_sub_segfault(): # Issue #1960 header = fits.Header.fromtextfile( get_pkg_data_filename('data/sub-segfault.hdr')) w = wcs.WCS(header) sub = w.sub([wcs.WCSSUB_CELESTIAL]) gc.collect()
def get_cornerRADECs(f): d,h = fits.getdata(f,header=True) w = wcs.WCS(h) lenx,leny = np.shape(d) four_corners_pixels = [[0,0],[0,lenx-1],[leny-1,lenx-1],[leny-1,0]] four_corners_RADEC = w.all_pix2world(four_corners_pixels,0) return four_corners_RADEC
def build_a_plane_position(plane): from astropy.io import fits from astropy.wcs import wcs from caom2 import SegmentType, Point, Vertex, Position, shape logging.error('do i get here?') try: z = fits.open('/usr/src/app/draogmims2caom2/draogmims2caom2/tests' '/data/gmims_HBN_Fan.fits') w = wcs.WCS(z[0].header) points = [] vertices = [] segment_type = SegmentType['MOVE'] for x, y in ([0, 0], [1, 0], [1, 1], [0, 1]): v = w.all_pix2world(x * z[0].header['naxis1'], y * z[0].header['naxis2'], 1, 1) points.append(Point(float(v[0]), float(v[1]))) vertices.append(Vertex(float(v[0]), float(v[1]), segment_type)) segment_type = SegmentType['LINE'] vertices.append( Vertex(points[0].cval1, points[0].cval2, SegmentType['CLOSE'])) polygon = shape.Polygon(points=points, samples=shape.MultiPolygon(vertices)) position = Position(time_dependent=False, bounds=polygon) plane.position = position except Exception as e: logging.error('wtf {}'.format(e))
def test_iteration(): world = np.array( [[-0.58995335, -0.5], [0.00664326, -0.5], [-0.58995335, -0.25], [0.00664326, -0.25], [-0.58995335, 0.], [0.00664326, 0.], [-0.58995335, 0.25], [0.00664326, 0.25], [-0.58995335, 0.5], [0.00664326, 0.5]], float) w = wcs.WCS() w.wcs.ctype = ['GLON-CAR', 'GLAT-CAR'] w.wcs.cdelt = [-0.006666666828, 0.006666666828] w.wcs.crpix = [75.907, 74.8485] x = w.wcs_world2pix(world, 1) expected = np.array( [[1.64400000e+02, -1.51498185e-01], [7.49105110e+01, -1.51498185e-01], [1.64400000e+02, 3.73485009e+01], [7.49105110e+01, 3.73485009e+01], [1.64400000e+02, 7.48485000e+01], [7.49105110e+01, 7.48485000e+01], [1.64400000e+02, 1.12348499e+02], [7.49105110e+01, 1.12348499e+02], [1.64400000e+02, 1.49848498e+02], [7.49105110e+01, 1.49848498e+02]], float) assert_array_almost_equal(x, expected) w2 = w.wcs_pix2world(x, 1) world[:, 0] %= 360. assert_array_almost_equal(w2, world)
def HDU_to_NDData(hdu): """ Create an N-dimensional dataset from an HDU component. Parameters ---------- hdu : HDU object HDU to transform into an N-dimensional dataset. Returns ------- result: astropy.nddata.NDDataRef with data from the HDU object. """ hdu.verify("fix") data=hdu.data meta=hdu.header mask=np.isnan(data) # Hack to correct wrong uppercased units generated by CASA try: bscale=meta['BSCALE'] except KeyError: bscale=1.0 try: bzero=meta['BZERO'] except KeyError: bzero=0.0 try: bsu=meta['BUNIT'] bsu=bsu.lower() bsu=bsu.replace("jy","Jy") bunit=u.Unit(bsu,format="fits") except KeyError: bunit=u.Unit("u.Jy/u.beam") rem_list=[] for i in meta.items(): if i[0].startswith('PC00'): rem_list.append(i[0]) for e in rem_list: meta.remove(e) mywcs=wcs.WCS(meta) # Create astropy units if len(data.shape) == 4: # Put data in physically-meaninful values, and remove stokes # TODO: Stokes is removed by summing (is this correct? maybe is averaging?) log.info("4D data detected: assuming RA-DEC-FREQ-STOKES (like CASA-generated ones), and dropping STOKES") data=data.sum(axis=0)*bscale+bzero mask = np.logical_and.reduce(mask,axis=0) mywcs=mywcs.dropaxis(3) elif len(data.shape) == 3: log.info("3D data detected: assuming RA-DEC-FREQ") data=data*bscale+bzero elif len(data.shape) == 2: log.info("2D data detected: assuming RA-DEC") data=data*bscale+bzero else: log.error("Only 3D data allowed (or 4D in case of polarization)") raise TypeError return ndd.NDDataRef(data, uncertainty=None, mask=mask,wcs=mywcs, meta=meta, unit=bunit)
def test_unit3(): w = wcs.WCS() for idx in (2, -3): with pytest.raises(IndexError): w.wcs.cunit[idx] with pytest.raises(IndexError): w.wcs.cunit[idx] = u.m with pytest.raises(ValueError): w.wcs.cunit = [u.m, u.m, u.m]
def __init__( self, data=None, spec_axis=None, pyorder=True, hdr=None, wcs=None, casa_cs=None, ): # If we have another cube object, then copy it if isinstance(data, Cube): self.init_from_cube(data) # If we have a string then read a file if type(data) == type("file.fits"): if (data[-4:]).upper() == "FITS": # ... if it ends in FITS call astropy self.from_fits_file(data) else: # ... else call CASA self.from_casa_image(data, transpose=pyorder) # If we have an array, save it if type(data) == type(np.array([1, 1])): self.data = data # Allow the user to force/supply attributes but note that # these may already be set by the file reader. If so, respect # that. if spec_axis != None and self.spec_axis == None: self.spec_axis = spec_axis if hdr != None and self.hdr == None: self.hdr == hdr if wcs != None and self.astropy_wcs == None: self.astropy_wcs == wcs if casa_cs != None and self.casa_cs == None: self.casa_cs == wcs if self.pyorder == None: self.pyorder = pyorder # Some filling-out logic if self.astropy_wcs == None and self.hdr != None: if astropy_ok: self.astropy_wcs = wcs.WCS(self.hdr) if self.spec_axis == None: self.find_spec_axis()
def __init__(self, file_path, build_cdf=True): """Constructor. """ logger.info('Reading FITS image from %s...' % file_path) self.hdu_list = fits.open(file_path) self.hdu_list.info() self.wcs = wcs.WCS(self.hdu_list['PRIMARY'].header) self.data = self.hdu_list['PRIMARY'].data.transpose() self.vmin = None self.vmax = None if build_cdf: self.build_cdf()
def fits2radec( fitsfn: Path, WCSfn: Path = None, solve: bool = False, args: str = None ) -> xarray.Dataset: fitsfn = Path(fitsfn).expanduser() if WCSfn is None: if fitsfn.suffix in (".fits", ".new"): # using .wcs will also work but gives a spurious warning WCSfn = fitsfn.with_suffix(".wcs") elif fitsfn.suffix == ".wcs": WCSfn = fitsfn else: raise ValueError(f"please convert {fitsfn} to GRAYSCALE .fits") if solve: if not doSolve(fitsfn, args): logging.error(f"{fitsfn} was not solved") return None if not WCSfn.is_file(): WCSfn = WCSfn.parent / (WCSfn.stem + "_stack.wcs") if not WCSfn.is_file(): logging.error(f"it appears {fitsfn} was not solved as {WCSfn} is not found") return None with fits.open(fitsfn, mode="readonly") as f: yPix, xPix = f[0].shape[-2:] x, y = meshgrid(range(xPix), range(yPix)) # pixel indices to find RA/dec of xy = column_stack((x.ravel(order="C"), y.ravel(order="C"))) # %% use astropy.wcs to register pixels to RA/DEC """ http://docs.astropy.org/en/stable/api/astropy.wcs.WCS.html#astropy.wcs.WCS naxis=[0,1] is to take x,y axes in case a color photo was input e.g. to astrometry.net cloud solver """ with fits.open(WCSfn, mode="readonly") as f: with warnings.catch_warnings(): warnings.simplefilter("ignore") radec = wcs.WCS(f[0].header).all_pix2world(xy, 0) # radec = wcs.WCS(hdul[0].header,naxis=[0,1]).all_pix2world(xy, 0) ra = radec[:, 0].reshape((yPix, xPix), order="C") dec = radec[:, 1].reshape((yPix, xPix), order="C") # %% collect output radec = xarray.Dataset( {"ra": (("y", "x"), ra), "dec": (("y", "x"), dec)}, {"x": range(xPix), "y": range(yPix)}, attrs={"filename": str(fitsfn)}, ) return radec
def get_wcs(fits_filename): """ Finds and returns the WCS for an image. If Primary Header WCS no good, searches each index until a good one is found. If none found, raises a ValueError """ # Try just opening the initial header wcs_init = wcs.WCS(fits_filename) ra, dec = wcs_init.axis_type_names if ra.upper() == "RA" and dec.upper() == "DEC": return wcs_init else: hdu_list = fits.open(fits_filename) for n in hdu_list: try: wcs_slice = wcs.WCS(n.header) ra, dec = wcs_slice.axis_type_names if ra.upper() == "RA" and dec.upper() == "DEC": return wcs_slice except: continue hdu_list.close() raise ValueError
def test_against_wcslib(inp): w = wcs.WCS() crval = [202.4823228, 47.17511893] w.wcs.crval = crval w.wcs.ctype = ['RA---TAN', 'DEC--TAN'] lonpole = 180 tan = models.Pix2Sky_TAN() n2c = models.RotateNative2Celestial(crval[0], crval[1], lonpole) c2n = models.RotateCelestial2Native(crval[0], crval[1], lonpole) m = tan | n2c minv = c2n | tan.inverse radec = w.wcs_pix2world(inp[0], inp[1], 1) xy = w.wcs_world2pix(radec[0], radec[1], 1) assert_allclose(m(*inp), radec, atol=1e-12) assert_allclose(minv(*radec), xy, atol=1e-12)
def read_fits(fits_filename): """ Function to read the FITS file and store the image array and WCS Inputs: fits_filename: Name of the FITS filename Outputs: wcs_info: WCS of the FITS image image_array: Array of the FITS image """ list_of_hdu = fits.open(fits_filename) # Get the image array image_array = fits.getdata(fits_filename) image_array = image_array[0][0] # Get the WCS of the image wcs_info = wcs.WCS(list_of_hdu[0].header, list_of_hdu).celestial return image_array, wcs_info
def load_fits(filepath): hdulist = fits.open(filepath) hduobject = hdulist[0] hduobject.verify("fix") bscale = 1.0 bunit = units.Unit('u.Jy/u.beam') bzero = 0.0 mask = numpy.isnan(hduobject.data) if 'BSCALE' in hduobject.header: bscale = hduobject.header['BSCALE'] if 'BZERO' in hduobject.header: bzero = hduobject.header['BZERO'] if 'BUNIT' in hduobject.header: unit = hduobject.header['BUNIT'].lower().replace('jy', 'Jy') bunit = units.Unit(unit, format='fits') for item in hduobject.header.items(): if item[0].startswith('PC00'): hduobject.header.remove(item[0]) coordinateSystem = wcs.WCS(hduobject.header) if len(hduobject.data.shape) == 4: log.info( '4D Detected: Assuming RA-DEC-FREQ-STOKES, and dropping STOKES') coordinateSystem = coordinateSystem.dropaxis(3) hduobject.data = hduobject.data.sum(axis=0) * bscale + bzero mask = numpy.logical_and.reduce(mask, axis=0) elif len(hduobject.data.shape) == 3: log.info('3D Detected: Assuming RA-DEC-FREQ') hduobject.data = (hduobject.data * bscale) + bzero elif len(hduobject.data.shape) == 2: log.info('2D Detected: Assuming RA-DEC') hduobject.data = (hduobject.data * bscale) + bzero else: log.error('Only 2-4D data allowed') raise TypeError('Only 2-4D data allowed') hdulist.close() return astropy.nddata.NDDataRef(hduobject.data, uncertainty=None, mask=mask, wcs=coordinateSystem, meta=hduobject.header, unit=bunit)
def fits2radec(fitsfn: Path, solve: bool=False, args: str=None) -> xarray.Dataset: fitsfn = Path(fitsfn).expanduser() if fitsfn.suffix == '.fits': WCSfn = fitsfn.with_suffix('.wcs') # using .wcs will also work but gives a spurious warning elif fitsfn.suffix == '.wcs': WCSfn = fitsfn else: raise ValueError(f'please convert {fitsfn} to GRAYSCALE .fits e.g. with ImageJ or ImageMagick') if solve: doSolve(fitsfn, args) with fits.open(fitsfn, mode='readonly') as f: yPix, xPix = f[0].shape[-2:] x, y = meshgrid(range(xPix), range(yPix)) # pixel indices to find RA/dec of xy = column_stack((x.ravel(order='C'), y.ravel(order='C'))) # %% use astropy.wcs to register pixels to RA/DEC """ http://docs.astropy.org/en/stable/api/astropy.wcs.WCS.html#astropy.wcs.WCS naxis=[0,1] is to take x,y axes in case a color photo was input e.g. to astrometry.net cloud solver """ try: with fits.open(WCSfn, mode='readonly') as f: # radec = wcs.WCS(hdul[0].header,naxis=[0,1]).all_pix2world(xy, 0) radec = wcs.WCS(f[0].header).all_pix2world(xy, 0) except OSError: raise OSError(f'It appears the WCS solution is not present, was the FITS image solved? looking for: {WCSfn}') ra = radec[:, 0].reshape((yPix, xPix), order='C') dec = radec[:, 1].reshape((yPix, xPix), order='C') # %% collect output radec = xarray.Dataset({'ra': (('y', 'x'), ra), 'dec': (('y', 'x'), dec), }, {'x': range(xPix), 'y': range(yPix)}, attrs={'filename': fitsfn}) return radec
def mask2mim(maskfile, mimfile, threshold=1.0, maxdepth=8): """ Use a fits file as a mask to create a region file. Pixels in mask file that are equal or above the threshold will be included in the reigon, while those that are below the threshold will not. Parameters ---------- maskfile : str Input file in fits format. mimfile : str Output filename threshold : float threshold value for separating include/exclude values maxdepth : int Maximum depth (resolution) of the healpix pixels """ hdu = pyfits.open(maskfile) wcs = pywcs.WCS(hdu[0].header) x, y = np.where(hdu[0].data >= threshold) ra, dec = wcs.all_pix2world(y, x, 0) sky = np.radians(Region.radec2sky(ra, dec)) vec = Region.sky2vec(sky) x, y, z = np.transpose(vec) pix = hp.vec2pix(2**maxdepth, x, y, z, nest=True) region = Region(maxdepth=maxdepth) region.add_pixels(pix, depth=maxdepth) region._renorm() save_region(region, mimfile) logging.info("Converted {0} -> {1}".format(maskfile, mimfile)) return
def from_fits_file(self, filename=None, skipdata=False, skipvalid=False, skiphdr=False): """ Read in a cube from a FITS file using astropy. """ # Require astropy to be loaded. if astropy_ok == False: print "Cannot read FITS files without astropy." return # ... record the filename self.filename = filename # ... open the file hdulist = fits.open(filename) # ... read the data - assume first extension if skipdata == False: self.data = hdulist[0].data # ... note where data is valid if skipvalid == False: self.valid = np.isfinite(self.data) # ... astropy always reads in pyorder self.pyorder = True # ... note the header and WCS information if skiphdr == False: self.astropy_wcs = wcs.WCS(hdulist[0].header) self.hdr = hdulist[0].header # ... figure out the spectral axis self.find_spec_axis()
def test_scalegen(): cube = SpectralCube(data, wcs.WCS(h), mask=BooleanArrayMask(mask, wcs=wcs.WCS(h))) noiseobj = noise.Noise(cube) assert np.isclose(noiseobj.scale, 1.1382529312849043)
def plot_fits_map(data, header, stretch='auto', exponent=2, scaleFrac=0.9, cmapName='gist_heat', zMin=None, zMax=None, annEllipseLst=[], annPolyLst=[], bunit=None, lw=1.0, interpolation='Nearest', fig=None, dpi=100, doColbar=True): """ Plot a colourscale image of a FITS map. annEllipseLst is a list of lists: annEllipseLst[0][i] = x_deg annEllipseLst[1][i] = y_deg annEllipseLst[2][i] = minor_deg annEllipseLst[3][i] = major_deg annEllipseLst[4][i] = pa_deg annEllipseLst[5][i] = colour ... optional, default to 'g' annPolyLst is also a list of lists: annPolyLst[0][i] = list of polygon coords = [[x1,y1], [x2, y2] ...] annPolyLst[1][i] = colour of polygon e.g., 'w' """ # Strip unused dimensions from the array data, header = strip_fits_dims(data, header, 2, 5) # Parse the WCS information w = mkWCSDict(header) wcs = pw.WCS(w['header2D']) # Calculate the image vmin and vmax by measuring the range in the inner # 'scale_frac' of the image s = data.shape boxMaxX = int(s[-1] / 2.0 + s[-1] * scaleFrac / 2.0 + 1.0) boxMinX = int(s[-1] / 2.0 - s[-1] * scaleFrac / 2.0 + 1.0) boxMaxY = int(s[-2] / 2.0 + s[-2] * scaleFrac / 2.0 + 1.0) boxMinY = int(s[-2] / 2.0 - s[-2] * scaleFrac / 2.0 + 1.0) dataSample = data[boxMinY:boxMaxY, boxMinX:boxMaxX] measures = calc_stats(dataSample) sigma = abs(measures['max'] / measures['madfm']) if stretch == 'auto': if sigma <= 20: vMin = measures['madfm'] * (-1.5) vMax = measures['madfm'] * 10.0 stretch = 'linear' elif sigma > 20: vMin = measures['madfm'] * (-3.0) vMax = measures['madfm'] * 40.0 stretch = 'linear' elif sigma > 500: vMin = measures['madfm'] * (-7.0) vMax = measures['madfm'] * 200.0 stretch = 'sqrt' if not zMax is None: vMax = max(zMax, measures['max']) if not zMax is None: vMin = zMin # Set the colourscale using an normalizer object normalizer = APLpyNormalize(stretch=stretch, exponent=exponent, vmin=vMin, vmax=vMax) # Setup the figure if fig is None: fig = plt.figure(facecolor='w', figsize=(9.5, 8)) ax = fig.add_axes([0.1, 0.08, 0.9, 0.87]) if w['coord_type'] == 'EQU': ax.set_xlabel('Right Ascension') ax.set_ylabel('Declination') elif w['coord_type'] == 'GAL': ax.set_xlabel('Galactic Longitude (deg)') ax.set_ylabel('Galactic Latitude (deg)') else: ax.set_xlabel('Unknown') ax.set_ylabel('Unknown') cosY = m.cos(m.radians(w['ycent'])) aspect = abs(w['ydelt'] / (w['xdelt'] * cosY)) # Set the format of the major tick mark and labels if w['coord_type'] == 'EQU': f = 15.0 majorFormatterX = FuncFormatter(label_format_hms) minorFormatterX = None majorFormatterY = FuncFormatter(label_format_dms) minorFormattery = None else: f = 1.0 majorFormatterX = FuncFormatter(label_format_deg) minorFormatterX = None majorFormatterY = FuncFormatter(label_format_deg) minorFormattery = None ax.xaxis.set_major_formatter(majorFormatterX) ax.yaxis.set_major_formatter(majorFormatterY) # Set the location of the the major tick marks #xrangeArcmin = abs(w['xmax']-w['xmin'])*(60.0*f) #xmultiple = m.ceil(xrangeArcmin/3.0)/(60.0*f) #yrangeArcmin = abs(w['ymax']-w['ymin'])*60.0 #ymultiple = m.ceil(yrangeArcmin/3.0)/60.0 #majorLocatorX = MultipleLocator(xmultiple) #ax.xaxis.set_major_locator(majorLocatorX) #majorLocatorY = MultipleLocator(ymultiple) #ax.yaxis.set_major_locator(majorLocatorY) ax.xaxis.set_major_locator(MaxNLocator(5)) ax.yaxis.set_major_locator(MaxNLocator(5)) # Print the image to the axis im = ax.imshow(data, interpolation=interpolation, origin='lower', aspect=aspect, extent=[w['xmax'], w['xmin'], w['ymin'], w['ymax']], cmap=plt.get_cmap(cmapName), norm=normalizer) # Add the colorbar if doColbar: cbar = fig.colorbar(im, pad=0.0) if 'BUNIT' in header: cbar.set_label(header['BUNIT']) else: cbar.set_label('Unknown') if not bunit is None: cbar.set_label(bunit) # Format the colourbar labels - TODO # Set white ticks ax.tick_params(pad=5) for line in ax.xaxis.get_ticklines() + ax.get_yticklines(): line.set_markeredgewidth(1) line.set_color('w') # Create the ellipse source annotations if len(annEllipseLst) > 0: if len(annEllipseLst) >= 5: srcXLst = np.array(annEllipseLst[0]) srcYLst = np.array(annEllipseLst[1]) srcMinLst = np.array(annEllipseLst[2]) srcMajLst = np.array(annEllipseLst[3]) srcPALst = np.array(annEllipseLst[4]) if len(annEllipseLst) >= 6: if type(annEllipseLst[5]) is str: srcEColLst = [annEllipseLst[5]] * len(srcXLst) elif type(annEllipseLst[5]) is list: srcEColLst = annEllipseLst[5] else: rcEColLst = ['g'] * len(srcXLst) else: srcEColLst = ['g'] * len(srcXLst) for i in range(len(srcXLst)): try: el = Ellipse((srcXLst[i], srcYLst[i]), srcMinLst[i], srcMajLst[i], angle=180.0 - srcPALst[i], edgecolor=srcEColLst[i], linewidth=lw, facecolor='none') ax.add_artist(el) except Exception: pass # Create the polygon source annotations if len(annPolyLst) > 0: annPolyCoordLst = annPolyLst[0] if len(annPolyLst) > 1: if type(annPolyLst[1]) is str: annPolyColorLst = [annPolyLst[1]] * len(annPolyCoordLst) elif type(annPolyLst[1]) is list: annPolyColorLst = annPolyLst[1] else: annPolyColorLst = ['g'] * len(annPolyCoordLst) else: annPolyColorLst = ['g'] * len(annPolyCoordLst) for i in range(len(annPolyCoordLst)): cpoly = Polygon(annPolyCoordLst[i], animated=False, linewidth=lw) cpoly.set_edgecolor(annPolyColorLst[i]) cpoly.set_facecolor('none') ax.add_patch(cpoly) return fig
starnames = a['name'].data radecstrs = [] for k in range(len(a)): cstr = '{}h{}m{}s {}d{}m{}s'.format(a['rah'][k], a['ram'][k], a['ras'][k], a['decd'][k], a['decm'][k], a['decs'][k]) radecstrs.append(cstr) print(starnames) print(radecstrs) # get the large fits file and wcs info filename = 'F475W_mosaic.fits.gz' cband = 'F475W' hdulist = fits.open(filename) image_wcs = wcs.WCS(hdulist[0].header) image = hdulist[0].data # size to extract in (ra, dec) arcsec size = (10., 10.) for k, cradec in enumerate(radecstrs): pimage = get_postage_stamp(cradec, size, image, image_wcs) if pimage is not None: print(pimage.wcs) ohdu = fits.PrimaryHDU(pimage.data, header=pimage.wcs.to_header()) ohdul = fits.HDUList([ohdu]) ohdul.writeto('%s_%s_pstamp.fits' % (starnames[k], cband), overwrite=True)
def test_unit2(): w = wcs.WCS() myunit = u.Unit("FOOBAR", parse_strict="warn") w.wcs.cunit[0] = myunit
def test_unit(): w = wcs.WCS() w.wcs.cunit[0] = u.erg assert w.wcs.cunit[0] == u.erg assert repr(w.wcs.cunit) == "['erg', '']"
if phot_band == "radio": sep_pattern = [400, 400] corner_coord = cent_coord.directional_offset_by( pa_pattern * u.deg, sep_pattern * u.arcsec) else: sep_pattern = [300, 300] corner_coord = cent_coord.directional_offset_by( pa_pattern * u.deg, sep_pattern * u.arcsec) # Name the section based on Source_Name and phot_band crop_img_name = BASE_OUT + "/" + prefilt_out["Source_Name"][ ii] + "_" + phot_band + ".fits" img_to_crop = img_dict[phot_band] if not os.path.exists(crop_img_name): hdul = fits.open(img_to_crop) img_wcs = wcs.WCS(hdul[0].header, hdul).celestial print(crop_img_name) xc, yc = img_wcs.all_world2pix(corner_coord.ra, corner_coord.dec, 0) xc = np.sort(xc) yc = np.sort(yc) xr = slice(int(np.round(xc[0])), int(np.floor(xc[1]))) yr = slice(int(np.round(yc[0])), int(np.floor(yc[1]))) if phot_band != "radio": crop_write_fits(hdul, img_wcs, hdul[0].data, xr, yr, crop_img_name) else:
def match_crop_fits(filename_indx): """ Use the funtions defined previously to find the overlapping region between two images and crop both the images to the overlapping image. This assumes that the WCS information in the FITS header is accurate. Parameters: ----------- filename_indx : The index into the list of filenames to select the file that needs to be processed """ wht_img = wht_list[filename_indx] coadd_img = coadd_list[filename_indx] print("Matching " + coadd_img) # Open wht image and store image data and WCS information wht_hdu = fits.open(wht_img) wht_wcs = wcs.WCS(wht_hdu[wcs_hext].header, wht_hdu).celestial wht_data = wht_hdu[img_hext].data # Open the image and store image data and WCS information coadd_hdu = fits.open(coadd_img) coadd_wcs = wcs.WCS(coadd_hdu[wcs_hext].header, coadd_hdu).celestial coadd_data = coadd_hdu[img_hext].data img_c_ra, img_c_dec = world_extent(coadd_wcs, coadd_hdu[wcs_hext].header) wht_c_ra, wht_c_dec = world_extent(wht_wcs, wht_hdu[wcs_hext].header) # Compute the corners of the ectangle that define the # overlapping region from the images ov_ra = np.zeros(4) ov_dec = np.zeros(4) # The left corners ov_ra[0:2] = np.min([img_c_ra[0:2], wht_c_ra[0:2]], axis=0) ov_dec[0:2] = np.max([img_c_dec[0:2], wht_c_dec[0:2]], axis=0) ov_ra[2:] = np.max([img_c_ra[2:], wht_c_ra[2:]], axis=0) ov_dec[2:] = np.min([img_c_dec[2:], wht_c_dec[2:]], axis=0) # Compute the pixel (x,y) coordinates at these overlapping # world coordinates img_ovx, img_ovy = coadd_wcs.all_world2pix(ov_ra, ov_dec, 1) wht_ovx, wht_ovy = wht_wcs.all_world2pix(ov_ra, ov_dec, 1) # Define the range of the x and y-axis of overlapping region # and check that they are of the same size wht_xr = np.round(np.array([wht_ovx[1], wht_ovx[2]])).astype(int) img_xr = np.round(np.array([img_ovx[1], img_ovx[2]])).astype(int) wht_yr = np.round(np.array([wht_ovy[0], wht_ovy[2]])).astype(int) img_yr = np.round(np.array([img_ovy[0], img_ovy[2]])).astype(int) # Now check that the area of the overlapping images # will be the same check_imsize(wht_xr, wht_yr, img_xr, img_yr) # Write the cropped, overlapping images to file crop_write_fits(coadd_hdu, coadd_wcs, coadd_data, img_xr, img_yr, coadd_outlist[filename_indx]) crop_write_fits(wht_hdu, wht_wcs, wht_data, wht_xr, wht_yr, wht_outlist[filename_indx]) return