def integrate_to_bins(self, new_bin_edges, theta_unit='a'): """ Uses integrate_gp to rebin the existing G_p. Note that the new G_p does not have the new bin widths divided out so it follows Sum{G_p,i} = 1, not integral(G_p(theta) d theta) = 1 Parameters ---------- new_bin_edges: array The values of theta defining the bin edges that you want to integrate to. The theta values are in units theta_unit theta_unit : string (optional) The unit in which new_bin_edges are given. The options are 'a', 'arcsec', 'arcseconds'; 'd', 'deg', 'degrees'; 'r', 'rad', 'radians'. Default is 'arcseconds' Returns ------- new_gp : array Gp integrated over the new bins """ #Convert the thetas to degrees new_bin_edges = misc.put_thetas_in_degrees(new_bin_edges, theta_unit) #Integrate Gp over each bin n_new_bins = len(new_bin_edges)-1 binned = np.zeros(n_new_bins) for i in range(n_new_bins): binned[i] = self.integrate_gp(new_bin_edges[i], new_bin_edges[i+1]) return binned
def integrate_powerlaw(self, A, beta, lowlim, highlim, param_unit='d', theta_unit='d'): """ A funtion that integrates the power law A * theta^-beta over a range of thetas Parameters ---------- A : float The amplitude of the power law for theta in units param_unit beta : float The power in the power law lowlim : float The lower limit of the theta range to integrate over highlim : float The upper limit of the theta range to integrate over param_unit : string (optional) The units of theta for which A was calculated. The options are 'a', 'arcsec', 'arcseconds'; 'd', 'deg', 'degrees'; 'r', 'rad', 'radians'. Default is 'd' theta_unit : string (optional) The units of lowlim and highlim. The options are 'a', 'arcsec', 'arcseconds'; 'd', 'deg', 'degrees'; 'r', 'rad', 'radians'. Default is 'd' Returns ------- integral : float The integral of the power law over the specified range """ #Do the integral of a power law A*theta^-beta from lowlim to highlim A = np.float(A) beta=np.float(beta) #Make sure the A is for theta in degrees A = self.convert_A_to_degrees(A, beta, param_unit) #Convert the limits to degrees lowlim, highlim = misc.put_thetas_in_degrees([lowlim, highlim], unit=theta_unit) #First define the function to be integrated def powerlaw(theta): return A * theta ** (-beta) #Do the integral pl_int, pl_int_err= intg.quad(powerlaw, lowlim, highlim) return pl_int
def _make_theta_bins(self, min_theta, max_theta, nbins, unit='arcseconds'): """ Internally sets the edges and centers of the angular bins Parameters ---------- min_theta : float The minimum of the theta bin edges max_theta : float The maximum of the theta bin edges nbins : float The number of theta bins unit : string (optional) The unit that min and max theta are in. Default is 'arcseconds' """ #Make sure the min and max are in degrees min_theta, max_theta = misc.put_thetas_in_degrees([min_theta, max_theta], unit) #Record things in degrees self._min_theta = min_theta self._max_theta = max_theta self._nbins = nbins #Make the bins if self._logbins: if min_theta<=0: print ("make_theta_bins says: you've asked for log theta bins " "and a min of theta<=0 which makes logs unhappy. " "Changed to 1e-4") min_theta=0.0001 edges = np.logspace(np.log10(min_theta), np.log10(max_theta), nbins+1) lcenters=misc.centers(np.log10(edges)) centers=10.**lcenters else: edges=np.linspace(min_theta, max_theta, nbins+1) centers=misc.centers(edges) #Record the bins and return self._theta_bins=edges self._thetas=centers return
def set_new_bins(self, min_theta, max_theta, nbins, unit='a'): """ Redo the range and number of bins. Parameters ---------- min_theta : float The minimum of the theta bin edges max_theta : float The maximum of the theta bin edges nbins : float The number of theta bins unit : string (optional) The unit that min and max theta are in. Default is 'arcseconds' """ #Set new params and rerun if different #First, convert to degrees if we need to min_theta, max_theta = misc.put_thetas_in_degrees([min_theta, max_theta], unit) #Are they different? min_different = self._min_theta != min_theta max_different = self._max_theta != max_theta n_different = self._nbins != nbins #If so, record and rerun bins if min_different or max_different or n_different: self._min_theta = min_theta self._max_theta = max_theta self._nbins = nbins self._make_theta_bins(min_theta, max_theta, nbins, unit='d') return
def integrate_gp_times_powerlaw(self, A, beta, lowlim, highlim, theta_unit='d', param_unit='d'): """ Integrates G_p * A * theta^-beta over a range in thetas. Useful for calculating the integral constraint. Parameters ---------- A : float The amplitude of the power law for theta in units param_unit beta : float The power in the power law lowlim : float The lower limit of the theta range to integrate over highlim : float The upper limit of the theta range to integrate over param_unit : string (optional) The units of theta for which A was calculated. The options are 'a', 'arcsec', 'arcseconds'; 'd', 'deg', 'degrees'; 'r', 'rad', 'radians'. Default is 'd' theta_unit : string (optional) The units of lowlim and highlim. The options are 'a', 'arcsec', 'arcseconds'; 'd', 'deg', 'degrees'; 'r', 'rad', 'radians'. Default is 'd' Returns ------- integral : float The integral of G_p * A * theta^-beta """ #Compute the integral of G_p * A * theta^-beta from lowlim to #highlim. A and beta are for the unit specified #Pull the theta properties centers, edges = self._theta_bins.get_bins(unit='d') #Get basic info and convert everything for theta in degrees nbins_gp = len(self._Gp) lowlim, highlim = misc.put_thetas_in_degrees([lowlim, highlim], unit=theta_unit) A = self.convert_A_to_degrees(A, beta, param_unit) #If it's completely outside the G_p range, we assume that G_p is 0 #and return 0 if (lowlim >= edges[-1]) or (highlim <= edges[0]): return 0 #Figure out which bins are all the way inside [lowlim, highlim] above_lowlim = edges >= lowlim min_edge_inside_val = edges[above_lowlim][0] min_edge_inside_index = np.arange(nbins_gp+1)[above_lowlim][0] below_highlim = edges <= highlim max_edge_inside_val = edges[below_highlim][-1] max_edge_inside_index = np.arange(nbins_gp+1)[below_highlim][-1] #Make sure that the limits aren't above or below the limits where G_p is defined if lowlim < edges[0]: min_edge_inside_val = edges[0] lowlim = edges[0] min_edge_inside_index = 0 if highlim > edges[-1]: max_edge_inside_val = edges[-1] highlim = edges[-1] max_edge_inside_index = nbins_gp #Initialize the holder for the result result=0 #Start by integrating the two partial bins if we didn't happen upon #an integration limit that corresponds exactly to an edge if min_edge_inside_val != lowlim: this_gp_val = self._Gp[min_edge_inside_index-1] w_int = self.integrate_powerlaw(A, beta, lowlim, min_edge_inside_val) result += this_gp_val * w_int if max_edge_inside_val != highlim: this_gp_val = self._Gp[max_edge_inside_index] w_int = self.integrate_powerlaw(A, beta, max_edge_inside_val, highlim) result += this_gp_val * w_int #Now loop through the bins that are inside nbins_inside = max_edge_inside_index - min_edge_inside_index for i in np.arange(nbins_inside): this_index = min_edge_inside_index + i this_gp_val = self._Gp[this_index] w_int = self.integrate_powerlaw(A, beta, edges[this_index], edges[this_index+1]) result += this_gp_val * w_int return result