# Copyright (c) 2018, Matthias Frey, Paul Scherrer Institut, Villigen PSI, Switzerland
# All rights reserved
#
# Implemented as part of the PhD thesis
# "Precise Simulations of Multibunches in High Intensity Cyclotrons"
#
# This file is part of pyOPALTools.
#
# pyOPALTools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# You should have received a copy of the GNU General Public License
# along with pyOPALTools. If not, see <https://www.gnu.org/licenses/>.
import h5py
import numpy as np
from .H5Error import H5ParseError, H5DatasetError, H5OverflowError
from .BaseParser import BaseParser
[docs]class H5Parser(BaseParser):
[docs] def __init__(self):
"""Constructor.
"""
self.__filename = ''
self.__h5f = ''
self.__nsteps = 0
[docs] def parse(self, fname, info = False):
"""Read a H5 file generated by OPAL
Parameters
----------
fname : str
H5 filename
info : bool, optional
Print H5 file summary
"""
self.__filename = fname
self.__h5f = h5py.File(fname, 'r')
self.__step_prefix = 'Step#'
if self.__h5f:
self.__nsteps = len(self.__h5f.keys())
if 'Attachment' in self.__h5f.keys():
self.__nsteps -= 1
if info:
print ( self.__str__() )
else:
raise H5ParseError("Cannot read '" + fname + "'")
[docs] def clear(self):
"""Clear data.
"""
self.close()
[docs] def close(self):
"""Closes h5 file.
"""
if self.__h5f:
del self.__h5f
self.__h5f = ''
self.__filename = ''
self.__nsteps = 0
[docs] def getNSteps(self):
"""Number of steps in file.
Returns
-------
int
The number of steps
"""
return self.__nsteps
[docs] def getStepAttributes(self, step = 0):
"""Attributes names of a step.
Parameters
----------
step : int, optional
Steps of file
Returns
-------
list [str]
All attribute names of a step
"""
self._check_step(step)
path = self.__step_prefix + str(step)
return list(self.__h5f[path].attrs.keys())
[docs] def getStepDatasets(self, step = 0):
"""All step dataset names.
Parameters
----------
step : int, optional
Steps of file
Returns
-------
list [str]
All attribute names of a step
"""
self._check_step(step)
path = self.__step_prefix + str(step)
return list(self.__h5f[path].keys())
[docs] def getStepDataset(self, dsetName, step=0):
"""Obtain the data of a step.
Parameters
----------
dsetName : str
Name of dataset
step : int, optional
Steps of file
Returns
-------
numpy.ndarray, (N,)
Array of a dataset of a step (check with getStepDatasets())
"""
self._check_step(step)
if not dsetName in self.getStepDatasets(step):
raise H5DatasetError("'" + dsetName + "' is not a dataset of this step")
data = []
path = self.__step_prefix + str(step) + '/' + dsetName
return np.asarray(self.__h5f[path])
[docs] def getStepAttribute(self, attrName, step=0):
"""Obtain the attribute data of a step.
Parameters
----------
attrName : str
Name of attribute
step : int, optional
Steps of file
"""
self._check_step(step)
data = []
path = self.__step_prefix + str(step)
data = self.__h5f[path].attrs[attrName]
return data[:]
[docs] def getGlobalAttributes(self):
"""All attributes of root.
Returns
-------
list
A list of strings of all root attributes
"""
return list(self.__h5f.attrs.keys())
[docs] def getGlobalAttribute(self, attrName):
"""Obtain value of global attribute.
Parameters
----------
attrName : str
Name of global attribute
Returns
-------
str
Value as string.
"""
value = self.__h5f.attrs[attrName]
# 7. March 2018
# https://stackoverflow.com/questions/37016946/remove-b-character-do-in-front-of-a-string-literal-in-python-3
return value.decode("utf-8")
[docs] def _check_step(self, step):
if step > self.__nsteps - 1:
raise H5OverflowError('Only ' + str(self.__nsteps - 1) + ' steps.')
elif step < 0:
raise H5OverflowError("Negative step number: '" + str(step) + "'")
def __str__(self):
"""Print file summary.
Returns
-------
str
A summary of the file.
"""
info = '\nNumber of steps: ' + str(self.__nsteps) + '\n\n'
info += 'Global attributes:\n'
info += '------------------\n'
for i, attr in enumerate(sorted(self.getGlobalAttributes())):
info += ' {:20}'.format(attr)
if (i+1) % 5 == 0:
info += '\n'
info += '\n\nStep attributes:\n'
info += '----------------\n'
for i, attr in enumerate(sorted(self.getStepAttributes())):
info += ' {:20}'.format(attr)
if (i+1) % 5 == 0:
info += '\n'
info += '\n\nStep datasets:\n'
info += '--------------\n'
for i, attr, in enumerate(sorted(self.getStepDatasets())):
info += ' {:20}'.format(attr)
if (i+1) % 5 == 0:
info += '\n'
return info + '\n'