Source code for tools21cm.xfrac_file

from . import const
import numpy as np
import os
from . import density_file as df
from .helper_functions import print_msg 

[docs] class XfracFile: ''' A C2Ray xfrac file. Use the read_from_file method to load an xfrac file, or pass the filename to the constructor. Attributes: xi (numpy array): the ionized fraction z (float): the redshift of the file (-1 if it couldn't be determined from the file name) ''' def __init__(self, filename = None, old_format=False, neutral=False, binary_format=False): ''' Initialize the file. If filename is given, read data. Otherwise, do nothing. Parameters: filename = None (string): the file to read from. old_format = False (bool): whether to use the old-style file format. Returns: Nothing ''' if filename: self.read_from_file(filename, old_format, neutral=neutral, binary_format=binary_format)
[docs] def read_from_file(self, filename, old_format=False, neutral=False, binary_format=False): ''' Read data from file. Parameters: filename (string): the file to read from. old_format = False (bool): whether to use the old-style (32 bits) file format. neutral = False (bool): whether the content is the neutral or ionized fraction binary_format = False (bool): whether the file is in Fortran unformatted or binary (no record separators) format Returns: Nothing ''' print_msg('Reading xfrac file:%s...' % filename) self.filename = filename f = open(filename, 'rb') if binary_format: temp_mesh = np.fromfile(f, count=3, dtype='int32') self.mesh_x, self.mesh_y, self.mesh_z = temp_mesh #[0:2] else: temp_mesh = np.fromfile(f, count=6, dtype='int32') self.mesh_x, self.mesh_y, self.mesh_z = temp_mesh[1:4] if old_format: self.xi = np.fromfile(f, dtype='float32') else: self.xi = np.fromfile(f, dtype='float64') self.xi = self.xi.reshape((self.mesh_x, self.mesh_y, self.mesh_z), order='F') if neutral: self.xi = 1.0-self.xi f.close() print_msg('...done') #Store the redshift from the filename import os.path try: name = os.path.split(filename)[1] self.z = float(name.split('_')[1][:-4]) except: print_msg('Could not determine redshift from file name') self.z = -1
[docs] def write_to_file(self, filename, xi, old_format=False, neutral=False, binary_format=False): ''' Write data to file. Parameters: filename (string): the file to write to. xi (numpy array): the ionized fraction old_format = False (bool): whether to use the old-style (32 bits) file format. neutral = False (bool): whether to write the neutral or ionized fraction binary_format = False (bool): whether the file is in Fortran unformatted or binary (no record separators) format Returns: Nothing ''' self.xi = xi print_msg('Writing xfrac file:%s...' % filename) self.filename = filename f = open(filename, 'wb') # Determine data type for xi based on old_format dtype_xi = 'float32' if old_format else 'float64' # Determine mesh dimensions # If xi is already a numpy array, its shape will give the mesh dimensions if self.xi.shape: self.mesh_x, self.mesh_y, self.mesh_z = self.xi.shape else: print_msg("Warning: xi attribute is not shaped. Assuming 0,0,0 for mesh dimensions.") self.mesh_x, self.mesh_y, self.mesh_z = 0, 0, 0 # Fallback # Prepare mesh dimensions for writing if binary_format: temp_mesh = np.array([self.mesh_x, self.mesh_y, self.mesh_z], dtype='int32') temp_mesh.tofile(f) else: # For Fortran unformatted, usually there are record markers. # In C2Ray's old format, it seems to write 6 int32 values where [1:4] are the mesh. # We'll replicate this if possible, otherwise use a placeholder. # The original read_from_file reads 6, and uses 1:4. Let's write the same. # Assuming the other values are not critical or can be default (e.g., 0). temp_mesh = np.zeros(6, dtype='int32') temp_mesh[1] = self.mesh_x temp_mesh[2] = self.mesh_y temp_mesh[3] = self.mesh_z temp_mesh.tofile(f) # Prepare data for writing (handle neutral option) data_to_write = self.xi if neutral: data_to_write = 1.0 - self.xi # Reshape to 1D and write data_to_write.astype(dtype_xi).T.flatten().tofile(f) # Transpose and flatten with Fortran order f.close() print_msg('...done')