def fit_island_iteratively(self, img, isl, iter_ngmax=5, opts=None): """Fits an island iteratively. For large islands, which can require many Gaussians to fit well, it is much faster to fit a small number of Gaussians simultaneously and iterate. However, this does usually result in larger residuals. """ import functions as func sgaul = []; sfgaul = [] gaul = []; fgaul = [] if opts == None: opts = img.opts thresh_isl = opts.thresh_isl thresh_pix = opts.thresh_pix thresh = opts.fittedimage_clip thr = isl.mean + thresh_isl * isl.rms rms = isl.rms if opts.verbose_fitting: print 'Iteratively fitting island ', isl.island_id gaul = []; fgaul = [] ffimg_tot = N.zeros(isl.shape, dtype=N.float32) peak_val = N.max(isl.image - isl.islmean) while peak_val >= thr: sgaul, sfgaul = self.fit_island(isl, opts, img, ffimg=ffimg_tot, ngmax=iter_ngmax, ini_gausfit='simple') gaul = gaul + sgaul; fgaul = fgaul + sfgaul # Calculate residual image if len(sgaul) > 0: for g in sgaul: gcopy = g[:] gcopy[1] -= isl.origin[0] gcopy[2] -= isl.origin[1] S1, S2, Th = func.corrected_size(gcopy[3:6]) gcopy[3] = S1 gcopy[4] = S2 gcopy[5] = Th A, C1, C2, S1, S2, Th = gcopy shape = isl.shape b = find_bbox(thresh*isl.rms, gcopy) bbox = N.s_[max(0, int(C1-b)):min(shape[0], int(C1+b+1)), max(0, int(C2-b)):min(shape[1], int(C2+b+1))] x_ax, y_ax = N.mgrid[bbox] ffimg = func.gaussian_fcn(gcopy, x_ax, y_ax) ffimg_tot[bbox] += ffimg peak_val_prev = peak_val peak_val = N.max(isl.image - isl.islmean - ffimg_tot) if func.approx_equal(peak_val, peak_val_prev): break else: break if len(gaul) == 0: # Fitting iteratively did not work -- try normal fit gaul, fgaul = self.fit_island(isl, opts, img, ini_gausfit='default') return gaul, fgaul
def __init__(self, img, gaussian, isl_idx, g_idx, flag=0): """Initialize Gaussian object from fitting data Parameters: img: PyBDSM image object gaussian: 6-tuple of fitted numbers isl_idx: island serial number g_idx: gaussian serial number flag: flagging (if any) """ import functions as func from const import fwsig import numpy as N use_wcs = True self.gaussian_idx = g_idx self.gaus_num = 0 # stored later self.island_id = isl_idx self.jlevel = img.j self.flag = flag self.parameters = gaussian p = gaussian self.peak_flux = p[0] self.centre_pix = p[1:3] size = p[3:6] if func.approx_equal(size[0], img.pixel_beam()[0]*1.1) and \ func.approx_equal(size[1], img.pixel_beam()[1]) and \ func.approx_equal(size[2], img.pixel_beam()[2]+90.0) or \ img.opts.fix_to_beam: # Check whether fitted Gaussian is just the distorted pixel beam # given as an initial guess or if size was fixed to the beam. If so, # reset the size to the undistorted beam. # Note: these are sigma sizes, not FWHM sizes. size = img.pixel_beam() size = (size[0], size[1], size[2]+90.0) # adjust angle so that corrected_size() works correctly size = func.corrected_size(size) # gives fwhm and P.A. self.size_pix = size # FWHM in pixels and P.A. CCW from +y axis # Use img.orig_beam for flux calculation and deconvolution on wavelet # images, as img.beam has been altered to match the wavelet scale. # Note: these are all FWHM sizes. if img.waveletimage: bm_pix = N.array(img.beam2pix(img.orig_beam)) else: bm_pix = N.array(img.beam2pix(img.beam)) # Calculate fluxes, sky sizes, etc. All sizes are FWHM. tot = p[0]*size[0]*size[1]/(bm_pix[0]*bm_pix[1]) if flag == 0: # These are good Gaussians errors = func.get_errors(img, p+[tot], img.islands[isl_idx].rms) self.centre_sky = img.pix2sky(p[1:3]) self.centre_skyE = img.pix2coord(errors[1:3], self.centre_pix, use_wcs=use_wcs) self.size_sky = img.pix2gaus(size, self.centre_pix, use_wcs=use_wcs) # FWHM in degrees and P.A. east from north self.size_sky_uncorr = img.pix2gaus(size, self.centre_pix, use_wcs=False) # FWHM in degrees and P.A. east from +y axis self.size_skyE = img.pix2gaus(errors[3:6], self.centre_pix, use_wcs=use_wcs) self.size_skyE_uncorr = img.pix2gaus(errors[3:6], self.centre_pix, use_wcs=False) gaus_dc, err = func.deconv2(bm_pix, size) self.deconv_size_sky = img.pix2gaus(gaus_dc, self.centre_pix, use_wcs=use_wcs) self.deconv_size_sky_uncorr = img.pix2gaus(gaus_dc, self.centre_pix, use_wcs=False) self.deconv_size_skyE = img.pix2gaus(errors[3:6], self.centre_pix, use_wcs=use_wcs) self.deconv_size_skyE_uncorr = img.pix2gaus(errors[3:6], self.centre_pix, use_wcs=False) else: # These are flagged Gaussians, so don't calculate sky values or errors errors = [0]*7 self.centre_sky = [0., 0.] self.centre_skyE = [0., 0.] self.size_sky = [0., 0., 0.] self.size_sky_uncorr = [0., 0., 0.] self.size_skyE = [0., 0.] self.size_skyE_uncorr = [0., 0., 0.] self.deconv_size_sky = [0., 0., 0.] self.deconv_size_sky_uncorr = [0., 0., 0.] self.deconv_size_skyE = [0., 0., 0.] self.deconv_size_skyE_uncorr = [0., 0., 0.] self.total_flux = tot self.total_fluxE = errors[6] self.peak_fluxE = errors[0] self.total_fluxE = errors[6] self.centre_pixE = errors[1:3] self.size_pixE = errors[3:6] self.rms = img.islands[isl_idx].rms self.mean = img.islands[isl_idx].mean self.total_flux_isl = img.islands[isl_idx].total_flux self.total_flux_islE = img.islands[isl_idx].total_fluxE