#/*##########################################################################
# Copyright (C) 2004-2014 V.A. Sole, European Synchrotron Radiation Facility
#
# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
# the ESRF by the Software group.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
#############################################################################*/
__author__ = "V.A. Sole - ESRF Data Analysis"
__contact__ = "sole@esrf.fr"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
import sys
from PyMca5.PyMcaGui import PyMcaQt as qt
safe_str = qt.safe_str
import copy
import posixpath
[docs]class HDFInfoCustomEvent(qt.QEvent):
def __init__(self, ddict):
if ddict is None:
ddict = {}
self.dict = ddict
qt.QEvent.__init__(self, qt.QEvent.User)
[docs]class VerticalSpacer(qt.QWidget):
def __init__(self, *args):
qt.QWidget.__init__(self, *args)
self.setSizePolicy(qt.QSizePolicy(qt.QSizePolicy.Fixed,
qt.QSizePolicy.Expanding))
[docs]class SimpleInfoGroupBox(qt.QGroupBox):
def __init__(self, parent, title=None, keys=None):
qt.QGroupBox.__init__(self, parent)
self.mainLayout = qt.QGridLayout(self)
self.mainLayout.setContentsMargins(0, 0, 0, 0)
self.mainLayout.setSpacing(2)
if title is not None:
self.setTitle(title)
if keys is None:
keys = []
self.keyList = keys
self.keyDict = {}
if len(self.keyList):
self._build()
def _build(self):
i = 0
for key in self.keyList:
label = qt.QLabel(self)
label.setText(key)
line = qt.QLineEdit(self)
line.setReadOnly(True)
self.mainLayout.addWidget(label, i, 0)
self.mainLayout.addWidget(line, i, 1)
self.keyDict[key] = (label, line)
i += 1
[docs] def setInfoDict(self, ddict):
if not len(self.keyList):
self.keyList = ddict.keys()
self._build()
self._fillInfo(ddict)
def _fillInfo(self, ddict0):
ddict = self._getMappedDict(ddict0)
actualKeys = list(ddict.keys())
dictKeys = []
for key in actualKeys:
l = key.lower()
if l not in dictKeys:
dictKeys.append(l)
for key in self.keyList:
l = key.lower()
if l in dictKeys:
self._fillKey(key,
ddict[actualKeys[dictKeys.index(l)]])
def _getMappedDict(self, ddict):
#Default implementation returns a copy of the input dictionnary
return copy.deepcopy(ddict)
def _fillKey(self, key, value):
#This can be overwritten
if type(value) == type(""):
self.keyDict[key][1].setText(value)
else:
self.keyDict[key][1].setText(safe_str(value))
[docs]class NameGroupBox(SimpleInfoGroupBox):
def __init__(self, parent, title=None, keys=[]):
SimpleInfoGroupBox.__init__(self, parent, title=title, keys=["Name", "Path", "Type"])
[docs] def setInfoDict(self, ddict):
key = "Value"
if key in ddict.keys():
if key not in self.keyList:
self.keyList.append(key)
label = qt.QLabel(self)
label.setText(key)
line = qt.QLineEdit(self)
line.setReadOnly(True)
i = self.keyList.index(key)
self.mainLayout.addWidget(label, i, 0)
self.mainLayout.addWidget(line, i, 1)
self.keyDict[key] = (label, line)
if 'Path' in ddict:
if ddict['Path'] == "/":
if 'Name' in ddict:
self.keyDict['Name'][0].setText("File")
SimpleInfoGroupBox.setInfoDict(self, ddict)
[docs]class DimensionGroupBox(SimpleInfoGroupBox):
def __init__(self, parent, title=None, keys=None):
keys = ["No. of Dimension(s)",
"Dimension Size(s)",
"Data Type"]
SimpleInfoGroupBox.__init__(self, parent, title=title, keys=keys)
def _getMappedDict(self, ddict):
return copy.deepcopy(ddict)
[docs]class MembersGroupBox(qt.QGroupBox):
def __init__(self, parent):
qt.QGroupBox.__init__(self, parent)
self.mainLayout = qt.QVBoxLayout(self)
self.mainLayout.setContentsMargins(0, 0, 0, 0)
self.mainLayout.setSpacing(2)
self.setTitle("Group Members")
self.label = qt.QLabel(self)
self.label.setText("Number of members: 0")
self.table = qt.QTableWidget(self)
#labels = ["Name", "Type", "Shape", "Value"]
labels = ["Name", "Value", "Type"]
nlabels = len(labels)
self.table.setColumnCount(nlabels)
rheight = self.table.horizontalHeader().sizeHint().height()
self.table.setMinimumHeight(12*rheight)
self.table.setMaximumHeight(20*rheight)
for i in range(nlabels):
item = self.table.horizontalHeaderItem(i)
if item is None:
item = qt.QTableWidgetItem(labels[i],
qt.QTableWidgetItem.Type)
item.setText(labels[i])
self.table.setHorizontalHeaderItem(i, item)
self._tableLabels = labels
self.mainLayout.addWidget(self.label)
self.mainLayout.addWidget(self.table)
[docs] def setInfoDict(self, ddict):
keylist = ddict.keys()
if "members" not in keylist:
self.hide()
return
keylist = ddict['members']
self.label.setText("Number of members: %d" % len(keylist))
nrows = len(keylist)
if not nrows:
self.table.setRowCount(nrows)
self.hide()
return
self.table.setRowCount(nrows)
if ddict['Path'] != '/':
#this could distroy ordering ...
keylist.sort()
row = 0
for key in keylist:
item = self.table.item(row, 0)
if item is None:
item = qt.QTableWidgetItem(key, qt.QTableWidgetItem.Type)
item.setFlags(qt.Qt.ItemIsSelectable|
qt.Qt.ItemIsEnabled)
self.table.setItem(row, 0, item)
else:
item.setText(key)
for label in self._tableLabels[1:]:
if not label in ddict[key]:
continue
col = self._tableLabels.index(label)
info = ddict[key][label]
item = self.table.item(row, col)
if item is None:
item = qt.QTableWidgetItem(info, qt.QTableWidgetItem.Type)
item.setFlags(qt.Qt.ItemIsSelectable|
qt.Qt.ItemIsEnabled)
self.table.setItem(row, col, item)
else:
item.setText(info)
row += 1
for i in range(self.table.columnCount()):
self.table.resizeColumnToContents(i)
[docs]def getInfo(hdf5File, node):
"""
hdf5File is and HDF5 file-like insance
node is the posix path to the node
"""
data = hdf5File[node]
ddict = {}
ddict['general'] = {}
ddict['attributes'] = {}
externalFile = False
if hasattr(hdf5File, "file"):
if hasattr(hdf5File.file, "filename"):
if data.file.filename != hdf5File.file.filename:
externalFile = True
if externalFile:
path = node
if path != "/":
name = posixpath.basename(node)
else:
name = hdf5File.file.filename
if data.name != node:
path += " external link to %s" % data.name
path += " in %s" % safe_str(data.file.filename)
name += " external link to %s" % data.name
name += " in %s" % safe_str(data.file.filename)
else:
name = data.name
ddict['general']['Path'] = path
ddict['general']['Name'] = name
else:
ddict['general']['Path'] = data.name
if ddict['general']['Path'] != "/":
ddict['general']['Name'] = posixpath.basename(data.name)
else:
ddict['general']['Name'] = data.file.filename
ddict['general']['Type'] = safe_str(data)
if hasattr(data, 'dtype'):
if ("%s" % data.dtype).startswith("|S") or\
("%s" % data.dtype).startswith("|O"):
if hasattr(data, 'shape'):
shape = data.shape
if not len(shape):
ddict['general']['Value'] = "%s" % data.value
elif shape[0] == 1:
ddict['general']['Value'] = "%s" % data.value[0]
else:
print("Warning: Node %s not fully understood" % node)
ddict['general']['Value'] = "%s" % data.value
elif hasattr(data, 'shape'):
shape = data.shape
if len(shape) == 1:
if shape[0] == 1:
ddict['general']['Value'] = "%s" % data.value[0]
elif len(shape) == 0:
ddict['general']['Value'] = "%s" % data.value
if hasattr(data, "keys"):
ddict['general']['members'] = list(data.keys())
elif hasattr(data, "listnames"):
ddict['general']['members'] = list(data.listnames())
else:
ddict['general']['members'] = []
for member in list(ddict['general']['members']):
ddict['general'][member] = {}
ddict['general'][member]['Name'] = safe_str(member)
if ddict['general']['Path'] == "/":
ddict['general'][member]['Type'] = safe_str(hdf5File[node+"/"+member])
continue
memberObject = hdf5File[node][member]
if hasattr(memberObject, 'shape'):
ddict['general'][member]['Type'] = safe_str(hdf5File[node+"/"+member])
dtype = memberObject.dtype
if hasattr(memberObject, 'shape'):
shape = memberObject.shape
if ("%s" % dtype).startswith("|S") or\
("%s" % dtype).startswith("|O"):
if not len(shape):
ddict['general'][member]['Shape'] = ""
ddict['general'][member]['Value'] = "%s" % memberObject.value
else:
ddict['general'][member]['Shape'] = shape[0]
ddict['general'][member]['Value'] = "%s" % memberObject.value[0]
continue
if not len(shape):
ddict['general'][member]['Shape'] = ""
ddict['general'][member]['Value'] = "%s" % memberObject.value
continue
ddict['general'][member]['Shape'] = "%d" % shape[0]
for i in range(1, len(shape)):
ddict['general'][member]['Shape'] += " x %d" % shape[i]
if len(shape) == 1:
if shape[0] == 1:
ddict['general'][member]['Value'] = "%s" % memberObject.value[0]
else:
ddict['general'][member]['Value'] = "%s, ..., %s" % (memberObject.value[0],
memberObject.value[-1])
elif len(shape) == 2:
ddict['general'][member]['Value'] = "%s, ..., %s" % (memberObject.value[0],
memberObject.value[-1])
else:
pass
else:
ddict['general'][member]['Type'] = safe_str(hdf5File[node+"/"+member])
if hasattr(data.attrs, "keys"):
ddict['attributes']['names'] = data.attrs.keys()
elif hasattr(data.attrs, "listnames"):
ddict['attributes']['names'] = data.attrs.listnames()
else:
ddict['attributes']['names'] = []
if sys.version >= '3.0.0':
ddict['attributes']['names'] = list(ddict['attributes']['names'])
ddict['attributes']['names'].sort()
for key in ddict['attributes']['names']:
ddict['attributes'][key] = {}
Name = key
Value = data.attrs[key]
Type = safe_str(type(Value))
if type(Value) == type(""):
Size = "%d" % len(Value)
elif type(Value) in [type(1), type(0.0)]:
Value = safe_str(Value)
Size = "1"
else:
Value = safe_str(Value)
Size = "Unknown"
ddict['attributes'][key]['Name'] = Name
ddict['attributes'][key]['Value'] = Value
ddict['attributes'][key]['Type'] = Type
ddict['attributes'][key]['Size'] = Size
return ddict
if __name__ == "__main__":
if len(sys.argv) < 3:
print("Usage:")
print("python HDF5Info.py hdf5File node")
sys.exit(0)
import h5py
h=h5py.File(sys.argv[1])
node = sys.argv[2]
info = getInfo(h, node)
app = qt.QApplication([])
w = HDF5InfoWidget()
w.setInfoDict(info)
w.show()
sys.exit(app.exec_())