def is_guide_ota(img, ota): """ Determines whether the specified image OTA was used for guiding. Parameters ---------- img : str Name of image being processed ota : str Name of current ``ota`` being processed in ``img`` Returns ------- guide : boolean True if guide OTA, False if not """ from astropy.io import fits from photutils.segmentation import detect_sources, source_properties, properties_table guide = False check_ota = 'illcor_'+ota+'.'+img.stem() hdu = fits.open(check_ota) data = hdu[0].data segm = detect_sources(data, 1.0, 50000) props = source_properties(data, segm) corners = [] for p in props: cutout = p.data_cutout yc, xc = int(p.cutout_centroid[0].value), int(p.cutout_centroid[1].value) bgcent = cutout[yc,xc] bgcorn = np.array([cutout[0,0], cutout[0,-1], cutout[-1,0], cutout[-1,-1]]) bgrat = bgcorn/bgcent corners.append(np.median(bgrat)) med_ratio = np.median(corners) print med_ratio if med_ratio > 3.: guide = True return guide
def find_skycomponents(im: Image, fwhm=1.0, threshold=10.0, npixels=5): """ Find gaussian components in Image above a certain threshold as Skycomponent :param fwhm: Full width half maximum of gaussian :param threshold: Threshold for component detection. Default: 10 standard deviations over median. :param im: Image to be searched :param params: :returns: list of sky components """ assert type(im) == Image log.info("find_skycomponents: Finding components in Image by segmentation") # We use photutils segmentation - this first segments the image # into pieces that are thought to contain individual sources, then # identifies the concrete source properties. Having these two # steps makes it straightforward to extract polarisation and # spectral information. # Make filter kernel sigma = fwhm * gaussian_fwhm_to_sigma kernel = Gaussian2DKernel(sigma, x_size=int(1.5 * fwhm), y_size=int(1.5 * fwhm)) kernel.normalize() # Segment the sum of the entire image cube image_sum = numpy.sum(im.data, axis=(0, 1)) segments = segmentation.detect_sources(image_sum, threshold, npixels=npixels, filter_kernel=kernel) log.info("find_skycomponents: Identified %d segments" % segments.nlabels) # Now get source properties for all polarisations and frequencies comp_tbl = [[ segmentation.source_properties(im.data[chan, pol], segments, filter_kernel=kernel, wcs=im.wcs) for pol in range(im.npol) ] for chan in range(im.nchan)] def comp_prop(comp, prop_name): return [[ comp_tbl[chan][pol][comp][prop_name] for pol in range(im.npol) ] for chan in range(im.nchan)] # Generate components comps = [] for segment in range(segments.nlabels): # Get flux and position. Astropy's quantities make this # unecesarily complicated. flux = numpy.array(comp_prop(segment, "max_value")) # These values seem inconsistent with the xcentroid, and ycentroid values # ras = u.Quantity(list(map(u.Quantity, # comp_prop(segment, "ra_icrs_centroid")))) # decs = u.Quantity(list(map(u.Quantity, # comp_prop(segment, "dec_icrs_centroid")))) xs = u.Quantity(list(map(u.Quantity, comp_prop(segment, "xcentroid")))) ys = u.Quantity(list(map(u.Quantity, comp_prop(segment, "ycentroid")))) sc = pixel_to_skycoord(xs, ys, im.wcs, 1) ras = sc.ra decs = sc.dec # Remove NaNs from RA/DEC (happens if there is no flux in that # polarsiation/channel) # ras[numpy.isnan(ras)] = 0.0 # decs[numpy.isnan(decs)] = 0.0 # Determine "true" position by weighting flux_sum = numpy.sum(flux) ra = numpy.sum(flux * ras) / flux_sum dec = numpy.sum(flux * decs) / flux_sum xs = numpy.sum(flux * xs) / flux_sum ys = numpy.sum(flux * ys) / flux_sum # Add component comps.append( Skycomponent( direction=SkyCoord(ra=ra, dec=dec), frequency=im.frequency, name="Segment %d" % segment, flux=flux, shape='Point', polarisation_frame=im.polarisation_frame, params={ 'xpixel': xs, 'ypixel': ys } # Table has lots of data, could add more in future )) return comps
def find_skycomponents(im: Image, fwhm=1.0, threshold=1.0, npixels=5) -> List[Skycomponent]: """ Find gaussian components in Image above a certain threshold as Skycomponent :param im: Image to be searched :param fwhm: Full width half maximum of gaussian in pixels :param threshold: Threshold for component detection. Default: 1 Jy. :param npixels: Number of connected pixels required :return: list of sky components """ assert isinstance(im, Image) log.info("find_skycomponents: Finding components in Image by segmentation") # We use photutils segmentation - this first segments the image # into pieces that are thought to contain individual sources, then # identifies the concrete source properties. Having these two # steps makes it straightforward to extract polarisation and # spectral information. # Make filter kernel sigma = fwhm * gaussian_fwhm_to_sigma kernel = Gaussian2DKernel(sigma, x_size=int(1.5 * fwhm), y_size=int(1.5 * fwhm)) kernel.normalize() # Segment the average over all channels of Stokes I image_sum = numpy.sum(im.data, axis=0)[0, ...] / float(im.shape[0]) segments = segmentation.detect_sources(image_sum, threshold, npixels=npixels, filter_kernel=kernel) assert segments is not None, "Failed to find any components" log.info("find_skycomponents: Identified %d segments" % segments.nlabels) # Now compute source properties for all polarisations and frequencies comp_tbl = [[ segmentation.source_properties(im.data[chan, pol], segments, filter_kernel=kernel, wcs=im.wcs.sub([1, 2])).to_table() for pol in [0] ] for chan in range(im.nchan)] def comp_prop(comp, prop_name): return [[comp_tbl[chan][pol][comp][prop_name] for pol in [0]] for chan in range(im.nchan)] # Generate components comps = [] for segment in range(segments.nlabels): # Get flux and position. Astropy's quantities make this # unnecessarily complicated. flux = numpy.array(comp_prop(segment, "max_value")) # These values seem inconsistent with the xcentroid, and ycentroid values # ras = u.Quantity(list(map(u.Quantity, # comp_prop(segment, "ra_icrs_centroid")))) # decs = u.Quantity(list(map(u.Quantity, # comp_prop(segment, "dec_icrs_centroid")))) xs = u.Quantity(list(map(u.Quantity, comp_prop(segment, "xcentroid")))) ys = u.Quantity(list(map(u.Quantity, comp_prop(segment, "ycentroid")))) sc = pixel_to_skycoord(xs, ys, im.wcs, 0) ras = sc.ra decs = sc.dec # Remove NaNs from RA/DEC (happens if there is no flux in that # polarsiation/channel) # ras[numpy.isnan(ras)] = 0.0 # decs[numpy.isnan(decs)] = 0.0 # Determine "true" position by weighting flux_sum = numpy.sum(flux) ra = numpy.sum(flux * ras) / flux_sum dec = numpy.sum(flux * decs) / flux_sum xs = numpy.sum(flux * xs) / flux_sum ys = numpy.sum(flux * ys) / flux_sum point_flux = im.data[:, :, numpy.round(ys.value).astype('int'), numpy.round(xs.value).astype('int')] # Add component comps.append( Skycomponent(direction=SkyCoord(ra=ra, dec=dec), frequency=im.frequency, name="Segment %d" % segment, flux=point_flux, shape='Point', polarisation_frame=im.polarisation_frame, params={})) return comps
numpy.mean(data), numpy.mean(data**2))) image = data.reshape((width, width)) # Detect sources, if requested if args.threshold > 0: from astropy.convolution import Gaussian2DKernel, Box2DKernel from astropy.stats import gaussian_fwhm_to_sigma import astropy.units as u from photutils import segmentation kernel = Gaussian2DKernel(args.fwhm * gaussian_fwhm_to_sigma, x_size=int(1.5*args.fwhm), y_size=int(1.5*args.fwhm)) kernel.normalize() segments = segmentation.detect_sources(image, args.threshold, npixels=args.npixels, filter_kernel=kernel) print("Have %d segments:" % (segments.nlabels)) props = segmentation.source_properties(image, segments, filter_kernel=kernel) for segment in props: print("l=%+.6f m=%+.6f intensity=%.f" % (segment.xcentroid.value / width * args.theta - args.theta/2, segment.ycentroid.value / width * args.theta - args.theta/2, segment.max_value)) # Visualise import matplotlib matplotlib.use(args.backend) project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(project_root) from util.visualize import show_image show_image(image, args.input, args.theta, norm=args.norm)