def read_data(self, level=2, sieve=None, strict=True, onlyid=False): """ bcg2.read_bcg2_numpy returns 3 numpy Record Arrays for header, halos, and particles. Header and halos are single dimensional Record Arrays containing data and halo information. Particle is a Record Array of Record Arrays for each halo id and for each particle axis. Schema for arrays can be found in halos/config.py. :level reads either header(0), halo metadata(1) or particle data (2). Should be 2. :sieve a set of ids to keep. All others discarded. If None, all data are kept. :strict[DEPRACATED]=False creates empty halo instances just with metadata, True does not create instances :onlyid=True reads only halo and particle ids, default is False for full data """ if onlyid != self.onlyid: # reset storage w/ appropriate types if different onlyid value self.onlyid = onlyid self.header = np.array([], dtype=config.DT_HEADER) self.halos = [] if not onlyid: self.h = np.array([], dtype=config.DT_GROUPS) if onlyid: self.h = np.array([], dtype=config.DT_ID) for file in self.files: header, h, particles = bgc2.read_bgc2_numpy(file, level=level, sieve=sieve, onlyid=onlyid) if level >= 0: # appending header data, level=0 self._add_header(header) if level >= 1: # appending halo group meta data, level=1 self._add_groups(h, onlyid) if level >= 2: # appending particle data, level=2 if not onlyid: for i in xrange(len(h)): self.halos.append( Halo(h[i].id, (h[i].x, h[i].y, h[i].z), particles[i])) else: for i in xrange(len(h)): self.halos.append( Halo(h[i], (None, None, None), particles[i])) # if level==1 and strict==False: # for i in xrange(len(h)): # self.halos.append(Halo(h[i].id, (h[i].x, h[i].y, h[i].z), ())) if self.verbose: print "data file(s) read"
def read_data(self, level=2, sieve=None, strict=True, onlyid=False): """ bcg2.read_bcg2_numpy returns 3 numpy Record Arrays for header, halos, and particles. Header and halos are single dimensional Record Arrays containing data and halo information. Particle is a Record Array of Record Arrays for each halo id and for each particle axis. Schema for arrays can be found in halos/config.py. :level reads either header(0), halo metadata(1) or particle data (2). Should be 2. :sieve a set of ids to keep. All others discarded. If None, all data are kept. :strict[DEPRACATED]=False creates empty halo instances just with metadata, True does not create instances :onlyid=True reads only halo and particle ids, default is False for full data """ if onlyid != self.onlyid: # reset storage w/ appropriate types if different onlyid value self.onlyid = onlyid self.header = np.array([], dtype=config.DT_HEADER) self.halos = [] if not onlyid: self.h = np.array([], dtype=config.DT_GROUPS) if onlyid: self.h = np.array([], dtype=config.DT_ID) for file in self.files: header, h, particles = bgc2.read_bgc2_numpy(file, level=level, sieve=sieve, onlyid=onlyid) if level >= 0: # appending header data, level=0 self._add_header(header) if level >= 1: # appending halo group meta data, level=1 self._add_groups(h, onlyid) if level >= 2: # appending particle data, level=2 if not onlyid: for i in xrange(len(h)): self.halos.append(Halo(h[i].id, (h[i].x, h[i].y, h[i].z), particles[i])) else: for i in xrange(len(h)): self.halos.append(Halo(h[i], (None, None, None), particles[i])) # if level==1 and strict==False: # for i in xrange(len(h)): # self.halos.append(Halo(h[i].id, (h[i].x, h[i].y, h[i].z), ())) if self.verbose: print "data file(s) read"
def main(): ''' ellipsoids.py This program reads in halo and particle data from bgc2 files and halo shape data from the Rockstar's ASCII output. Halo shape information generated from Rockstar is used to fit halos with appropriately-rotated ellipsoidal shells, and the half-mass radius is found from the ellipsoidal radius of the (n/2)th particle. The halo IDs and resulting half-mass radii are saved to disk to be added as an additional column in the master halo database. Optionally, plots are generated to demonstrate the ellipsoid halo fitting. Requires bgc2.py as a dependency. ''' #opts, args = get_args(sys.argv[1:]) #output_file, bgc2_files, ascii_files = parse_args(opts, args) ascii_files = [sys.argv[1]] bgc2_files = [sys.argv[2]] for (ascii_file, bgc2_file) in zip(ascii_files, bgc2_files): # read in halo ID, shape data, etc. from Rockstar output ascii_header, ascii_data = read_files(ascii_file, header_line=0, rec_array=True) # read in bgc2 files and make arrays of halo and particle data bgc2_header, halos, particles = bgc2.read_bgc2_numpy(bgc2_file) # find array to sort halos by number of particles to work from the biggest down halo_indices = np.argsort(halos.npart) halo_indices = halo_indices[::-1] if start_halo > 0: halo_indices = halo_indices[start_halo:] # loop through halos to work on one halo and particle list at a time for iteration, halo_index in enumerate(halo_indices): # exit loop if max iteration reached if (max_iteration > 0) and (iteration >= max_iteration): break # get data for current halo halo = np.array(halos[halo_index]).view(np.recarray) halo_particles = particles[halo_index] ascii_halo = ascii_data[ascii_data.id == halo.id] # check for id match and duplicate halos if len(ascii_halo) != 1: print "Error: found %d ASCII halo matches for halo ID %d." % (len(ascii_halo), ascii_halo.id[0]) continue # skip halos with fewer than specified number of particles if (npart_threshold > 0) and (halo.npart < npart_threshold): print "Skipping remaining halos with fewer than %d particles." % npart_threshold break # convert Mpc to kpc for halo and particle positions print "Converting units to kpc..." halo.radius = halo.radius * dist_scale for pos in halo.x, halo.y, halo.z, halo_particles.x, halo_particles.y, halo_particles.z: pos[...] = pos * dist_scale # make particle positions relative to halo center print "Making particle positions relative to halo center..." for particle_pos, halo_pos in zip([halo_particles.x, halo_particles.y, halo_particles.z], [halo.x, halo.y, halo.z]): particle_pos[...] = particle_pos - halo_pos # optionally, generate simplified fake halo data for testing/debugging if test_fake_halo: ascii_halo, halo, halo_particles = make_fake_halo(ascii_halo, halo, halo_particles) # convert particle cartesian coordinates to (spherical or ellipsoidal) radii print "Converting particle positions to spherical radii..." r_sphere = np.sqrt((halo_particles.x)**2 + (halo_particles.y)**2 + (halo_particles.z)**2) if method == 'sphere': r = r_sphere elif method == 'ellipsoid': print "Rotating eigenvalue matrix of axis ratios..." ratios = get_rotated_ratios_matrix(ascii_halo) #ratios = get_best_minor_rotation(ascii_halo.rvir, ratios, \ ratios = get_best_minor_rotation(ascii_halo.Rs, ratios, \ np.array([ascii_halo.Ax[0], ascii_halo.Ay[0], ascii_halo.Az[0]]), \ np.column_stack((halo_particles.x, halo_particles.y, halo_particles.z))) print "Converting particle positions to ellipsoidal radii..." r = get_ellipsoid_r(ratios, np.column_stack((halo_particles.x, halo_particles.y, halo_particles.z))) # find half-mass radius r_half_mass_sphere, r_half_mass_ell = get_half_mass_r(r, r_sphere) # save result to array for later output to file # !! todo -- add this # make plots if (iteration < num_halos_to_plot) and (generate_testing_plots or generate_paper_plots): print "Making plot set %d for halo ID %d..." % (iteration, halo.id) make_plots(iteration, halo, ascii_halo, halo_particles, ratios, r, r_half_mass_ell) # save results to file # !! todo -- add this print 'Finished.' return