def make_data_tree(self): #The astroML correlation function methods want a cartesian position #instead of the angular positions- this does the conversion print "make_datatree says: Computing the BallTree for data." data = np.asarray(corr.ra_dec_to_xyz(self._ra[self._use], self._dec[self._use]), order='F').T self._data_tree = BallTree(data, leaf_size=2) return
def make_random_tree(self): #Make sure we have the random data made if (self._ra_random is None) or (self._dec_random is None): print "make_random_tree says: no random sample found. Generating one." self.generate_random_sample() #Make the tree print "make_randomtree says: Computing the BallTree for the randoms." random_data=np.asarray(corr.ra_dec_to_xyz(self._ra_random, self._dec_random), order='F').T self._random_tree = BallTree(random_data, leaf_size=2) return
def generate_rr(self, set_nbins=None, logbins=True, min_sep=0.01, force_n_randoms=None, save_to=None, n_chunks=1): #Do random-random counts over the entire field. If set_nbins is declared, #generate_rr will not go looking for the correlation functions so that the #RR counts for the IC calculation and the CF calculation can be done in parallel. #Figure out how many randoms we need. This was calculated by playing with #the number of randoms in the GOODS-S field and seeing when the RR counts converged #to the "way too many" curve. 27860 per 1.43e-5 steradians was what I settled on. #If there's a forced number, it will ignore my estimate. # Amendment 4/15- this minimum number seems to be somewhat too small for fields that # aren't as smooth as GOODS-S, so I'm multiplying it by 5. This looks ok. # Amendment 8/15- added the capability to do this in several chunks. if force_n_randoms is None: surface_density_required = 27860.*5./1.43e-5 area = self._image_mask.masked_area_solid_angle() number_needed = surface_density_required * area else: number_needed=force_n_randoms #If we're doing more than one chunk, divide the number we need into n_chunks chunks if n_chunks > 1: number_needed = np.ceil(float(number_needed)/n_chunks).astype(int) total_number = number_needed * n_chunks print "total number: ", total_number print "number per iteration: ", number_needed print "number of chunks: ", n_chunks #Range of separations to make bins over min_ra = self._ra[self._use].min() min_dec = self._dec[self._use].min() max_ra = self._ra[self._use].max() max_dec = self._dec[self._use].max() max_sep=misc.ang_sep(min_ra, min_dec, max_ra, max_dec, radians_in=False, radians_out=False) #Choose how many bins if set_nbins is None: #Get our theta bin info from the CF if we can. Error if we can't if self._theta_bins is None: raise ValueError("AngularCatalog.generate_rr says: I need" " either a set number of bins (set_nbins=N)" " or thetas from a CF to extrapolate. " " You have given me neither.") centers, edges = self._cfs[name].get_thetas(unit='degrees') nbins= np.ceil( len(centers) * 2. * max_sep/edges.max()) else: nbins=set_nbins #Make the bins rr_theta_bins = binclass.ThetaBins(min_sep, max_sep, nbins, unit='d', logbins=logbins) use_centers, use_theta_bins = rr_theta_bins.get_thetas(unit='degrees') #Do the loop G_p=np.zeros(nbins) rr_counts=np.zeros(nbins) for n_i in np.arange(n_chunks): print "doing chunk #", n_i #Remake the random sample so we're sure we have the right oversample factor self.generate_random_sample(masked=True, make_exactly=number_needed) #Code snippet shamelessly copied from astroML.correlations xyz_data = corr.ra_dec_to_xyz(self._ra_random, self._dec_random) data_R = np.asarray(xyz_data, order='F').T bins = corr.angular_dist_to_euclidean_dist(use_theta_bins) Nbins = len(bins) - 1 counts_RR = np.zeros(Nbins + 1) for i in range(Nbins + 1): counts_RR[i] = np.sum(self._random_tree.query_radius(data_R, bins[i], count_only=True)) rr = np.diff(counts_RR) #Landy and Szalay define G_p(theta) as <N_p(theta)>/(n(n-1)/2) G_p += rr/(number_needed*(number_needed-1)) rr_counts += rr print "Dividing out the theta bin sizes and number of chunks" #I divide out the bin width because just using the method #that L&S detail gives you a {G_p,i} with the property that #Sum[G_p,i]=1. This is not equivalent to Integral[G_p d(theta)]=1, #which is what they assume everywhere else. #Dividing out the bin width gives you that and lets you pretend #G_p is a continuous but chunky-looking function. G_p /= np.diff(use_theta_bins) G_p /= n_chunks self._rr_ngals=[total_number, n_chunks] self._Gp = gpclass.Gp(min_sep, max_sep, nbins, G_p, total_number, n_chunks, logbins=logbins, unit='d', RR=rr_counts) if save_to is not None: self.save_gp(save_to)