def parse_halo_catalog_internal(self): """ This parser works on the files output directly out of yt's internal halo_finder. The parse_halo_catalog_external works with an external version of FOF. Examples -------- >>> ds = load("DD0000/DD0000") >>> halo_list = FOFHaloFinder(ds) >>> halo_list.write_out("FOF/groups_00000.txt") >>> halos_COM = parse_halo_catalog_internal() """ hp = [] for line in open("%s/groups_%05i.txt" % \ (self.FOF_directory, self.output_id)): if line.startswith("# RED"): self.redshift = float(line.split("=")[1]) continue if line.strip() == "": continue # empty if line[0] == "#": continue # comment x, y, z = [float(f) for f in line.split()[7:10]] # COM x,y,z hp.append([x, y, z]) if hp != []: self.halo_positions = np.array(hp) self.halo_kdtree = KDTree(self.halo_positions) else: self.halo_positions = None self.halo_kdtree = None return hp
def parse_halo_catalog_internal(self): """ This parser works on the files output directly out of yt's internal halo_finder. The parse_halo_catalog_external works with an external version of FOF. Examples -------- >>> ds = load("DD0000/DD0000") >>> halo_list = FOFHaloFinder(ds) >>> halo_list.write_out("FOF/groups_00000.txt") >>> halos_COM = parse_halo_catalog_internal() """ hp = [] for line in open("%s/groups_%05i.txt" % \ (self.FOF_directory, self.output_id)): if line.startswith("# RED"): self.redshift = float(line.split("=")[1]) continue if line.strip() == "": continue # empty if line[0] == "#": continue # comment x,y,z = [float(f) for f in line.split()[7:10]] # COM x,y,z hp.append([x,y,z]) if hp != []: self.halo_positions = np.array(hp) self.halo_kdtree = KDTree(self.halo_positions) else: self.halo_positions = None self.halo_kdtree = None return hp
def parse_halo_catalog_external(self): hp = [] for line in open("%s/groups_%05i.dat" % \ (self.FOF_directory, self.output_id)): if line.strip() == "": continue # empty if line.startswith("# Red"): self.redshift = float(line.split("=")[1]) if line[0] == "#": continue # comment if line[0] == "d": continue # datavar x, y, z = [float(f) for f in line.split(None, 3)[:-1]] hp.append([x, y, z]) if hp != []: self.halo_positions = np.array(hp) self.halo_kdtree = KDTree(self.halo_positions) else: self.halo_positions = None self.halo_kdtree = None return hp
def parse_halo_catalog_external(self): hp = [] for line in open("%s/groups_%05i.dat" % \ (self.FOF_directory, self.output_id)): if line.strip() == "": continue # empty if line.startswith("# Red"): self.redshift = float(line.split("=")[1]) if line[0] == "#": continue # comment if line[0] == "d": continue # datavar x,y,z = [float(f) for f in line.split(None, 3)[:-1]] hp.append([x,y,z]) if hp != []: self.halo_positions = np.array(hp) self.halo_kdtree = KDTree(self.halo_positions) else: self.halo_positions = None self.halo_kdtree = None return hp
class HaloCatalog(object): r"""A catalog of halos, parsed from EnzoFOF outputs. This class will read in catalogs output by the Enzo FOF halo finder and make available their positions, radii, etc. Enzo FOF was provided starting with 2.0, and can be run either inline (with the correct options) or as a postprocessing step using the `-F` command line option. This class is mostly useful when calculating a merger tree, and when the particle IDs for members of a given halo are output as well. Parameters ---------- output_id : int This is the integer output id of the halo catalog to parse and load. cache : bool Should we store, in between accesses, the particle IDs? If set to true, the correct particle files must exist. external_FOF : bool, optional Are we building a tree from outputs generated by an external FOF program, or an FOF internal to yt? FOF_directory : str, optional Directory where FOF files are located """ cache = None def __init__(self, output_id, cache=True, external_FOF=True, FOF_directory="FOF"): self.output_id = output_id self.external_FOF = external_FOF self.redshift = 0.0 self.FOF_directory = FOF_directory self.particle_file = h5py.File("%s/particles_%05i.h5" % \ (FOF_directory, output_id), "r") if self.external_FOF: self.parse_halo_catalog_external() else: self.parse_halo_catalog_internal() if cache: self.cache = dict() #MaxLengthDict() def __del__(self): self.particle_file.close() def parse_halo_catalog_external(self): hp = [] for line in open("%s/groups_%05i.dat" % \ (self.FOF_directory, self.output_id)): if line.strip() == "": continue # empty if line.startswith("# Red"): self.redshift = float(line.split("=")[1]) if line[0] == "#": continue # comment if line[0] == "d": continue # datavar x, y, z = [float(f) for f in line.split(None, 3)[:-1]] hp.append([x, y, z]) if hp != []: self.halo_positions = np.array(hp) self.halo_kdtree = KDTree(self.halo_positions) else: self.halo_positions = None self.halo_kdtree = None return hp def parse_halo_catalog_internal(self): """ This parser works on the files output directly out of yt's internal halo_finder. The parse_halo_catalog_external works with an external version of FOF. Examples -------- >>> ds = load("DD0000/DD0000") >>> halo_list = FOFHaloFinder(ds) >>> halo_list.write_out("FOF/groups_00000.txt") >>> halos_COM = parse_halo_catalog_internal() """ hp = [] for line in open("%s/groups_%05i.txt" % \ (self.FOF_directory, self.output_id)): if line.startswith("# RED"): self.redshift = float(line.split("=")[1]) continue if line.strip() == "": continue # empty if line[0] == "#": continue # comment x, y, z = [float(f) for f in line.split()[7:10]] # COM x,y,z hp.append([x, y, z]) if hp != []: self.halo_positions = np.array(hp) self.halo_kdtree = KDTree(self.halo_positions) else: self.halo_positions = None self.halo_kdtree = None return hp def read_particle_ids(self, halo_id): if self.cache is not None: if halo_id not in self.cache: if self.external_FOF: self.cache[halo_id] = \ self.particle_file["/Halo%08i/Particle ID" % halo_id][:] else: self.cache[halo_id] = \ self.particle_file["/Halo%08i/particle_index" % halo_id][:] ids = self.cache[halo_id] else: if self.external_FOF: ids = self.particle_file["/Halo%08i/Particle ID" % halo_id][:] else: ids = self.particle_file["/Halo%08i/particle_index" % halo_id][:] return HaloParticleList(halo_id, self.halo_positions[halo_id, :], ids) def calculate_parentage_fractions(self, other_catalog, radius=0.10): parentage_fractions = {} if self.halo_positions is None or other_catalog.halo_positions is None: return parentage_fractions mylog.debug("Ball-tree query with radius %0.3e", radius) all_nearest = self.halo_kdtree.query_ball_tree( other_catalog.halo_kdtree, radius) pbar = get_pbar("Halo Mergers", self.halo_positions.shape[0]) for hid1, nearest in enumerate(all_nearest): pbar.update(hid1) parentage_fractions[hid1] = {} HPL1 = self.read_particle_ids(hid1) for hid2 in sorted(nearest): HPL2 = other_catalog.read_particle_ids(hid2) p1, p2 = HPL1.find_relative_parentage(HPL2) parentage_fractions[hid1][hid2] = (p1, p2, HPL2.number_of_particles) parentage_fractions[hid1][ "NumberOfParticles"] = HPL1.number_of_particles pbar.finish() return parentage_fractions
class HaloCatalog(object): r"""A catalog of halos, parsed from EnzoFOF outputs. This class will read in catalogs output by the Enzo FOF halo finder and make available their positions, radii, etc. Enzo FOF was provided starting with 2.0, and can be run either inline (with the correct options) or as a postprocessing step using the `-F` command line option. This class is mostly useful when calculating a merger tree, and when the particle IDs for members of a given halo are output as well. Parameters ---------- output_id : int This is the integer output id of the halo catalog to parse and load. cache : bool Should we store, in between accesses, the particle IDs? If set to true, the correct particle files must exist. external_FOF : bool, optional Are we building a tree from outputs generated by an external FOF program, or an FOF internal to yt? FOF_directory : str, optional Directory where FOF files are located """ cache = None def __init__(self, output_id, cache = True, external_FOF=True, FOF_directory="FOF"): self.output_id = output_id self.external_FOF = external_FOF self.redshift = 0.0 self.FOF_directory = FOF_directory self.particle_file = h5py.File("%s/particles_%05i.h5" % \ (FOF_directory, output_id), "r") if self.external_FOF: self.parse_halo_catalog_external() else: self.parse_halo_catalog_internal() if cache: self.cache = dict()#MaxLengthDict() def __del__(self): self.particle_file.close() def parse_halo_catalog_external(self): hp = [] for line in open("%s/groups_%05i.dat" % \ (self.FOF_directory, self.output_id)): if line.strip() == "": continue # empty if line.startswith("# Red"): self.redshift = float(line.split("=")[1]) if line[0] == "#": continue # comment if line[0] == "d": continue # datavar x,y,z = [float(f) for f in line.split(None, 3)[:-1]] hp.append([x,y,z]) if hp != []: self.halo_positions = np.array(hp) self.halo_kdtree = KDTree(self.halo_positions) else: self.halo_positions = None self.halo_kdtree = None return hp def parse_halo_catalog_internal(self): """ This parser works on the files output directly out of yt's internal halo_finder. The parse_halo_catalog_external works with an external version of FOF. Examples -------- >>> ds = load("DD0000/DD0000") >>> halo_list = FOFHaloFinder(ds) >>> halo_list.write_out("FOF/groups_00000.txt") >>> halos_COM = parse_halo_catalog_internal() """ hp = [] for line in open("%s/groups_%05i.txt" % \ (self.FOF_directory, self.output_id)): if line.startswith("# RED"): self.redshift = float(line.split("=")[1]) continue if line.strip() == "": continue # empty if line[0] == "#": continue # comment x,y,z = [float(f) for f in line.split()[7:10]] # COM x,y,z hp.append([x,y,z]) if hp != []: self.halo_positions = np.array(hp) self.halo_kdtree = KDTree(self.halo_positions) else: self.halo_positions = None self.halo_kdtree = None return hp def read_particle_ids(self, halo_id): if self.cache is not None: if halo_id not in self.cache: if self.external_FOF: self.cache[halo_id] = \ self.particle_file["/Halo%08i/Particle ID" % halo_id][:] else: self.cache[halo_id] = \ self.particle_file["/Halo%08i/particle_index" % halo_id][:] ids = self.cache[halo_id] else: if self.external_FOF: ids = self.particle_file["/Halo%08i/Particle ID" % halo_id][:] else: ids = self.particle_file["/Halo%08i/particle_index" % halo_id][:] return HaloParticleList(halo_id, self.halo_positions[halo_id,:], ids) def calculate_parentage_fractions(self, other_catalog, radius = 0.10): parentage_fractions = {} if self.halo_positions == None or other_catalog.halo_positions == None: return parentage_fractions mylog.debug("Ball-tree query with radius %0.3e", radius) all_nearest = self.halo_kdtree.query_ball_tree( other_catalog.halo_kdtree, radius) pbar = get_pbar("Halo Mergers", self.halo_positions.shape[0]) for hid1, nearest in enumerate(all_nearest): pbar.update(hid1) parentage_fractions[hid1] = {} HPL1 = self.read_particle_ids(hid1) for hid2 in sorted(nearest): HPL2 = other_catalog.read_particle_ids(hid2) p1, p2 = HPL1.find_relative_parentage(HPL2) parentage_fractions[hid1][hid2] = (p1, p2, HPL2.number_of_particles) parentage_fractions[hid1]["NumberOfParticles"] = HPL1.number_of_particles pbar.finish() return parentage_fractions