예제 #1
0
 def apply_transfer_1d(self, kgrid, maglim=26.5):
     """
   Apply a 1D SExtractor magnitude kernels at the FAINT END. This only 
   happens for magnitudes FAINTER than maglim.
   """
     convolved = np.zeros(self.RLDist.value.shape, "float")
     # temporary store the GALFIT kernel-corrected distribution
     value_temp = self.RLDist.value.copy()
     # self.RLDist.value_last = value_temp
     # bring back the distribution before GALFIT kernel corrections
     self.RLDist.value = self.RLDist.value_last.copy()
     for key in kgrid.kernels.keys():
         k = kgrid.kernels[key]
         if k.completeness > 0:
             maglo, maghi = kgrid.get_kernel_coverage(key)
             if (maglo <= maglim) & (maghi > maglim):
                 # apply 1-D kernel
                 section = self.RLDist.window_function(
                     maglo, maghi, self.RLDist.ylimits[0],
                     self.RLDist.ylimits[1])
                 k2d = np.zeros((len(k.kernel), 5))
                 k2d[:, 2] = k.kernel
                 section = hconvolve(section, k2d, threads=1)
                 convolved = convolved + section
     # now combine this with self.RLDist.value
     self.RLDist.value = value_temp + convolved
     return self.RLDist
예제 #2
0
def conv_kernel(key, kgrid, bmodel):
    """
   Given a kernel grid kgrid, find the corresponding kernel using the provided key.
   Then convolve the corresponding region of bmodel with the kernel and returned 
   the convolved model array.
   key -- a list of indices for a given kernel
   kgrid -- the transfunc_calc.kernelgrid instance
   bmodel -- a bivmodel.bivmodel instance
   """
    # the worker function to perform convolution for a given kernel
    namodel = bmodel.model
    modshape = shape(namodel)
    print modshape
    limits = bmodel.limits
    pixdx = bmodel.pixdx
    kern = kgrid.kernels[key]  # the kernel under consideration
    print shape(kern.kernel)
    x0, x1 = kern.x0_cell, kern.x1_cell  # the limits this kernel applies
    index0 = around((x0 - limits[:, 0]) / pixdx).astype('int')
    index1 = around((x1 - limits[:, 0]) / pixdx).astype('int')
    mid0, rid0 = index0
    mid1, rid1 = index1
    #print "mid0,mid1,rid0,rid1",mid0,mid1,rid0,rid1
    # if this kernel is COMPLETELY outside of the limits -- do not perform convolution
    if (mid1 < 0) | (rid1 < 0):
        return zeros(modshape)
    if (mid0 > modshape[0]) | (rid0 > modshape[1]):
        return zeros(modshape)
    # if kernel bounds partially overlaps with model space: set indexes accordingly
    # so that the proper region in model is convolved with kernel
    mid0 = maximum(mid0, 0)
    rid0 = maximum(rid0, 0)
    mid1 = minimum(mid1, modshape[0])
    rid1 = minimum(rid1, modshape[1])
    #print "mid0,mid1,rid0,rid1",mid0,mid1,rid0,rid1
    kx, ky = shape(kern.kernel)  # the kernel array dimension
    if kx % 2 == 0:
        kx0 = kx / 2 - 1  # padding before section
        kx1 = kx / 2  # padding after section
    else:
        kx0 = kx / 2
        kx1 = kx / 2
    if ky % 2 == 0:
        ky0 = ky / 2 - 1
        ky1 = ky / 2
    else:
        ky0 = ky / 2
        ky1 = ky / 2
    section = zeros(shape(namodel), "float")
    section[mid0:mid1,
            rid0:rid1] = namodel[mid0:mid1,
                                 rid0:rid1]  # paste the model onto empty image
    # min_comp is used to mask out low completeness kernels --- not implemented now
    if (sum(kern.kernel.ravel()) > 0) & (sum(section.ravel()) > 0):
        convolved_sect = hconvolve.hconvolve(section,
                                             kern.kernel)  # for hconvolve
    else:
        convolved_sect = 0. * section
    return convolved_sect
예제 #3
0
 def convolve(self, kernel, output):
     """
   Convolves self with a kernel, and save the output.
   """
     kernelimg = pyfits.getdata(kernel)
     convimg = hconvolve(self.data, kernelimg)
     if os.path.exists(output):
         os.remove(output)
     pyfits.append(output, convimg, self.hdr)
예제 #4
0
def blur_mask(mask, blur_kernel, threshold=0.1):
    """
   Given an input mask image (numpy array) of values 0 or 1 (1 being accepted 
   pixels), convolve the mask by blur_kernel (normalized to 1) and set pixels 
   above the threshold to value 1 and then the rest 0.
   """
    k = pyfits.getdata(blur_kernel)
    k = k / k.sum()
    mask = hconvolve.hconvolve(mask, k)
    mask = np.where(mask >= threshold, 1, 0).astype('int')
    return mask
예제 #5
0
def apply_transfer_2d_worker(bmodel, kgrid, klist, q_out):
    for k in klist:
        kern = kgrid.kernels[k]  # the kernel under consideration
        #print shape(kern.kernel)
        x0, x1 = kern.x0_cell, kern.x1_cell  # the limits this kernel applies
        index0 = around(
            (x0 - bmodel.limits[:, 0]) / bmodel.pixdx).astype('int')
        index1 = around(
            (x1 - bmodel.limits[:, 0]) / bmodel.pixdx).astype('int')
        mid0, rid0 = index0
        mid1, rid1 = index1
        modshape = shape(bmodel.model)
        namodel = bmodel.model
        #print "mid0,mid1,rid0,rid1",mid0,mid1,rid0,rid1
        # if this kernel is COMPLETELY outside of the limits -- do not perform convolution
        if (mid1 < 0) | (rid1 < 0):
            continue
        elif (mid0 > modshape[0]) | (rid0 > modshape[1]):
            continue
        # if kernel bounds partially overlaps with model space: set indexes accordingly
        # so that the proper region in model is convolved with kernel
        mid0 = maximum(mid0, 0)
        rid0 = maximum(rid0, 0)
        mid1 = minimum(mid1, modshape[0])
        rid1 = minimum(rid1, modshape[1])
        kx, ky = shape(kern.kernel)  # the kernel array dimension
        if kx % 2 == 0:
            kx0 = kx / 2 - 1  # padding before section
            kx1 = kx / 2  # padding after section
        else:
            kx0 = kx / 2
            kx1 = kx / 2
        if ky % 2 == 0:
            ky0 = ky / 2 - 1
            ky1 = ky / 2
        else:
            ky0 = ky / 2
            ky1 = ky / 2
        section = zeros(shape(namodel), "float")
        section[mid0:mid1, rid0:rid1] = namodel[mid0:mid1, rid0:rid1]
        # paste the model onto empty image
        if (sum(kern.kernel.ravel()) > 0) & (sum(section.ravel()) > 0):
            convolved_sect = hconvolve.hconvolve(section,
                                                 kern.kernel)  # for hconvolve
        else:
            convolved_sect = 0. * section
        q_out.put(convolved_sect)
예제 #6
0
 def worker(keys, q):
     for key in keys:
         k = KG.kernels[key[0], key[1]]
         if k.completeness > 0:
             maglo, maghi = np.array(KG.get_kernel_coverage(*key)[:2])
             logrlo, logrhi = KG.get_kernel_coverage(*key)[2:]
             # if maglo >= maglim:
             if not self.RLDist.overlap(maglo, maghi, logrlo, logrhi):
                 # this kernel is too faint... continue
                 continue
             # elif self.RLDist.overlap(maglo, maghi, logrlo, logrhi):
             else:
                 section = self.RLDist.window_function(
                     maglo, maghi, logrlo, logrhi)
                 # If we already parallel the kernels, then DO NOT use
                 # parallelization in hconvolve again! Python doesn't like that.
                 section = hconvolve(section, k.kernel, threads=1)
                 q.put(section)
예제 #7
0
    def M2M(self, params, kcorr=0.):
        """
      Calculate RM distribution, then apply the transformation from 
      log(M_star) directly to m_obs.
      self.M2M_kernel should be a dictionary, whose keys are (logMlo,logMhi)
      denoting the boundary of each stellar mass bin, and the values are
      a tuple (X0, p(X) or sigma_X)---sigma_X being the scatter of a 
      Gaussian around X0 *in magnitudes*. The conversion between M1500 and 
      logM is

      M1500 = (-2.5/a) * logM + X
      
      params are in (alpha_m, logMstar_m, logR0, sigma, beta_m)
      """
        # Strategy: convert R-M distribution into R-m (apparent magnitude)
        # distribution using the "X factor" and the magnitude correction at
        # each redshift z.
        bivmodel_RL = zeros(self.npix)
        # the kernel width in the X dimension
        kw = self.M2M_kernel['kwidth']
        # kw is in pixels
        X_ref = self.M2M_kernel['xref']
        # a reference value for X. I will shift RM distribution by X_ref first,
        # and then shift the kernel in each bin to center around the respective
        # X values.
        # if 'type' == 'distribution': not yet implemented...
        if self.M2M_kernel['type'] == 'distribution':
            # the correction is M1500 = -log10(M_star) + X, with X a random
            # variable following probability distribution p(X)
            # First, convert logM into m (apparent magnitude) and calculate the
            # uncorrected R-m distribution converted from RM distribution.
            # Pixel size is unchanged.
            raise ValueError, "distribution-type M2M kernels not yet implemented..."
            mstar_ref = -1. * params[1] + X_ref + kcorr
            m0_ref = -1. * self.logM0 + X_ref + kcorr
            params_ref = params.copy()
            params_ref[1] = mstar_ref
            #print "params_ref", params_ref
            #print "m0_ref", m0_ref
            model0 = self.bivariate_RM_0(params_ref,
                                         self.limits,
                                         pixdx=self.pixdx,
                                         logM0=m0_ref,
                                         xdirection=1,
                                         a=1)
            #print "max(model0)", max(model0.ravel())
            # Now apply relative shifts for each kernel (relative to X_ref) as
            # well as smearing around X0 in each bin.
            for k in self.M2M_kernel['kernels'].keys():
                if k[1] < self.limits_m[0][1]:
                    continue
                elif k[0] > self.limits_m[0][0]:
                    continue
                #print "k", k
                X0 = self.M2M_kernel['kernels'][k][0]
                # the reference X of this bin
                logMlo = k[0]
                logMhi = k[1]
                # The limits in M1500 of this stellar mass bin before smearing
                mobs_hi = -1. * logMlo + X0 + kcorr
                mobs_lo = -1. * logMhi + X0 + kcorr
                j0 = round((mobs_lo - self.limits[0][0]) / self.pixdx[0])
                j0 = maximum(int(j0), 0)
                j1 = round((mobs_hi - self.limits[0][0]) / self.pixdx[0])
                j1 = minimum(int(j1), self.npix[0] - 1)
                #print "k, j0, j1", k, j0, j1
                if j1 <= j0:
                    continue
                model_RL_k = model0.copy()
                # Copy the section in this log(M_star) bin onto the M1500 grid
                #model_RL_k[j0:j1] = model_RM_k[i0:i1].copy()
                model_RL_k[:j0, :] = 0.
                model_RL_k[j1:, :] = 0.
                # Now smear the model
                X_shift = X0 - X_ref
                # the relative shift between X0 and X_ref---this will be the mean
                # of the Gaussian distribution of this kernel
                X_shift_pix = X_shift / self.pixdx[0]
                #if type(self.M2M_kernel[k][1]) == type(1.0):
                # A Gaussian kernel, with sigma given in magnitude
                sigma_X = self.M2M_kernel['kernels'][k][1]
                # sigma_X is in magnitudes
                sigma_X_pix = sigma_X / self.pixdx[0]
                # sigma_X_pix is in pixels
                if kw % 2 == 1:
                    xarr = arange(-(kw - 1) / 2., (kw + 1) / 2.)
                else:
                    xarr = arange(kw) - kw / 2.
                if sigma_X > 0:
                    kernel = gauss.gauss(xarr, X_shift_pix, sigma_X_pix)
                else:
                    # a delta-function kernel
                    kernel = zeros(kw)
                    kernel[int(kw / 2 + X_shift_pix)] = 1.0
                #else:
                #   # the 1-D smearing kernel
                #   kernel = self.M2M_kernel[k][1].copy()
                # Make kernel into a 2D array (pad with 0 on both sides) for
                # convolution
                kernel2d = zeros((len(kernel), 3))
                kernel2d[:, 1] = kernel
                # smear with p(X)
                model_RL_k = hconvolve(model_RL_k, kernel2d)
                # paste back onto bivmodel_M1500
                bivmodel_RL = bivmodel_RL + model_RL_k
        elif self.M2M_kernel['type'] == 'equation':
            # Uses a linear equation M1500 = -a * log(M_star) + b, and a Gaussian
            # spread around this equation (the uncertainty is the same throughout)
            # all stellar mass bins.
            # If dm is given by self.pixdx[0], then dlogM needs to be rescaled
            # to self.pixdx[0]/a
            a, b, sigma_X = self.M2M_kernel['kernels']
            sigma_X_pix = sigma_X / self.pixdx[0]
            # if M2M_kernel['type']=='equation', then M2M_kernel['kernels']
            # should contain a list of three numbers: a, b, and sigma_X. The
            # transformation now is M1500 = -a * log(M_star) + b, and sigma_X
            # smears the model in the magnitude direction.
            mstar_ref = (-2.5 / a) * params[1] + b + kcorr
            m0_ref = (-2.5 / a) * self.logM0 + b + kcorr
            params_ref = params.copy()
            params_ref[1] = mstar_ref
            #print "params_ref", params_ref
            #print "m0_ref", m0_ref
            model0 = self.bivariate_RM1500_0(params,
                                             self.limits,
                                             pixdx=self.pixdx,
                                             logM0=self.logM0,
                                             a=abs(a),
                                             b=b,
                                             kcorr=kcorr)
            #return model0
            # Now apply the smearing due to uncertain M/L
            if kw % 2 == 1:
                xarr = arange(-(kw - 1) / 2., (kw + 1) / 2.)
            else:
                xarr = arange(kw) - kw / 2.
            if sigma_X > 0:
                kernel = gauss.gauss(xarr, 0., sigma_X_pix)
            else:
                # a delta-function kernel
                kernel = zeros(kw)
                kernel[int(kw / 2)] = 1.0
            kernel2d = zeros((len(kernel), 3))
            kernel2d[:, 1] = kernel
            # smear with p(X)
            bivmodel_RL = hconvolve(model0, kernel2d)

        return bivmodel_RL