def fit_channels(self, img, chan_images, clip_rms, src, beamlist):
        """Fits normalizations of Gaussians in source to multiple channels

        If unresolved, the size of the Gaussians are adjusted to match the
        channel's beam size (given by beamlist) before fitting.

        Returns array of total fluxes (N_channels x N_Gaussians) and array
        of errors (N_channels x N_Gaussians).
        """
        import functions as func
        from const import fwsig

        isl = img.islands[src.island_id]
        isl_bbox = isl.bbox
        nchan = chan_images.shape[0]
        x, y = N.mgrid[isl_bbox]
        gg = src.gaussians
        fitfix = N.ones(len(gg))  # fit only normalization
        srcmask = isl.mask_active

        total_flux = N.zeros(
            (nchan, len(fitfix)))  # array of fluxes: N_channels x N_Gaussians
        errors = N.zeros(
            (nchan, len(fitfix)))  # array of fluxes: N_channels x N_Gaussians
        for cind in range(nchan):
            image = chan_images[cind]
            gg_adj = self.adjust_size_by_freq(img.beam, beamlist[cind], gg)
            p, ep = func.fit_mulgaus2d(image,
                                       gg_adj,
                                       x,
                                       y,
                                       srcmask,
                                       fitfix,
                                       adj=True)
            pbeam = img.beam2pix(beamlist[cind])
            bm_pix = (pbeam[0] / fwsig, pbeam[1] / fwsig, pbeam[2]
                      )  # IN SIGMA UNITS
            for ig in range(len(fitfix)):
                total_flux[cind,
                           ig] = p[ig * 6] * p[ig * 6 + 3] * p[ig * 6 + 4] / (
                               bm_pix[0] * bm_pix[1])
            p = N.insert(p, N.arange(len(fitfix)) * 6 + 6, total_flux[cind])
            rms_isl = N.mean(clip_rms[cind])
            errors[cind] = func.get_errors(img,
                                           p,
                                           rms_isl,
                                           bm_pix=(bm_pix[0] * fwsig,
                                                   bm_pix[1] * fwsig,
                                                   bm_pix[2]))[6]
            self.reset_size(gg)

        return total_flux, errors
Example #2
0
    def fit_channels(self, img, chan_images, clip_rms, src, beamlist):
        """Fits normalizations of Gaussians in source to multiple channels

        If unresolved, the size of the Gaussians are adjusted to match the
        channel's beam size (given by beamlist) before fitting.

        Returns array of total fluxes (N_channels x N_Gaussians) and array
        of errors (N_channels x N_Gaussians).
        """
        import functions as func
        from const import fwsig

        isl = img.islands[src.island_id]
        isl_bbox = isl.bbox
        nchan = chan_images.shape[0]
        x, y = N.mgrid[isl_bbox]
        gg = src.gaussians
        fitfix = N.ones(len(gg)) # fit only normalization
        srcmask = isl.mask_active

        total_flux = N.zeros((nchan, len(fitfix))) # array of fluxes: N_channels x N_Gaussians
        errors = N.zeros((nchan, len(fitfix))) # array of fluxes: N_channels x N_Gaussians
        for cind in range(nchan):
            image = chan_images[cind]
            gg_adj = self.adjust_size_by_freq(img.beam, beamlist[cind], gg)
            p, ep = func.fit_mulgaus2d(image, gg_adj, x, y, srcmask, fitfix, adj=True)
            pbeam = img.beam2pix(beamlist[cind])
            bm_pix = (pbeam[0]/fwsig, pbeam[1]/fwsig, pbeam[2])  # IN SIGMA UNITS
            for ig in range(len(fitfix)):
                total_flux[cind, ig] = p[ig*6]*p[ig*6+3]*p[ig*6+4]/(bm_pix[0]*bm_pix[1])
            p = N.insert(p, N.arange(len(fitfix))*6+6, total_flux[cind])
            rms_isl = N.mean(clip_rms[cind])
            errors[cind] = func.get_errors(img, p, rms_isl, bm_pix=(bm_pix[0]*fwsig, bm_pix[1]*fwsig, bm_pix[2]))[6]
            self.reset_size(gg)

        return total_flux, errors
Example #3
0
    def __call__(self, img):
        mylog = mylogger.logging.getLogger("PyBDSM." + img.log + "Polarisatn")
        if img.opts.polarisation_do:
            mylog.info('Extracting polarisation properties for all sources')
            pols = ['I', 'Q', 'U', 'V']

            # Run gausfit and gual2srl on PI image to look for polarized sources
            # undetected in I
            fit_PI = img.opts.pi_fit
            n_new = 0
            ch0_pi = N.sqrt(img.ch0_Q_arr**2 + img.ch0_U_arr**2)
            img.ch0_pi_arr = ch0_pi

            if fit_PI:
                from . import _run_op_list
                mylogger.userinfo(mylog, "\nChecking PI image for new sources")

                mask = img.mask_arr
                minsize = img.opts.minpix_isl

                # Set up image object for PI image.
                pi_chain, pi_opts = self.setpara_bdsm(img)
                pimg = Image(pi_opts)
                pimg.beam = img.beam
                pimg.pixel_beam = img.pixel_beam
                pimg.pixel_beamarea = img.pixel_beamarea
                pimg.log = 'PI.'
                pimg.pix2beam = img.pix2beam
                pimg.beam2pix = img.beam2pix
                pimg.pix2gaus = img.pix2gaus
                pimg.gaus2pix = img.gaus2pix
                pimg.pix2sky = img.pix2sky
                pimg.sky2pix = img.sky2pix
                pimg.pix2coord = img.pix2coord
                pimg.wcs_obj = img.wcs_obj
                pimg.mask_arr = mask
                pimg.masked = img.masked
                pimg.ch0_arr = ch0_pi
                pimg._pi = True

                success = _run_op_list(pimg, pi_chain)
                if not success:
                    return

                img.pi_islands = pimg.islands
                img.pi_gaussians = pimg.gaussians
                img.pi_sources = pimg.sources

                # Now check for new sources in the PI image that are not
                # found in the Stokes I image. If any new sources are found,
                # adjust their IDs to follow after those found in I.
                new_isl = []
                new_src = []
                new_gaus = []
                n_new_src = 0
                isl_id = img.islands[-1].island_id
                src_id = img.sources[-1].source_id
                gaus_id = img.gaussians[-1].gaus_num
                for pi_isl in pimg.islands:
                    new_sources = []
                    for pi_src in pi_isl.sources:
                        if img.pyrank[int(img.sky2pix(pi_src.posn_sky_max)[0]),
                                      int(img.sky2pix(pi_src.posn_sky_max)[1]
                                          )] == -1:
                            src_id += 1
                            pi_src._pi = True
                            pi_src.island_id = isl_id
                            pi_src.source_id = src_id
                            pi_src.spec_indx = N.NaN
                            pi_src.e_spec_indx = N.NaN
                            pi_src.spec_norm = N.NaN
                            pi_src.specin_flux = [N.NaN]
                            pi_src.specin_fluxE = [N.NaN]
                            pi_src.specin_freq = [N.NaN]
                            pi_src.specin_freq0 = N.NaN
                            new_sources.append(pi_src)
                            new_src.append(pi_src)
                            n_new_src += 1
                            for g in pi_src.gaussians:
                                gaus_id += 1
                                new_gaus.append(g)
                                g.gaus_num = gaus_id
                    if len(new_sources) > 0:
                        isl_id += 1
                        pi_isl.sources = new_sources
                        pi_isl.island_id = isl_id
                        pi_isl._pi = True
                        new_isl.append(pi_isl)

                n_new = len(new_isl)
                mylogger.userinfo(mylog, "New sources found in PI image",
                                  '%i (%i total)' % (n_new, img.nsrc + n_new))

            if n_new > 0:
                img.islands += new_isl
                img.sources += new_src
                img.gaussians += new_gaus
                img.nsrc += n_new_src

            bar = statusbar.StatusBar(
                'Calculating polarisation properties ....  : ', 0, img.nsrc)
            if img.opts.quiet == False:
                bar.start()

            for isl in img.islands:
                isl_bbox = isl.bbox
                ch0_I = img.ch0_arr[isl_bbox]
                ch0_Q = img.ch0_Q_arr[isl_bbox]
                ch0_U = img.ch0_U_arr[isl_bbox]
                ch0_V = img.ch0_V_arr[isl_bbox]
                ch0_images = [ch0_I, ch0_Q, ch0_U, ch0_V]

                for i, src in enumerate(isl.sources):
                    # For each source, assume the morphology does not change
                    # across the Stokes cube. This assumption allows us to fit
                    # the Gaussians of each source to each Stokes image by
                    # simply fitting only the overall normalizations of the
                    # individual Gaussians.
                    #
                    # First, fit all source Gaussians to each Stokes image:
                    x, y = N.mgrid[isl_bbox]
                    gg = src.gaussians
                    fitfix = N.ones(len(gg))  # fit only normalization
                    srcmask = isl.mask_active
                    total_flux = N.zeros(
                        (4, len(fitfix)), dtype=N.float32
                    )  # array of fluxes: N_Stokes x N_Gaussians
                    errors = N.zeros(
                        (4, len(fitfix)), dtype=N.float32
                    )  # array of fluxes: N_Stokes x N_Gaussians

                    for sind, image in enumerate(ch0_images):
                        if (sind == 0 and hasattr(src, '_pi')
                            ) or sind > 0:  # Fit I only for PI sources
                            p, ep = func.fit_mulgaus2d(image, gg, x, y,
                                                       srcmask, fitfix)
                            for ig in range(len(fitfix)):
                                center_pix = (p[ig * 6 + 1], p[ig * 6 + 2])
                                bm_pix = N.array([
                                    img.pixel_beam()[0],
                                    img.pixel_beam()[1],
                                    img.pixel_beam()[2]
                                ])
                                total_flux[sind, ig] = p[ig * 6] * p[
                                    ig * 6 + 3] * p[ig * 6 + 4] / (bm_pix[0] *
                                                                   bm_pix[1])
                            p = N.insert(p,
                                         N.arange(len(fitfix)) * 6 + 6,
                                         total_flux[sind])
                            if sind > 0:
                                rms_img = img.__getattribute__('rms_' +
                                                               pols[sind] +
                                                               '_arr')
                            else:
                                rms_img = img.rms_arr
                            if len(rms_img.shape) > 1:
                                rms_isl = rms_img[isl.bbox].mean()
                            else:
                                rms_isl = rms_img
                            errors[sind] = func.get_errors(img, p, rms_isl)[6]

                    # Now, assign fluxes to each Gaussian.
                    src_flux_I = 0.0
                    src_flux_Q = 0.0
                    src_flux_U = 0.0
                    src_flux_V = 0.0
                    src_flux_I_err_sq = 0.0
                    src_flux_Q_err_sq = 0.0
                    src_flux_U_err_sq = 0.0
                    src_flux_V_err_sq = 0.0

                    for ig, gaussian in enumerate(src.gaussians):
                        flux_I = total_flux[0, ig]
                        flux_I_err = abs(errors[0, ig])
                        flux_Q = total_flux[1, ig]
                        flux_Q_err = abs(errors[1, ig])
                        flux_U = total_flux[2, ig]
                        flux_U_err = abs(errors[2, ig])
                        flux_V = total_flux[3, ig]
                        flux_V_err = abs(errors[3, ig])

                        if hasattr(src, '_pi'):
                            gaussian.total_flux = flux_I
                            gaussian.total_fluxE = flux_I_err
                        gaussian.total_flux_Q = flux_Q
                        gaussian.total_flux_U = flux_U
                        gaussian.total_flux_V = flux_V
                        gaussian.total_fluxE_Q = flux_Q_err
                        gaussian.total_fluxE_U = flux_U_err
                        gaussian.total_fluxE_V = flux_V_err

                        if hasattr(src, '_pi'):
                            src_flux_I += flux_I
                            src_flux_I_err_sq += flux_I_err**2
                        src_flux_Q += flux_Q
                        src_flux_U += flux_U
                        src_flux_V += flux_V
                        src_flux_Q_err_sq += flux_Q_err**2
                        src_flux_U_err_sq += flux_U_err**2
                        src_flux_V_err_sq += flux_V_err**2

                        # Calculate and store polarisation fractions and angle for each Gaussian in the island
                        # For this we need the I flux, which we can just take from g.total_flux and src.total_flux
                        flux_I = gaussian.total_flux
                        flux_I_err = gaussian.total_fluxE
                        stokes = [flux_I, flux_Q, flux_U, flux_V]
                        stokes_err = [
                            flux_I_err, flux_Q_err, flux_U_err, flux_V_err
                        ]

                        lpol_frac, lpol_frac_loerr, lpol_frac_hierr = self.calc_lpol_fraction(
                            stokes, stokes_err)  # linear pol fraction
                        lpol_ang, lpol_ang_err = self.calc_lpol_angle(
                            stokes, stokes_err)  # linear pol angle
                        cpol_frac, cpol_frac_loerr, cpol_frac_hierr = self.calc_cpol_fraction(
                            stokes, stokes_err)  # circular pol fraction
                        tpol_frac, tpol_frac_loerr, tpol_frac_hierr = self.calc_tpol_fraction(
                            stokes, stokes_err)  # total pol fraction

                        gaussian.lpol_fraction = lpol_frac
                        gaussian.lpol_fraction_loerr = lpol_frac_loerr
                        gaussian.lpol_fraction_hierr = lpol_frac_hierr
                        gaussian.cpol_fraction = cpol_frac
                        gaussian.cpol_fraction_loerr = cpol_frac_loerr
                        gaussian.cpol_fraction_hierr = cpol_frac_hierr
                        gaussian.tpol_fraction = tpol_frac
                        gaussian.tpol_fraction_loerr = tpol_frac_loerr
                        gaussian.tpol_fraction_hierr = tpol_frac_hierr
                        gaussian.lpol_angle = lpol_ang
                        gaussian.lpol_angle_err = lpol_ang_err

                    # Store fluxes for each source in the island
                    if hasattr(src, '_pi'):
                        src.total_flux = src_flux_I
                        src.total_fluxE = N.sqrt(src_flux_I_err_sq)
                    src.total_flux_Q = src_flux_Q
                    src.total_flux_U = src_flux_U
                    src.total_flux_V = src_flux_V
                    src.total_fluxE_Q = N.sqrt(src_flux_Q_err_sq)
                    src.total_fluxE_U = N.sqrt(src_flux_U_err_sq)
                    src.total_fluxE_V = N.sqrt(src_flux_V_err_sq)

                    # Calculate and store polarisation fractions and angle for each source in the island
                    # For this we need the I flux, which we can just take from g.total_flux and src.total_flux
                    src_flux_I = src.total_flux
                    src_flux_I_err = src.total_fluxE
                    stokes = [src_flux_I, src_flux_Q, src_flux_U, src_flux_V]
                    stokes_err = [
                        src_flux_I_err,
                        N.sqrt(src_flux_Q_err_sq),
                        N.sqrt(src_flux_U_err_sq),
                        N.sqrt(src_flux_V_err_sq)
                    ]

                    lpol_frac, lpol_frac_loerr, lpol_frac_hierr = self.calc_lpol_fraction(
                        stokes, stokes_err)  # linear pol fraction
                    lpol_ang, lpol_ang_err = self.calc_lpol_angle(
                        stokes, stokes_err)  # linear pol angle
                    cpol_frac, cpol_frac_loerr, cpol_frac_hierr = self.calc_cpol_fraction(
                        stokes, stokes_err)  # circular pol fraction
                    tpol_frac, tpol_frac_loerr, tpol_frac_hierr = self.calc_tpol_fraction(
                        stokes, stokes_err)  # total pol fraction

                    src.lpol_fraction = lpol_frac
                    src.lpol_fraction_loerr = lpol_frac_loerr
                    src.lpol_fraction_hierr = lpol_frac_hierr
                    src.cpol_fraction = cpol_frac
                    src.cpol_fraction_loerr = cpol_frac_loerr
                    src.cpol_fraction_hierr = cpol_frac_hierr
                    src.tpol_fraction = tpol_frac
                    src.tpol_fraction_loerr = tpol_frac_loerr
                    src.tpol_fraction_hierr = tpol_frac_hierr
                    src.lpol_angle = lpol_ang
                    src.lpol_angle_err = lpol_ang_err
                    if bar.started:
                        bar.increment()
            bar.stop()
            img.completed_Ops.append('polarisation')
Example #4
0
    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
Example #5
0
class Op_gaul2srl(Op):
    """
    Slightly modified from fortran.
    """
    def __call__(self, img):
        #  for each island, get the gaussians into a list and then send them to process
        #  src_index is source number, starting from 0
        mylog = mylogger.logging.getLogger("PyBDSM." + img.log + "Gaul2Srl")
        mylogger.userinfo(mylog, 'Grouping Gaussians into sources')
        img.aperture = img.opts.aperture
        if img.aperture is not None and img.aperture <= 0.0:
            mylog.warn('Specified aperture is <= 0. Skipping aperture fluxes.')
            img.aperture = None

        src_index = -1
        dsrc_index = 0
        sources = []
        dsources = []
        no_gaus_islands = []
        for iisl, isl in enumerate(img.islands):
            isl_sources = []
            isl_dsources = []
            g_list = []
            for g in isl.gaul:
                if g.flag == 0:
                    g_list.append(g)

            if len(g_list) > 0:
                if len(g_list) == 1:
                    src_index, source = self.process_single_gaussian(img,
                                                                     g_list,
                                                                     src_index,
                                                                     code='S')
                    sources.append(source)
                    isl_sources.append(source)
                else:
                    src_index, source = self.process_CM(
                        img, g_list, isl, src_index)
                    sources.extend(source)
                    isl_sources.extend(source)
            else:
                if not img.waveletimage:
                    dg = isl.dgaul[0]
                    no_gaus_islands.append(
                        (isl.island_id, dg.centre_pix[0], dg.centre_pix[1]))
                    # Put in the dummy Source as the source and use negative IDs
                    g_list = isl.dgaul
                    dsrc_index, dsource = self.process_single_gaussian(
                        img, g_list, dsrc_index, code='S')
                    dsources.append(dsource)
                    isl_dsources.append(dsource)

            isl.sources = isl_sources
            isl.dsources = isl_dsources
        img.sources = sources
        img.dsources = dsources
        img.nsrc = src_index + 1
        mylogger.userinfo(mylog, "Number of sources formed from Gaussians",
                          str(img.nsrc))
        if not img.waveletimage and not img._pi and len(
                no_gaus_islands) > 0 and not img.opts.quiet:
            message = 'All Gaussians were flagged for the following island'
            if len(no_gaus_islands) == 1:
                message += ':\n'
            else:
                message += 's:\n'
            for isl_id in no_gaus_islands:
                message += '    Island #%i (x=%i, y=%i)\n' % isl_id
            if len(no_gaus_islands) == 1:
                message += 'Please check this island. If it is a valid island and\n'
            else:
                message += 'Please check these islands. If they are valid islands and\n'
            if img.opts.atrous_do:
                message += 'should be fit, try adjusting the flagging options (use\n'\
                           'show_fit with "ch0_flagged=True" to see the flagged Gaussians).'
            else:
                message += 'should be fit, try adjusting the flagging options (use\n'\
                           'show_fit with "ch0_flagged=True" to see the flagged Gaussians)\n'\
                           'or enabling the wavelet module (with "atrous_do=True").'
            message += '\nTo include empty islands in output source catalogs, set\n'\
                        'incl_empty=True in the write_catalog task.'
            mylog.warning(message)

        img.completed_Ops.append('gaul2srl')

#################################################################################################

    def process_single_gaussian(self, img, g_list, src_index, code):
        """ Process single gaussian into a source, for both S and C type sources. g is just one
            Gaussian object (not a list)."""

        g = g_list[0]

        total_flux = [g.total_flux, g.total_fluxE]
        peak_flux_centroid = peak_flux_max = [g.peak_flux, g.peak_fluxE]
        posn_sky_centroid = posn_sky_max = [g.centre_sky, g.centre_skyE]
        size_sky = [g.size_sky, g.size_skyE]
        size_sky_uncorr = [g.size_sky_uncorr, g.size_skyE]
        deconv_size_sky = [g.deconv_size_sky, g.deconv_size_skyE]
        deconv_size_sky_uncorr = [g.deconv_size_sky_uncorr, g.deconv_size_skyE]
        bbox = img.islands[g.island_id].bbox
        ngaus = 1
        island_id = g.island_id
        if g.gaus_num < 0:
            gaussians = []
        else:
            gaussians = list([g])
        aper_flux = func.ch0_aperture_flux(img, g.centre_pix, img.aperture)

        source_prop = list([code, total_flux, peak_flux_centroid, peak_flux_max, aper_flux, posn_sky_centroid, \
             posn_sky_max, size_sky, size_sky_uncorr, deconv_size_sky, deconv_size_sky_uncorr, bbox, ngaus, island_id, gaussians])
        source = Source(img, source_prop)

        if g.gaussian_idx == -1:
            src_index -= 1
        else:
            src_index += 1
        g.source_id = src_index
        g.code = code
        source.source_id = src_index

        return src_index, source

##################################################################################################

    def process_CM(self, img, g_list, isl, src_index):
        """
        Bundle errors with the quantities.
        ngau = number of gaussians in island
        src_id = the source index array for every gaussian in island
        nsrc = final number of distinct sources in the island
        """

        ngau = len(g_list)  # same as cisl in callgaul2srl.f
        nsrc = ngau  # same as islct; initially make each gaussian as a source
        src_id = N.arange(nsrc)  # same as islnum in callgaul2srl.f

        boxx, boxy = isl.bbox
        subn = boxx.stop - boxx.start
        subm = boxy.stop - boxy.start
        delc = [boxx.start, boxy.start]
        subim = self.make_subim(subn, subm, g_list, delc)

        index = [(i, j) for i in range(ngau) for j in range(ngau) if j > i]
        for pair in index:
            same_island = self.in_same_island(pair, img, g_list, isl, subim,
                                              subn, subm, delc)
            if same_island:
                nsrc -= 1
                mmax, mmin = max(src_id[pair[0]],
                                 src_id[pair[1]]), min(src_id[pair[0]],
                                                       src_id[pair[1]])
                arr = N.where(src_id == mmax)[0]
                src_id[arr] = mmin
                # now reorder src_id so that it is contiguous
        for i in range(ngau):
            ind1 = N.where(src_id == i)[0]
            if len(ind1) == 0:
                arr = N.where(src_id > i)[0]
                if len(arr) > 0:
                    decr = N.min(src_id[arr]) - i
                    for j in arr:
                        src_id[j] -= decr
        nsrc = N.max(src_id) + 1
        # now do whats in sub_calc_para_source

        source_list = []
        for isrc in range(nsrc):
            posn = N.where(src_id == isrc)[0]
            g_sublist = []
            for i in posn:
                g_sublist.append(g_list[i])
            ngau_insrc = len(posn)
            # Do source type C
            if ngau_insrc == 1:
                src_index, source = self.process_single_gaussian(img,
                                                                 g_sublist,
                                                                 src_index,
                                                                 code='C')
            else:
                # make mask and subim. Invalid mask value is -1 since 0 is valid srcid
                mask = self.make_mask(isl, subn, subm, 1, isrc, g_sublist,
                                      delc)
                src_index, source = self.process_Multiple(img, g_sublist, mask, src_index, isrc, subim, \
                                    isl, delc, subn, subm)
            source_list.append(source)

        return src_index, source_list

##################################################################################################

    def in_same_island(self, pair, img, g_list, isl, subim, subn, subm, delc):
        """ Whether two gaussians belong to the same source or not. """
        import functions as func

        def same_island_min(pair, g_list, subim, delc, tol=0.5):
            """ If the minimum of the reconstructed fluxes along the line joining the peak positions
                is greater than thresh_isl times the rms_clip, they belong to different islands. """

            g1 = g_list[pair[0]]
            g2 = g_list[pair[1]]
            pix1 = N.array(g1.centre_pix)
            pix2 = N.array(g2.centre_pix)

            x1, y1 = N.floor(pix1) - delc
            x2, y2 = N.floor(pix2) - delc
            pix1 = N.array(
                N.unravel_index(N.argmax(subim[x1:x1 + 2, y1:y1 + 2]),
                                (2, 2))) + [x1, y1]
            pix2 = N.array(
                N.unravel_index(N.argmax(subim[x2:x2 + 2, y2:y2 + 2]),
                                (2, 2))) + [x2, y2]
            if pix1[1] >= subn: pix1[1] = pix1[1] - 1
            if pix2[1] >= subm: pix2[1] = pix2[1] - 1

            maxline = int(round(N.max(N.abs(pix1 - pix2) + 1)))
            flux1 = g1.peak_flux
            flux2 = g2.peak_flux
            # get pix values of the line
            pixdif = pix2 - pix1
            same_island_min = False
            same_island_cont = False
            if maxline == 1:
                same_island_min = True
                same_island_cont = True
            else:
                if abs(pixdif[0]) > abs(pixdif[1]):
                    xline = N.round(min(pix1[0], pix2[0]) + N.arange(maxline))
                    yline = N.round((pix1[1]-pix2[1])/(pix1[0]-pix2[0])* \
                           (min(pix1[0],pix2[0])+N.arange(maxline)-pix1[0])+pix1[1])
                else:
                    yline = N.round(min(pix1[1], pix2[1]) + N.arange(maxline))
                    xline = N.round((pix1[0]-pix2[0])/(pix1[1]-pix2[1])* \
                           (min(pix1[1],pix2[1])+N.arange(maxline)-pix1[1])+pix1[0])
                rpixval = N.zeros(maxline, dtype=N.float32)
                xbig = N.where(xline >= N.size(subim, 0))
                xline[xbig] = N.size(subim, 0) - 1
                ybig = N.where(yline >= N.size(subim, 1))
                yline[ybig] = N.size(subim, 1) - 1
                for i in range(maxline):
                    pixval = subim[xline[i], yline[i]]
                    rpixval[i] = pixval
                min_pixval = N.min(rpixval)
                minind_p = N.argmin(rpixval)
                maxind_p = N.argmax(rpixval)

                if minind_p in (0, maxline - 1) and maxind_p in (0,
                                                                 maxline - 1):
                    same_island_cont = True
                if min_pixval >= min(flux1, flux2):
                    same_island_min = True
                elif abs(min_pixval - min(flux1, flux2)
                         ) <= tol * isl.rms * img.opts.thresh_isl:
                    same_island_min = True

            return same_island_min, same_island_cont

        def same_island_dist(pair, g_list, tol=0.5):
            """ If the centres are seperated by a distance less than half the sum of their
                fwhms along the PA of the line joining them, they belong to the same island. """
            from math import sqrt

            g1 = g_list[pair[0]]
            g2 = g_list[pair[1]]
            pix1 = N.array(g1.centre_pix)
            pix2 = N.array(g2.centre_pix)
            gsize1 = g1.size_pix
            gsize2 = g2.size_pix

            fwhm1 = func.gdist_pa(pix1, pix2, gsize1)
            fwhm2 = func.gdist_pa(pix1, pix2, gsize2)
            dx = pix2[0] - pix1[0]
            dy = pix2[1] - pix1[1]
            dist = sqrt(dy * dy + dx * dx)

            if dist <= tol * (fwhm1 + fwhm2):
                same_island = True
            else:
                same_island = False

            return same_island

        if img.opts.group_by_isl:
            same_isl1_min = True
            same_isl1_cont = True
            same_isl2 = True
        else:
            if img.opts.group_method == 'curvature':
                subim = -1.0 * func.make_curvature_map(subim)
            tol = img.opts.group_tol
            same_isl1_min, same_isl1_cont = same_island_min(
                pair, g_list, subim, delc, tol)
            same_isl2 = same_island_dist(pair, g_list, tol / 2.0)

        g1 = g_list[pair[0]]

        same_island = (same_isl1_min and same_isl2) or same_isl1_cont

        return same_island

##################################################################################################

    def process_Multiple(self, img, g_sublist, mask, src_index, isrc, subim,
                         isl, delc, subn, subm):
        """ Same as gaul_to_source.f. isrc is same as k in the fortran version. """
        from math import pi, sqrt
        from const import fwsig
        from scipy import ndimage
        import functions as func

        mylog = mylogger.logging.getLogger("PyBDSM." + img.log + "Gaul2Srl  ")
        dum = img.beam[0] * img.beam[1]
        cdeltsq = img.wcs_obj.acdelt[0] * img.wcs_obj.acdelt[1]
        bmar_p = 2.0 * pi * dum / (cdeltsq * fwsig * fwsig)

        # try
        subim_src = self.make_subim(subn, subm, g_sublist, delc)
        mompara = func.momanalmask_gaus(subim_src, mask, isrc, bmar_p, True)
        # initial peak posn and value
        maxv = N.max(subim_src)
        maxx, maxy = N.unravel_index(N.argmax(subim_src), subim_src.shape)
        # fit gaussian around this posn
        blc = N.zeros(2)
        trc = N.zeros(2)
        n, m = subim_src.shape[0:2]
        bm_pix = N.array([
            img.pixel_beam()[0] * fwsig,
            img.pixel_beam()[1] * fwsig,
            img.pixel_beam()[2]
        ])
        ssubimsize = max(N.int(N.round(N.max(bm_pix[0:2]) * 2)) + 1, 5)
        blc[0] = max(0, maxx - (ssubimsize - 1) / 2)
        blc[1] = max(0, maxy - (ssubimsize - 1) / 2)
        trc[0] = min(n, maxx + (ssubimsize - 1) / 2)
        trc[1] = min(m, maxy + (ssubimsize - 1) / 2)
        s_imsize = trc - blc + 1

        p_ini = [maxv, (s_imsize[0]-1)/2.0*1.1, (s_imsize[1]-1)/2.0*1.1, bm_pix[0]/fwsig*1.3, \
                 bm_pix[1]/fwsig*1.1, bm_pix[2]*2]
        data = subim_src[blc[0]:blc[0] + s_imsize[0],
                         blc[1]:blc[1] + s_imsize[1]]
        smask = mask[blc[0]:blc[0] + s_imsize[0], blc[1]:blc[1] + s_imsize[1]]
        rmask = N.where(smask == isrc, False, True)
        x_ax, y_ax = N.indices(data.shape)

        if N.sum(~rmask) >= 6:
            para, ierr = func.fit_gaus2d(data, p_ini, x_ax, y_ax, rmask)
            if (0.0<para[1]<s_imsize[0]) and (0.0<para[2]<s_imsize[1]) and \
              para[3]<s_imsize[0] and para[4]<s_imsize[1]:
                maxpeak = para[0]
            else:
                maxpeak = maxv
            posn = para[1:3] - (0.5 * N.sum(s_imsize) - 1) / 2.0 + N.array(
                [maxx, maxy]) - 1 + delc
        else:
            maxpeak = maxv
            posn = N.unravel_index(N.argmax(data * ~rmask),
                                   data.shape) + N.array(delc) + blc

        # calculate peak by bilinear interpolation around centroid
        # First check that moment analysis gave a valid position. If not, use
        # posn from gaussian fit instead.
        if N.isnan(mompara[1]):
            mompara[1] = posn[0] - delc[0]
        x1 = N.int(N.floor(mompara[1]))
        if N.isnan(mompara[2]):
            mompara[2] = posn[1] - delc[1]
        y1 = N.int(N.floor(mompara[2]))
        xind = slice(x1, x1 + 2, 1)
        yind = slice(y1, y1 + 2, 1)
        if img.opts.flag_smallsrc and (
                N.sum(mask[xind, yind] == N.ones((2, 2)) * isrc) != 4):
            mylog.debug('Island = ' + str(isl.island_id))
            mylog.debug('Mask = ' + repr(mask[xind, yind]) +
                        'xind, yind, x1, y1 = ' + repr(xind) + ' ' +
                        repr(yind) + ' ' + repr(x1) + ' ' + repr(y1))
        t = (mompara[1] - x1) / (x1 + 1 - x1)  # in case u change it later
        u = (mompara[2] - y1) / (y1 + 1 - y1)
        s_peak=(1.0-t)*(1.0-u)*subim_src[x1,y1]+t*(1.0-u)*subim_src[x1+1,y1]+ \
               t*u*subim_src[x1+1,y1+1]+(1.0-t)*u*subim_src[x1,y1+1]
        if (not img.opts.flag_smallsrc) and (
                N.sum(mask[xind, yind] == N.ones((2, 2)) * isrc) != 4):
            mylog.debug('Speak ' + repr(s_peak) + 'Mompara = ' + repr(mompara))
            mylog.debug('x1, y1 : ' + repr(x1) + ', ' + repr(y1))
            # import pylab as pl
            # pl.imshow(N.transpose(subim_src), origin='lower', interpolation='nearest')
            # pl.suptitle('Image of bad M source '+str(isl.island_id))
            # convert pixels to coords
        try:
            sra, sdec = img.pix2sky(
                [mompara[1] + delc[0], mompara[2] + delc[1]])
            mra, mdec = img.pix2sky(posn)
        except RuntimeError, err:
            # Invalid pixel wcs coordinate
            sra, sdec = 0.0, 0.0
            mra, mdec = 0.0, 0.0

        # "deconvolve" the sizes
        gaus_c = [mompara[3], mompara[4], mompara[5]]
        gaus_bm = [bm_pix[0], bm_pix[1], bm_pix[2]]
        gaus_dc, err = func.deconv2(gaus_bm, gaus_c)
        deconv_size_sky = img.pix2gaus(
            gaus_dc, [mompara[1] + delc[0], mompara[2] + delc[1]])
        deconv_size_sky_uncorr = img.pix2gaus(
            gaus_dc, [mompara[1] + delc[0], mompara[2] + delc[1]],
            use_wcs=False)

        # update all objects etc
        tot = 0.0
        totE_sq = 0.0
        for g in g_sublist:
            tot += g.total_flux
            totE_sq += g.total_fluxE**2
        totE = sqrt(totE_sq)
        size_pix = [mompara[3], mompara[4], mompara[5]]
        size_sky = img.pix2gaus(size_pix,
                                [mompara[1] + delc[0], mompara[2] + delc[1]])
        size_sky_uncorr = img.pix2gaus(
            size_pix, [mompara[1] + delc[0], mompara[2] + delc[1]],
            use_wcs=False)

        # Estimate uncertainties in source size and position due to
        # errors in the constituent Gaussians using a Monte Carlo technique.
        # Sum with Condon (1997) errors in quadrature.
        plist = mompara.tolist() + [tot]
        plist[0] = s_peak
        plist[3] /= fwsig
        plist[4] /= fwsig
        errors = func.get_errors(img, plist, isl.rms)

        if img.opts.do_mc_errors:
            nMC = 20
            mompara0_MC = N.zeros(nMC, dtype=N.float32)
            mompara1_MC = N.zeros(nMC, dtype=N.float32)
            mompara2_MC = N.zeros(nMC, dtype=N.float32)
            mompara3_MC = N.zeros(nMC, dtype=N.float32)
            mompara4_MC = N.zeros(nMC, dtype=N.float32)
            mompara5_MC = N.zeros(nMC, dtype=N.float32)
            for i in range(nMC):
                # Reconstruct source from component Gaussians. Draw the Gaussian
                # parameters from random distributions given by their errors.
                subim_src_MC = self.make_subim(subn,
                                               subm,
                                               g_sublist,
                                               delc,
                                               mc=True)

                try:
                    mompara_MC = func.momanalmask_gaus(subim_src_MC, mask,
                                                       isrc, bmar_p, True)
                    mompara0_MC[i] = mompara_MC[0]
                    mompara1_MC[i] = mompara_MC[1]
                    mompara2_MC[i] = mompara_MC[2]
                    mompara3_MC[i] = mompara_MC[3]
                    mompara4_MC[i] = mompara_MC[4]
                    mompara5_MC[i] = mompara_MC[5]
                except:
                    mompara0_MC[i] = mompara[0]
                    mompara1_MC[i] = mompara[1]
                    mompara2_MC[i] = mompara[2]
                    mompara3_MC[i] = mompara[3]
                    mompara4_MC[i] = mompara[4]
                    mompara5_MC[i] = mompara[5]
            mompara0E = N.std(mompara0_MC)
            mompara1E = N.std(mompara1_MC)
            if mompara1E > 2.0 * mompara[1]:
                mompara1E = 2.0 * mompara[1]  # Don't let errors get too large
            mompara2E = N.std(mompara2_MC)
            if mompara2E > 2.0 * mompara[2]:
                mompara2E = 2.0 * mompara[2]  # Don't let errors get too large
            mompara3E = N.std(mompara3_MC)
            if mompara3E > 2.0 * mompara[3]:
                mompara3E = 2.0 * mompara[3]  # Don't let errors get too large
            mompara4E = N.std(mompara4_MC)
            if mompara4E > 2.0 * mompara[4]:
                mompara4E = 2.0 * mompara[4]  # Don't let errors get too large
            mompara5E = N.std(mompara5_MC)
            if mompara5E > 2.0 * mompara[5]:
                mompara5E = 2.0 * mompara[5]  # Don't let errors get too large
        else:
            mompara1E = 0.0
            mompara2E = 0.0
            mompara3E = 0.0
            mompara4E = 0.0
            mompara5E = 0.0

        # Now add MC errors in quadrature with Condon (1997) errors
        size_skyE = [
            sqrt(mompara3E**2 + errors[3]**2) * sqrt(cdeltsq),
            sqrt(mompara4E**2 + errors[4]**2) * sqrt(cdeltsq),
            sqrt(mompara5E**2 + errors[5]**2)
        ]
        sraE, sdecE = (sqrt(mompara1E**2 + errors[1]**2) * sqrt(cdeltsq),
                       sqrt(mompara2E**2 + errors[2]**2) * sqrt(cdeltsq))
        deconv_size_skyE = size_skyE  # set deconvolved errors to non-deconvolved ones

        # Find aperture flux
        if img.opts.aperture_posn == 'centroid':
            aper_pos = [mompara[1] + delc[0], mompara[2] + delc[1]]
        else:
            aper_pos = posn
        aper_flux, aper_fluxE = func.ch0_aperture_flux(img, aper_pos,
                                                       img.aperture)

        isl_id = isl.island_id
        source_prop = list([
            'M', [tot, totE], [s_peak, isl.rms], [maxpeak, isl.rms],
            [aper_flux, aper_fluxE], [[sra, sdec], [sraE, sdecE]],
            [[mra, mdec], [sraE, sdecE]], [size_sky, size_skyE],
            [size_sky_uncorr, size_skyE], [deconv_size_sky, deconv_size_skyE],
            [deconv_size_sky_uncorr, deconv_size_skyE], isl.bbox,
            len(g_sublist), isl_id, g_sublist
        ])
        source = Source(img, source_prop)

        src_index += 1
        for g in g_sublist:
            g.source_id = src_index
            g.code = 'M'
        source.source_id = src_index

        return src_index, source
Example #6
0
    def __call__(self, img):
        mylog = mylogger.logging.getLogger("PyBDSM."+img.log+"Polarisatn")
        if img.opts.polarisation_do:
          mylog.info('Extracting polarisation properties for all sources')
          pols = ['I', 'Q', 'U', 'V']

          # Run gausfit and gual2srl on PI image to look for polarized sources
          # undetected in I
          fit_PI = img.opts.pi_fit
          n_new = 0
          ch0_pi = N.sqrt(img.ch0_Q_arr**2 + img.ch0_U_arr**2)
          img.ch0_pi_arr = ch0_pi

          if fit_PI:
              from . import _run_op_list
              mylogger.userinfo(mylog, "\nChecking PI image for new sources")

              mask = img.mask_arr
              minsize = img.opts.minpix_isl

              # Set up image object for PI image.
              pi_chain, pi_opts = self.setpara_bdsm(img)
              pimg = Image(pi_opts)
              pimg.beam = img.beam
              pimg.pixel_beam = img.pixel_beam
              pimg.pixel_beamarea = img.pixel_beamarea
              pimg.log = 'PI.'
              pimg.pix2beam = img.pix2beam
              pimg.beam2pix = img.beam2pix
              pimg.pix2gaus = img.pix2gaus
              pimg.gaus2pix = img.gaus2pix
              pimg.pix2sky = img.pix2sky
              pimg.sky2pix = img.sky2pix
              pimg.pix2coord = img.pix2coord
              pimg.wcs_obj = img.wcs_obj
              pimg.mask_arr = mask
              pimg.masked = img.masked
              pimg.ch0_arr = ch0_pi
              pimg._pi = True

              success = _run_op_list(pimg, pi_chain)
              if not success:
                  return

              img.pi_islands = pimg.islands
              img.pi_gaussians = pimg.gaussians
              img.pi_sources = pimg.sources

              # Now check for new sources in the PI image that are not
              # found in the Stokes I image. If any new sources are found,
              # adjust their IDs to follow after those found in I.
              new_isl = []
              new_src = []
              new_gaus = []
              n_new_src = 0
              isl_id = img.islands[-1].island_id
              src_id = img.sources[-1].source_id
              gaus_id = img.gaussians[-1].gaus_num
              for pi_isl in pimg.islands:
                  new_sources = []
                  for pi_src in pi_isl.sources:
                      if img.pyrank[int(img.sky2pix(pi_src.posn_sky_max)[0]),
                                    int(img.sky2pix(pi_src.posn_sky_max)[1])] == -1:
                          src_id += 1
                          pi_src._pi = True
                          pi_src.island_id = isl_id
                          pi_src.source_id = src_id
                          pi_src.spec_indx = N.NaN
                          pi_src.e_spec_indx = N.NaN
                          pi_src.spec_norm = N.NaN
                          pi_src.specin_flux = [N.NaN]
                          pi_src.specin_fluxE = [N.NaN]
                          pi_src.specin_freq = [N.NaN]
                          pi_src.specin_freq0 = N.NaN
                          new_sources.append(pi_src)
                          new_src.append(pi_src)
                          n_new_src += 1
                          for g in pi_src.gaussians:
                              gaus_id += 1
                              new_gaus.append(g)
                              g.gaus_num = gaus_id
                  if len(new_sources) > 0:
                      isl_id += 1
                      pi_isl.sources = new_sources
                      pi_isl.island_id = isl_id
                      pi_isl._pi = True
                      new_isl.append(pi_isl)

              n_new = len(new_isl)
              mylogger.userinfo(mylog, "New sources found in PI image", '%i (%i total)' %
                                (n_new, img.nsrc+n_new))

          if n_new > 0:
              img.islands += new_isl
              img.sources += new_src
              img.gaussians += new_gaus
              img.nsrc += n_new_src

          bar = statusbar.StatusBar('Calculating polarisation properties ....  : ', 0, img.nsrc)
          if img.opts.quiet == False:
              bar.start()

          for isl in img.islands:
            isl_bbox = isl.bbox
            ch0_I = img.ch0_arr[isl_bbox]
            ch0_Q = img.ch0_Q_arr[isl_bbox]
            ch0_U = img.ch0_U_arr[isl_bbox]
            ch0_V = img.ch0_V_arr[isl_bbox]
            ch0_images = [ch0_I, ch0_Q, ch0_U, ch0_V]

            for i, src in enumerate(isl.sources):
                # For each source, assume the morphology does not change
                # across the Stokes cube. This assumption allows us to fit
                # the Gaussians of each source to each Stokes image by
                # simply fitting only the overall normalizations of the
                # individual Gaussians.
                #
                # First, fit all source Gaussians to each Stokes image:
                x, y = N.mgrid[isl_bbox]
                gg = src.gaussians
                fitfix = N.ones(len(gg)) # fit only normalization
                srcmask = isl.mask_active
                total_flux = N.zeros((4, len(fitfix)), dtype=N.float32) # array of fluxes: N_Stokes x N_Gaussians
                errors = N.zeros((4, len(fitfix)), dtype=N.float32) # array of fluxes: N_Stokes x N_Gaussians

                for sind, image in enumerate(ch0_images):
                    if (sind==0 and hasattr(src, '_pi')) or sind > 0: # Fit I only for PI sources
                        p, ep = func.fit_mulgaus2d(image, gg, x, y, srcmask, fitfix)
                        for ig in range(len(fitfix)):
                            center_pix = (p[ig*6 + 1], p[ig*6 + 2])
                            bm_pix = N.array([img.pixel_beam()[0], img.pixel_beam()[1], img.pixel_beam()[2]])
                            total_flux[sind, ig] = p[ig*6]*p[ig*6+3]*p[ig*6+4]/(bm_pix[0]*bm_pix[1])
                        p = N.insert(p, N.arange(len(fitfix))*6+6, total_flux[sind])
                        if sind > 0:
                            rms_img = img.__getattribute__('rms_'+pols[sind]+'_arr')
                        else:
                            rms_img = img.rms_arr
                        if len(rms_img.shape) > 1:
                            rms_isl = rms_img[isl.bbox].mean()
                        else:
                            rms_isl = rms_img
                        errors[sind] = func.get_errors(img, p, rms_isl)[6]

                # Now, assign fluxes to each Gaussian.
                src_flux_I = 0.0
                src_flux_Q = 0.0
                src_flux_U = 0.0
                src_flux_V = 0.0
                src_flux_I_err_sq = 0.0
                src_flux_Q_err_sq = 0.0
                src_flux_U_err_sq = 0.0
                src_flux_V_err_sq = 0.0

                for ig, gaussian in enumerate(src.gaussians):
                    flux_I = total_flux[0, ig]
                    flux_I_err = abs(errors[0, ig])
                    flux_Q = total_flux[1, ig]
                    flux_Q_err = abs(errors[1, ig])
                    flux_U = total_flux[2, ig]
                    flux_U_err = abs(errors[2, ig])
                    flux_V = total_flux[3, ig]
                    flux_V_err = abs(errors[3, ig])

                    if hasattr(src, '_pi'):
                        gaussian.total_flux = flux_I
                        gaussian.total_fluxE = flux_I_err
                    gaussian.total_flux_Q = flux_Q
                    gaussian.total_flux_U = flux_U
                    gaussian.total_flux_V = flux_V
                    gaussian.total_fluxE_Q = flux_Q_err
                    gaussian.total_fluxE_U = flux_U_err
                    gaussian.total_fluxE_V = flux_V_err

                    if hasattr(src, '_pi'):
                        src_flux_I += flux_I
                        src_flux_I_err_sq += flux_I_err**2
                    src_flux_Q += flux_Q
                    src_flux_U += flux_U
                    src_flux_V += flux_V
                    src_flux_Q_err_sq += flux_Q_err**2
                    src_flux_U_err_sq += flux_U_err**2
                    src_flux_V_err_sq += flux_V_err**2

                    # Calculate and store polarisation fractions and angle for each Gaussian in the island
                    # For this we need the I flux, which we can just take from g.total_flux and src.total_flux
                    flux_I = gaussian.total_flux
                    flux_I_err = gaussian.total_fluxE
                    stokes = [flux_I, flux_Q, flux_U, flux_V]
                    stokes_err = [flux_I_err, flux_Q_err, flux_U_err, flux_V_err]

                    lpol_frac, lpol_frac_loerr, lpol_frac_hierr = self.calc_lpol_fraction(stokes, stokes_err) # linear pol fraction
                    lpol_ang, lpol_ang_err = self.calc_lpol_angle(stokes, stokes_err) # linear pol angle
                    cpol_frac, cpol_frac_loerr, cpol_frac_hierr = self.calc_cpol_fraction(stokes, stokes_err) # circular pol fraction
                    tpol_frac, tpol_frac_loerr, tpol_frac_hierr = self.calc_tpol_fraction(stokes, stokes_err) # total pol fraction

                    gaussian.lpol_fraction = lpol_frac
                    gaussian.lpol_fraction_loerr = lpol_frac_loerr
                    gaussian.lpol_fraction_hierr = lpol_frac_hierr
                    gaussian.cpol_fraction = cpol_frac
                    gaussian.cpol_fraction_loerr = cpol_frac_loerr
                    gaussian.cpol_fraction_hierr = cpol_frac_hierr
                    gaussian.tpol_fraction = tpol_frac
                    gaussian.tpol_fraction_loerr = tpol_frac_loerr
                    gaussian.tpol_fraction_hierr = tpol_frac_hierr
                    gaussian.lpol_angle = lpol_ang
                    gaussian.lpol_angle_err = lpol_ang_err

                # Store fluxes for each source in the island
                if hasattr(src, '_pi'):
                    src.total_flux = src_flux_I
                    src.total_fluxE = N.sqrt(src_flux_I_err_sq)
                src.total_flux_Q = src_flux_Q
                src.total_flux_U = src_flux_U
                src.total_flux_V = src_flux_V
                src.total_fluxE_Q = N.sqrt(src_flux_Q_err_sq)
                src.total_fluxE_U = N.sqrt(src_flux_U_err_sq)
                src.total_fluxE_V = N.sqrt(src_flux_V_err_sq)

                # Calculate and store polarisation fractions and angle for each source in the island
                # For this we need the I flux, which we can just take from g.total_flux and src.total_flux
                src_flux_I = src.total_flux
                src_flux_I_err = src.total_fluxE
                stokes = [src_flux_I, src_flux_Q, src_flux_U, src_flux_V]
                stokes_err = [src_flux_I_err, N.sqrt(src_flux_Q_err_sq), N.sqrt(src_flux_U_err_sq), N.sqrt(src_flux_V_err_sq)]

                lpol_frac, lpol_frac_loerr, lpol_frac_hierr = self.calc_lpol_fraction(stokes, stokes_err) # linear pol fraction
                lpol_ang, lpol_ang_err = self.calc_lpol_angle(stokes, stokes_err) # linear pol angle
                cpol_frac, cpol_frac_loerr, cpol_frac_hierr = self.calc_cpol_fraction(stokes, stokes_err) # circular pol fraction
                tpol_frac, tpol_frac_loerr, tpol_frac_hierr = self.calc_tpol_fraction(stokes, stokes_err) # total pol fraction

                src.lpol_fraction = lpol_frac
                src.lpol_fraction_loerr = lpol_frac_loerr
                src.lpol_fraction_hierr = lpol_frac_hierr
                src.cpol_fraction = cpol_frac
                src.cpol_fraction_loerr = cpol_frac_loerr
                src.cpol_fraction_hierr = cpol_frac_hierr
                src.tpol_fraction = tpol_frac
                src.tpol_fraction_loerr = tpol_frac_loerr
                src.tpol_fraction_hierr = tpol_frac_hierr
                src.lpol_angle = lpol_ang
                src.lpol_angle_err = lpol_ang_err
                if bar.started:
                    bar.increment()
          bar.stop()
          img.completed_Ops.append('polarisation')