units=U.yr, unit_convert=U.Gyr) # mHI_g extractors['mHI_g'] = extractor( keytype='particle_g', filetype='particle', dependencies=('redshift', 'rho_g', 'Habundance_g', 'proton_mass', 'SFR_g', 'fH', 'fHe', 'T_g', 'code_to_g', 'T0', 'gamma'), hpath='/PartType0/Mass', attr=None, convert=lambda vals, raw, path, fname, hpath: raw * vals.Habundance_g * h_a_powers(vals, path, fname, hpath) * atomic_frac( vals.redshift, vals.rho_g * vals.Habundance_g / (mu(vals) * vals.proton_mass), vals.T_g, vals.rho_g, vals.Habundance_g, onlyA1=True, EAGLE_corrections=True, SFR=vals.SFR_g, mu=mu(vals), gamma=vals.gamma, fH=vals.fH, T0=vals.T0, ) * vals.code_to_g, units=U.g, unit_convert=U.solMass) # -----------------------------------------------------------------------------
def __init__(self, basePath, snapNum, subID, distance=3. * U.Mpc, vpeculiar=0 * U.km / U.s, rotation={'L_coords': (60. * U.deg, 0. * U.deg)}, ra=0. * U.deg, dec=0. * U.deg): # optional dependencies for this source class from illustris_python.groupcat import loadSingle, loadHeader from illustris_python.snapshot import loadSubset, getSnapOffsets from Hdecompose.atomic_frac import atomic_frac X_H = 0.76 data_header = loadHeader(basePath, snapNum) data_sub = loadSingle(basePath, snapNum, subhaloID=subID) haloID = data_sub['SubhaloGrNr'] fields_g = ('Masses', 'Velocities', 'InternalEnergy', 'ElectronAbundance', 'Density') subset_g = getSnapOffsets(basePath, snapNum, haloID, "Group") data_g = loadSubset(basePath, snapNum, 'gas', fields=fields_g, subset=subset_g) try: data_g.update( loadSubset(basePath, snapNum, 'gas', fields=('CenterOfMass', ), subset=subset_g, sq=False)) except Exception as exc: if ('Particle type' in exc.args[0]) and \ ('does not have field' in exc.args[0]): data_g.update( loadSubset(basePath, snapNum, 'gas', fields=('Coordinates', ), subset=subset_g, sq=False)) else: raise try: data_g.update( loadSubset(basePath, snapNum, 'gas', fields=('GFM_Metals', ), subset=subset_g, mdi=(0, ), sq=False)) except Exception as exc: if ('Particle type' in exc.args[0]) and \ ('does not have field' in exc.args[0]): X_H_g = X_H else: raise else: X_H_g = data_g['GFM_Metals'] # only loaded column 0: Hydrogen a = data_header['Time'] z = data_header['Redshift'] h = data_header['HubbleParam'] xe_g = data_g['ElectronAbundance'] rho_g = data_g['Density'] * 1E10 / h * U.Msun \ * np.power(a / h * U.kpc, -3) u_g = data_g['InternalEnergy'] # unit conversion handled in T_g mu_g = 4 * C.m_p.to(U.g).value / (1 + 3 * X_H_g + 4 * X_H_g * xe_g) gamma = 5. / 3. # see http://www.tng-project.org/data/docs/faq/#gen4 T_g = (gamma - 1) * u_g / C.k_B.to(U.erg / U.K).value * 1E10 * mu_g \ * U.K m_g = data_g['Masses'] * 1E10 / h * U.Msun # cast to float64 to avoid underflow error nH_g = U.Quantity(rho_g * X_H_g / mu_g, dtype=np.float64) / C.m_p # In TNG_corrections I set f_neutral = 1 for particles with density # > .1cm^-3. Might be possible to do a bit better here, but HI & H2 # tables for TNG will be available soon anyway. fatomic_g = atomic_frac(z, nH_g, T_g, rho_g, X_H_g, onlyA1=True, TNG_corrections=True) mHI_g = m_g * X_H_g * fatomic_g try: xyz_g = data_g['CenterOfMass'] * a / h * U.kpc except KeyError: xyz_g = data_g['Coordinates'] * a / h * U.kpc vxyz_g = data_g['Velocities'] * np.sqrt(a) * U.km / U.s V_cell = data_g['Masses'] / data_g['Density'] \ * np.power(a / h * U.kpc, 3) # Voronoi cell volume r_cell = np.power(3. * V_cell / 4. / np.pi, 1. / 3.).to(U.kpc) # hsm_g has in mind a cubic spline that =0 at h, I think hsm_g = 2.5 * r_cell * find_fwhm(CubicSplineKernel().kernel) xyz_centre = data_sub['SubhaloPos'] * a / h * U.kpc xyz_g -= xyz_centre vxyz_centre = data_sub['SubhaloVel'] * np.sqrt(a) * U.km / U.s vxyz_g -= vxyz_centre super().__init__(distance=distance, vpeculiar=vpeculiar, rotation=rotation, ra=ra, dec=dec, h=h, T_g=T_g, mHI_g=mHI_g, xyz_g=xyz_g, vxyz_g=vxyz_g, hsm_g=hsm_g) return
def __init__(self, snapPath=None, snapBase=None, fof=None, sub=None, db_user=None, db_key=None, subBoxSize=50. * U.kpc, distance=3. * U.Mpc, vpeculiar=0 * U.km / U.s, rotation={'L_coords': (60. * U.deg, 0. * U.deg)}, ra=0. * U.deg, dec=0. * U.deg, print_query=False): if snapPath is None: raise ValueError('Provide snapPath argument to EAGLESource.') if snapBase is None: raise ValueError('Provide snapBase argument to EAGLESource.') if fof is None: raise ValueError('Provide fof argument to EAGLESource.') if sub is None: raise ValueError('Provide sub argument to EAGLESource.') if db_user is None: raise ValueError('Provide EAGLE database username.') # optional dependencies for this source class from eagleSqlTools import connect, execute_query from pyread_eagle import EagleSnapshot from Hdecompose.atomic_frac import atomic_frac import h5py snapNum = int(snapBase.split('_')[1]) volCode = normpath(snapPath).split(sep)[-2] query = \ 'SELECT '\ ' sh.redshift as redshift, '\ ' sh.CentreOfPotential_x as x, '\ ' sh.CentreOfPotential_y as y, '\ ' sh.CentreOfPotential_z as z, '\ ' sh.Velocity_x as vx, '\ ' sh.Velocity_y as vy, '\ ' sh.Velocity_z as vz '\ 'FROM '\ ' {:s}_SubHalo as sh '.format(volCode) + \ 'WHERE '\ ' sh.Snapnum = {:d} '.format(snapNum) + \ ' and sh.GroupNumber = {:d} '.format(fof) + \ ' and sh.SubGroupNumber = {:d}'.format(sub) if print_query: print('-----EAGLE-DB-QUERY-----') print(query) print('-------QUERY-ENDS-------') if db_key is None: print('EAGLE database') q = execute_query(connect(db_user, db_key), query) redshift = q['redshift'] a = np.power(1 + redshift, -1) cop = np.array([q[coord] for coord in 'xyz']) * a * U.Mpc vcent = np.array([q['v' + coord] for coord in 'xyz']) * U.km / U.s snapFile = join(snapPath, snapBase + '.0.hdf5') with h5py.File(snapFile, 'r') as f: h = f['RuntimePars'].attrs['HubbleParam'] subBoxSize = (subBoxSize * h / a).to(U.Mpc).value centre = (cop * h / a).to(U.Mpc).value eagle_data = EagleSnapshot(snapFile) region = np.vstack( (centre - subBoxSize, centre + subBoxSize)).T.flatten() eagle_data.select_region(*region) lbox = f['/Header'].attrs['BoxSize'] * U.Mpc / h fH = f['/RuntimePars'].attrs['InitAbundance_Hydrogen'] fHe = f['/RuntimePars'].attrs['InitAbundance_Helium'] proton_mass = f['/Constants'].attrs['PROTONMASS'] * U.g mu = 1 / (fH + .25 * fHe) gamma = f['/RuntimePars'].attrs['EOS_Jeans_GammaEffective'] T0 = f['/RuntimePars'].attrs['EOS_Jeans_TempNorm_K'] * U.K def fetch(att, ptype=0): # gas is type 0, only need gas properties tmp = eagle_data.read_dataset(ptype, att) dset = f['/PartType{:d}/{:s}'.format(ptype, att)] aexp = dset.attrs.get('aexp-scale-exponent') hexp = dset.attrs.get('h-scale-exponent') return np.array(tmp, dtype='f8') * np.power(a, aexp) \ * np.power(h, hexp) code_to_g = f['/Units'].attrs['UnitMass_in_g'] * U.g code_to_cm = f['/Units'].attrs['UnitLength_in_cm'] * U.cm code_to_cm_s = f['/Units'].attrs['UnitVelocity_in_cm_per_s'] \ * U.cm / U.s ng_g = fetch('GroupNumber') particles = dict( xyz_g=(fetch('Coordinates') * code_to_cm).to(U.kpc), vxyz_g=(fetch('Velocity') * code_to_cm_s).to(U.km / U.s), T_g=fetch('Temperature') * U.K, hsm_g=(fetch('SmoothingLength') * code_to_cm).to(U.kpc) * find_fwhm(WendlandC2Kernel().kernel)) rho_g = fetch('Density') * U.g * U.cm**-3 SFR_g = fetch('StarFormationRate') Habundance_g = fetch('ElementAbundance/Hydrogen') particles['mHI_g'] = (atomic_frac(redshift, rho_g * Habundance_g / (mu * proton_mass), particles['T_g'], rho_g, Habundance_g, onlyA1=True, EAGLE_corrections=True, SFR=SFR_g, mu=mu, gamma=gamma, fH=fH, T0=T0) * code_to_g).to(U.solMass) mask = ng_g == fof for k, v in particles.items(): particles[k] = v[mask] particles['xyz_g'] -= cop particles['xyz_g'][particles['xyz_g'] > lbox / 2.] -= lbox.to(U.kpc) particles['xyz_g'][particles['xyz_g'] < -lbox / 2.] += lbox.to(U.kpc) particles['vxyz_g'] -= vcent super().__init__(distance=distance, vpeculiar=vpeculiar, rotation=rotation, ra=ra, dec=dec, h=h, **particles) return
'T_g', 'code_to_g', 'T0', 'gamma' ), hpath='/PartType0/Masses', attr=None, convert=lambda vals, raw, path, fname, hpath: raw * vals.Habundance_g * h_a_powers(vals, path, fname, hpath) * atomic_frac( vals.redshift, vals.rho_g * vals.Habundance_g / (mu(vals) * vals.proton_mass), vals.T_g, vals.rho_g, vals.Habundance_g, onlyA1=True, EAGLE_corrections=True, SFR=vals.SFR_g, mu=mu(vals), gamma=vals.gamma, fH=vals.fH, T0=vals.T0, ) * vals.code_to_g, units=U.g, unit_convert=U.solMass ) # -----------------------------------------------------------------------------------------------------