Source code for yt.utilities.file_handler
from contextlib import contextmanager
from yt._maintenance.deprecation import issue_deprecation_warning
from yt.utilities.on_demand_imports import NotAModule, _h5py as h5py
[docs]
def valid_hdf5_signature(fn: str, /) -> bool:
signature = b"\x89HDF\r\n\x1a\n"
try:
with open(fn, "rb") as f:
header = f.read(8)
return header == signature
except Exception:
return False
[docs]
def warn_h5py(fn):
issue_deprecation_warning(
"warn_h5py is not used within yt any more and is deprecated.", since="4.3"
)
needs_h5py = valid_hdf5_signature(fn)
if needs_h5py and isinstance(h5py.File, NotAModule):
raise RuntimeError(
"This appears to be an HDF5 file, but h5py is not installed."
)
[docs]
class HDF5FileHandler:
handle = None
def __init__(self, filename):
self.handle = h5py.File(filename, mode="r")
def __getitem__(self, key):
return self.handle[key]
def __contains__(self, item):
return item in self.handle
def __len__(self):
return len(self.handle)
@property
def attrs(self):
return self.handle.attrs
[docs]
def keys(self):
return list(self.handle.keys())
[docs]
def items(self):
return list(self.handle.items())
[docs]
def close(self):
if self.handle is not None:
self.handle.close()
[docs]
class FITSFileHandler(HDF5FileHandler):
def __init__(self, filename):
from yt.utilities.on_demand_imports import _astropy
if isinstance(filename, _astropy.pyfits.hdu.image._ImageBaseHDU):
self.handle = _astropy.pyfits.HDUList(filename)
elif isinstance(filename, _astropy.pyfits.HDUList):
self.handle = filename
else:
self.handle = _astropy.pyfits.open(
filename, memmap=True, do_not_scale_image_data=True, ignore_blank=True
)
self._fits_files = []
def __del__(self):
for f in self._fits_files:
f.close()
del self._fits_files
del self.handle
self.handle = None
[docs]
def close(self):
self.handle.close()
[docs]
def valid_netcdf_signature(fn: str, /) -> bool:
try:
with open(fn, "rb") as f:
header = f.read(4)
except Exception:
return False
else:
return header in (b"CDF\x01", b"CDF\x02") or (
fn.endswith((".nc", ".nc4")) and valid_hdf5_signature(fn)
)
[docs]
def valid_netcdf_classic_signature(filename):
issue_deprecation_warning(
"valid_netcdf_classic_signature is not used within yt any more and is deprecated.",
since="4.3",
)
signature_v1 = b"CDF\x01"
signature_v2 = b"CDF\x02"
try:
with open(filename, "rb") as f:
header = f.read(4)
return header == signature_v1 or header == signature_v2
except Exception:
return False
[docs]
def warn_netcdf(fn):
# There are a few variants of the netCDF format.
issue_deprecation_warning(
"warn_netcdf is not used within yt any more and is deprecated.", since="4.3"
)
classic = valid_netcdf_classic_signature(fn)
# NetCDF-4 Classic files are HDF5 files constrained to the Classic
# data model used by netCDF-3.
netcdf4_classic = valid_hdf5_signature(fn) and fn.endswith((".nc", ".nc4"))
needs_netcdf = classic or netcdf4_classic
from yt.utilities.on_demand_imports import _netCDF4 as netCDF4
if needs_netcdf and isinstance(netCDF4.Dataset, NotAModule):
raise RuntimeError(
"This appears to be a netCDF file, but the "
"python bindings for netCDF4 are not installed."
)
[docs]
class NetCDF4FileHandler:
def __init__(self, filename):
self.filename = filename
[docs]
@contextmanager
def open_ds(self, **kwargs):
from yt.utilities.on_demand_imports import _netCDF4 as netCDF4
ds = netCDF4.Dataset(self.filename, mode="r", **kwargs)
yield ds
ds.close()