Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions tools/gadget3_to_eagleHDF.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import numpy as np
import os
import argparse
from scipy.io import FortranFile
import h5py as h5

"""
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is common to put the docstring at the very beginning of the script file rather than after the imports.

Script for converting .gadget3 binary ICs to the hdf5 format, for use with the EAGLE code.

Adapted from an IDL script by Rob Crain, by Jonathan Davies, 2021.

Usage: ics2hdf.py ics_file
* Creates an hdf5 file in the same directory as the original ICs, with the same name.
"""

def ics2hdf(ics_file):

raw_ics = os.path.abspath(ics_file)

# Do quick checks to make sure input is valid
assert os.path.isfile(raw_ics),'Input ICs file does not exist.'
assert raw_ics.split('.')[-1] == 'gadget3','Input ICs not valid. Please input GADGET3 binary ICs (.gadget3)'

out_ics = raw_ics[:-7] + 'hdf5'

print('Reading binary file '+raw_ics)

# Open the FORTRAN unformatted binary ICs
f = FortranFile(raw_ics, 'r')
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming you use the trick bellow, this'll have to be changed into

Suggested change
def ics2hdf(ics_file):
raw_ics = os.path.abspath(ics_file)
# Do quick checks to make sure input is valid
assert os.path.isfile(raw_ics),'Input ICs file does not exist.'
assert raw_ics.split('.')[-1] == 'gadget3','Input ICs not valid. Please input GADGET3 binary ICs (.gadget3)'
out_ics = raw_ics[:-7] + 'hdf5'
print('Reading binary file '+raw_ics)
# Open the FORTRAN unformatted binary ICs
f = FortranFile(raw_ics, 'r')
def ics2hdf(ics_file):
assert ics_file.name.split('.')[-1] == 'gadget3', 'Input ICs not valid. Please input GADGET3 binary ICs (.gadget3)'
out_ics = raw_ics.name[:-7] + "hdf5"
print(f"Reading binary file {raw_ics}")
# Open the FORTRAN unformatted binary ICs
f = FortranFile(ics_file, 'r')


# Read the header with the proper types
header = f.read_record('(6,)i4','(6,)f8','f8','f8','i4','i4','(6,)i4','i4','i4','f8','f8','f8','f8','i4','i4','(6,)i4','i4','i4','(56,)b')

hdict = {}
hdict['NumPart_ThisFile'] = header[0]
hdict['MassTable'] = header[1]
hdict['ExpansionFactor'] = header[2][0]
hdict['Time'] = header[2][0]
hdict['Redshift'] = header[3][0]
hdict['Flag_Sfr'] = header[4][0]
hdict['Flag_Feedback'] = header[5][0]
hdict['NumPart_Total'] = header[6]
hdict['Flag_Cooling'] = header[7][0]
hdict['NumFilesPerSnapshot'] = header[8][0]
hdict['BoxSize'] = header[9][0]
hdict['Omega0'] = header[10][0]
hdict['OmegaLambda'] = header[11][0]
hdict['HubbleParam'] = header[12][0]
hdict['Flag_StellarAge'] = header[13][0]
hdict['Flag_Metals'] = header[14][0]
hdict['NumPart_Total_HighWord'] = header[15]
hdict['Flag_DoublePrecision'] = header[17][0]

# Correction to header (from Rob Crain's original IDL script):
hdict['Flag_DoublePrecision'] = np.int32(0)

# Pointer to this dict element for later convenience
npart = hdict['NumPart_ThisFile']

# Get the particle array lengths
tot_npart = npart[1] + npart[2]

# Load the particles
pos = f.read_record('(%d,3)f4'%(tot_npart))
vel = f.read_record('(%d,3)f4'%(tot_npart))
ids = f.read_record('(%d,)i8'%(tot_npart))


# Write out the ICs in hdf5 format

print('Writing hdf5 file to '+out_ics)

out = h5.File(out_ics,'w')

print('Writing header...')

out_header = out.create_group('Header')

for key in hdict.keys():
out_header.attrs.create(key,data=hdict[key])

offset = 0
for ptype in range(len(npart)):

num = npart[ptype]
if num == 0:
continue

print('Writing PartType'+str(ptype)+'...')

out_pgroup = out.create_group('PartType%i'%(ptype))

out_pgroup.create_dataset('Coordinates',data=pos[offset:offset+num,:])
out_pgroup.create_dataset('Velocity',data=vel[offset:offset+num,:])
out_pgroup.create_dataset('ParticleIDs',data=ids[offset:offset+num])

offset += num

print('Done!')



def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
'input_ICs',
type=str,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is actually a special argument file type to handle files

Suggested change
type=str,
type=argparse.FileType(mode="br"),

Note that you need to open it in binary format for FortranFile to be happy.

help="The input .gadget3 binary ICs file"
)
args = parser.parse_args()
ics2hdf(args.input_ICs)


if __name__ == "__main__":
main()