Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
prjemian committed Mar 26, 2016
2 parents 6353a3e + 140298f commit bbef494
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Change History
Production
**********

:2016.0216.0: `issue #36 <https://github.com/prjemian/spec2nexus/issues/36>`_: identify NIAC2014-compliant NeXus files
:2016.0210.0: bugfix: eznx.makeGroup() now correctly sets attributes on new group + documentation for NIAC2014 attributes
:2016.0204.0: (`#45 <https://github.com/prjemian/spec2nexus/issues/45>`_) handle case when no data points in scan ,
(`#46 <https://github.com/prjemian/spec2nexus/issues/46>`_) spec.getScan() ensures argument is used as ``str``
Expand Down
2 changes: 2 additions & 0 deletions src/spec2nexus/dev_h5toText.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
# sys.argv.append('6')
# sys.argv.append(os.path.join(testpath, 'data', 'writer_1_3.h5'))
sys.argv.append(os.path.join(testpath, 'data', 'Data_Q.h5'))
# sys.argv.append(os.path.join(testpath, 'data', 'compression.h5'))
# sys.argv.append(os.path.join(testpath, 'data', 'writer_1_3.h5'))
# sys.argv.append(os.path.join(os.environ['HOMEPATH'], 'Desktop', 'thau_1.nxs.hdf'))


Expand Down
118 changes: 118 additions & 0 deletions src/spec2nexus/h5toText.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,113 @@ def isNeXusFile(filename):
'''
is `filename` is a NeXus HDF5 file?
Tests if ``filename`` adheres to either
"Associating plottable data using attributes applied to the **NXdata** group"
(needs URL - NeXus manual is not yet ready to provide it)
or
"Associating plottable data by name using the ``axes`` attribute"
(needs URL - again, from NeXus manual)
or
"Associating plottable data by dimension number using the ``axis`` attribute"
(needs URL - again, from NeXus manual)
'''
if not os.path.exists(filename):
return None
m1 = isNeXusFile_ByNXdataAttrs
m2 = isNeXusFile_ByAxes
m3 = isNeXusFile_ByAxisAttr
# shorter method names to make next line readable
return m1(filename) or m2(filename) or m3(filename)


def _get_group_niac2014(parent, attribute, nxclass_name):
'''
supports the NIAC2014method:
Search parent for the group named by the attribute
(with fallback if the attribute is not defined to picking *any*
group that has the same nxclass_name).
'''
group = parent.attrs.get(attribute, None)
if group is None:
# Expect that some data files will not write these attributes.
# Find *any* HDF5 group that has its @NX_class attribute set to ``nxclass_name``.
for node0 in parent.values():
# TODO: verify
# Does this search ALL POSSIBLE {nxclass_name} groups for
# at least one compliance or just the first one it finds?
if isNeXusGroup(node0, nxclass_name):
group = node0
break
if group is None:
return False
if not isNeXusGroup(group, nxclass_name):
return False
return group

def isNeXusFile_ByNXdataAttrs(filename):
'''
is `filename` is a NeXus HDF5 file?
This is the "NIAC2014" method.
In short, verify these NeXus classpaths exist::
/@default={entry_group}
/{entry_group}:NXentry/@default={data_group}
/{entry_group}:NXentry/{data_group}:NXdata
/{entry_group}:NXentry/{data_group}:NXdata/@signal={signal_dataset}
/{entry_group}:NXentry/{data_group}:NXdata/{signal_dataset}
/{entry_group}:NXentry/{data_group}:NXdata/@axes=["{axes_dataset1}", ...]
/{entry_group}:NXentry/{data_group}:NXdata/@{axes_dataset1}_indices=int[]
...
where curly braces (``{`` and ``}``) denote that the enclosed name
is defined in the data file.
'''
try:
f = h5py.File(filename, 'r')
if not isHdf5File(f):
f.close()
return False

# find the NXentry group
nxentry = _get_group_niac2014(f, 'default', 'NXentry')
if nxentry is None:
return False

# find the NXdata group
nxdata = _get_group_niac2014(nxentry, 'default', 'NXdata')
if nxdata is None:
return False # no compliant NXdata group identified

# find the signal dataset
signal = nxdata.attrs.get('signal', None)
if signal is None:
return False # no signal attribute
if isinstance(signal, numpy.ndarray):
signal = signal[0]
if signal not in nxdata:
return False # no signal dataset
ds_signal = nxdata[signal]
if not isNeXusDataset(ds_signal):
return False # that HDF5 object is not a NeXus dataset

# Tests for nxdata.attrs['axes'] and nxdata.attrs['{axisname}_indices']
# cannot be robust since we expect some clients simply will not write these.

f.close()
return True
except Exception, _exc:
pass # ignore any Exceptions, they mean that result stays "False"
return False


def isNeXusFile_ByAxes(filename):
'''
is `filename` is a NeXus HDF5 file?
This has been, to date, the most common method in NeXus to define the default plot.
In short, verify this NeXus classpath exists::
/NXentry/NXdata/dataset/@signal=1
Expand Down Expand Up @@ -283,6 +390,17 @@ def isNeXusFile(filename):
return False


def isNeXusFile_ByAxisAttr(filename):
'''
is `filename` is a NeXus HDF5 file?
This is the oldest method in NeXus to define the default plot.
NOTE: **Not implemented yet!**
'''
return False # TODO: implement this method


def isNeXusGroup(obj, NXtype):
'''is `obj` a NeXus group?'''
nxclass = None
Expand Down

0 comments on commit bbef494

Please sign in to comment.