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
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
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)
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
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)
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)
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