def load_p0(snapdir, snapnum, ahf_path=None, Rvir=None, loud=1, keys_to_extract=None, calculate_qtys=True): '''Loads gas particle snapshot and adds `CoordinatesRelative`, `r`, `r_scaled`, `Vi`, `posC`, and `Rvir` columns to dictionary. `Rvir` argument must be in units of physical kpc. If `ahf_path` is passed instead, `Rvir` will be read in with units physical kpc. ''' p0 = openSnapshot(snapdir, snapnum, 0, loud=loud, keys_to_extract=keys_to_extract) p1 = openSnapshot(snapdir, snapnum, 1, loud=loud, keys_to_extract=['Coordinates', 'Masses']) if loud: print(f"Loading redshift {p0['Redshift']}") posC = halo_center_wrapper(p1)[0] if ahf_path: _, Rvir = load_AHF('', snapnum, p0['Redshift'], hubble=p0['HubbleParam'], ahf_path=ahf_path, extra_names_to_read=[]) # position relative to center p0['CoordinatesRelative'] = p0['Coordinates'] - posC if calculate_qtys: # distance from halo center p0['r'] = np.linalg.norm(p0['CoordinatesRelative'], axis=1) # distance from halo center in units of virial radius p0['r_scaled'] = p0['r'] / Rvir # volume of each particle in units (physical kpc)^3 p0['Vi'] = p0['Masses'] / p0['Density'] p0['posC'] = posC #halo center in units physical kpc p0['Rvir'] = Rvir #virial radius in units physical kpc return p0
def FIREtoVTK(snapdir, snapnum, ptype, datacols, fn_out): pdata = openSnapshot(snapdir, snapnum, ptype, loud=1) print(f"Loaded redshift {pdata['Redshift']}") x, y, z = pdata['Coordinates'][:, 0].copy(), pdata['Coordinates'][:, 1].copy( ), pdata['Coordinates'][:, 2].copy() data = {k: pdata[k].copy() for k in datacols} Points1d(x, y, z, data, fn_out)
def openSnapshot(self, load_stars=0, keys_to_extract=None, star_keys_to_extract=None): if (self.snapdict is not None and ('star_snapdict' in self.__dict__ and self.star_snapdict is not None)): return elif not self.extract_galaxy: ## isolated galaxy huh? good choice. ## don't worry, cosmological will be overwritten in openSnapshot if ## HubbleParam != 1, none of the coordinates will be offset ## and the galaxy won't be rotated or extracted snapdict = openSnapshot(self.snapdir, self.snapnum, ptype=0, cosmological=0, keys_to_extract=keys_to_extract) if load_stars: star_snapdict = openSnapshot( self.snapdir, self.snapnum, ptype=4, cosmological=0, keys_to_extract=star_keys_to_extract) ## could just be a sub-snapshot that's been pre-extracted if not star_snapdict['cosmological']: raise Exception("Need to open type 1 and type 2 parts") else: snapdict = openSnapshot(self.snapdir, self.snapnum, ptype=0, cosmological=1, keys_to_extract=keys_to_extract) if load_stars: star_snapdict = openSnapshot( self.snapdir, self.snapnum, ptype=4, cosmological=1, keys_to_extract=star_keys_to_extract) else: star_snapdict = None ## cosmological snapshot it is then... scom, rvir, vesc = load_AHF(self.snapdir, self.snapnum, snapdict['Redshift'], ahf_path=self.ahf_path) ## filter all the keys in the snapdict as necessary to extract a spherical volume ## centered on scom (the halo center), using 3*frame_half_width diskFilterDictionary( star_snapdict if load_stars else None, snapdict, radius=3 * self.frame_half_width, ## particles to mask orient_radius=3 * self. frame_half_width, ## particles to orient on (in principle could orient on inner region and want larger region) scom=scom, orient_stars=load_stars) ## bind the snapdicts self.snapdict = snapdict if load_stars: self.star_snapdict = star_snapdict
def loadData(self, com_offset=False): """Loads FIRE snapshot data using Alex Gurvich's :func:`firefly.data_reader.snapshot_utils.openSnapshot`. (reproduced from https://github.com/agurvich/abg_python) and binds it to a corresponding :class:`firefly.data_reader.ParticleGroup` instance. :param com_offset: flag to offset all coordinates by the COM of the snapshot, defaults to False :type com_offset: bool, optional """ com = None for ptype, UIname, dec_factor in list( zip(self.ptypes, self.UInames, self.decimation_factors))[::-1]: print("Loading ptype %d" % ptype) ## load each particle type's snapshot data snapdict = openSnapshot( self.snapdir, self.snapnum, int(ptype), ## ptype should be 1,2,3,4,etc... keys_to_extract=['Coordinates'] + self.fields + ['Masses'] * com_offset) if com_offset and com is None: com = np.zeros(3) ## use concentric shells to find an estimate ## for the center of mass for i in range(4): rs = np.sqrt(np.sum(snapdict['Coordinates']**2, axis=1)) rmax = np.nanmax(rs) / 10**i rmask = rs <= rmax if np.sum(rmask) == 0: break print("Centering on particles within %.2f kpc" % rmax) ## compute the center of mass of the particles within this shell this_com = (np.sum(snapdict['Coordinates'][rmask] * snapdict['Masses'][rmask][:, None], axis=0) / np.sum(snapdict['Masses'][rmask])) snapdict['Coordinates'] -= this_com ## keep track of total com com += this_com vcom = (np.sum(snapdict['Velocities'][rmask] * snapdict['Masses'][rmask][:, None], axis=0) / np.sum(snapdict['Masses'][rmask])) snapdict['Velocities'] -= vcom elif com is not None: snapdict['Coordinates'] -= com snapdict['Velocities'] -= vcom ## initialize output arrays for fields tracked_names = [] tracked_arrays = [] tracked_filter_flags = [] tracked_colormap_flags = [] for field, filterFlag, colormapFlag, magFlag, logFlag in list( zip(self.fields, self.filterFlags, self.colormapFlags, self.magFlags, self.logFlags)): ## easypeasy, just read from the snapdict if field in snapdict: arr = snapdict[field] ## if asked to compute galactocentric radius from the coordinates elif field == 'GCRadius': arr = np.sqrt(np.sum(snapdict['Coordinates']**2, axis=1)) ## elif field == ' ': ## NOTE: define custom shortcut field here else: continue ## take the log and/or magnitude if requested if magFlag: arr = np.linalg.norm(arr, axis=1) field = 'mag%s' % field if logFlag: arr = np.log10(arr) field = 'log10%s' % field ## append this field into the arrays tracked_names = np.append(tracked_names, [field], axis=0) tracked_filter_flags = np.append(tracked_filter_flags, [filterFlag], axis=0) tracked_colormap_flags = np.append(tracked_colormap_flags, [colormapFlag], axis=0) tracked_arrays.append(arr) ## initialize a particleGroup instance ## for this particle type self.particleGroups = np.append(self.particleGroups, [ ParticleGroup(UIname, snapdict['Coordinates'], tracked_names=tracked_names, tracked_arrays=tracked_arrays, decimation_factor=dec_factor, tracked_filter_flags=tracked_filter_flags, tracked_colormap_flags=tracked_colormap_flags, doSPHrad='SmoothingLength' in tracked_names) ], axis=0) ## reverse the order to match specified ptypes order self.particleGroups = self.particleGroups[::-1] ## save the filenames that were opened ## so you can re-open them yourself in that order if you need to for particleGroup in self.particleGroups: particleGroup.filenames_opened = snapdict['fnames'] ## add this particle group to the reader's settings file self.settings.attachSettings(particleGroup) return self.particleGroups
def loadData(self): """ Loads the snapshot data using Alex Gurvich's openSnapshot utility (originally from github.com/abg_python) and binds it to a ParticleGroup. Converts to physical coordinates (removes factors of h and scale factor) and will calculate the temperature and age in gyr of star particles for you (You're welcome!!). Also adds these particle groups to the reader's options file. """ for ptype, UIname, dec_factor in list( zip(self.ptypes, self.UInames, self.decimation_factors)): FireflyMessage("Loading ptype %s" % ptype) snapdict = openSnapshot( self.snapdir, self.snapnum, int(ptype), ## ptype should be PartType4,etc... keys_to_extract=['Coordinates'] + self.returnKeys) tracked_names,tracked_arrays,tracked_filter_flags,tracked_colormap_flags = [],[],[],[] for returnKey, filterFlag, colormapFlag, doMag, doLog in list( zip(self.returnKeys, self.filterFlags, self.colormapFlags, self.doMags, self.doLogs)): if returnKey in snapdict: arr = snapdict[returnKey] ## if asked to compute galactocentric radius from the coordinates elif returnKey in ['GCRadius']: arr = np.sqrt(np.sum(snapdict['Coordinates']**2, axis=1)) else: continue if doLog: arr = np.log10(arr) returnKey = 'log10%s' % returnKey elif doMag: arr = np.linalg.norm(arr, axis=1) returnKey = 'mag%s' % returnKey tracked_names = np.append(tracked_names, [returnKey], axis=0) tracked_filter_flags = np.append(tracked_filter_flags, [filterFlag], axis=0) tracked_colormap_flags = np.append(tracked_colormap_flags, [colormapFlag], axis=0) tracked_arrays.append(arr) self.particleGroups = np.append(self.particleGroups, [ ParticleGroup(UIname, snapdict['Coordinates'], tracked_names=tracked_names, tracked_arrays=tracked_arrays, decimation_factor=dec_factor, tracked_filter_flags=tracked_filter_flags, tracked_colormap_flags=tracked_colormap_flags, doSPHrad='SmoothingLength' in tracked_names) ], axis=0) ## save the filenames that were opened (so you can re-open them yourself in that order) self.particleGroups[-1].filenames_opened = snapdict['fnames'] ## add this particle group to the reader's options file self.options.addToOptions(self.particleGroups[-1]) return self.particleGroups
def load_allparticles(snapdir, snapnum, particle_types=[0, 1, 2, 4, 5], keys_to_extract={}, ptype_centering=1, Rvir=None, ahf_path=None, loud=1): '''Loads all particle data from simulation directory `snapdir` for a snapshot `snapnum`, and returns dict of dicts for each particle type. Notes: - `posC` (array of len 3; halo center in units physical kpc) is added to each particle dicts. - If either `Rvir` or `ahf_path` is defined, `r_scaled` (array; particle distances from halo center in units of Rvir) and `Rvir` (scalar; virial radius in units physical kpc) columns are added to each particle dict. - If a particle dict contains `'Masses'` and `'Density'` keys, `Vi` (array; particle volumes in units (physical kpc)^3) column is added to that particle dict. Optional parameters: `particle_types`: list of particle types to load `keys_to_extract`: dict that maps each particle type to a list of keys to read. If dict does not contain a particle type, ALL keys are read in for that particle type. `ptype_centering`: particle type used to find halo center (shrinking sphere method) `Rvir`: virial radius in units of physical kpc `ahf_path`: directory with AHF file. If defined, `Rvir` will be read in with units physical kpc (this will overwrite any value passed for `Rvir`). `loud`: verbose output if `True` ''' keys_to_extract = { **{ptype: None for ptype in particle_types}, **keys_to_extract } #load all keys for particle types for which keys were not given part = { ptype: openSnapshot(snapdir, snapnum, ptype, loud=loud, keys_to_extract=keys_to_extract[ptype]) for ptype in particle_types } if loud: print(f"Loading redshift {part[particle_types[0]]['Redshift']}") posC = halo_center_wrapper(part[ptype_centering])[0] if ahf_path: _, Rvir = load_AHF('', snapnum, part[particle_types[0]]['Redshift'], hubble=part[particle_types[0]]['HubbleParam'], ahf_path=ahf_path, extra_names_to_read=[]) for ptype, p_i in part.items(): p_i['posC'] = posC #halo center in units physical kpc if Rvir is not None: p_i['Rvir'] = Rvir #virial radius in units physical kpc # position relative to center p_i_CoordinatesRelative = p_i['Coordinates'] - posC # distance from halo center p_i_r = np.linalg.norm(p_i_CoordinatesRelative, axis=1) # distance from halo center in units of virial radius p_i['r_scaled'] = p_i_r / Rvir if ('Masses' in p_i) and ('Density' in p_i): # volume of each particle in units (physical kpc)^3 p_i['Vi'] = p_i['Masses'] / p_i['Density'] return part