@@ -148,6 +148,33 @@ def _dec(cls):
148
148
_dec (container_cls )
149
149
150
150
151
+ def get_nwbfile_version (h5py_file : h5py .File ):
152
+ """
153
+ Get the NWB version of the file if it is an NWB file.
154
+ :returns: Tuple consisting of: 1) the original version string as stored in the file and
155
+ 2) a tuple with the parsed components of the version string, consisting of integers
156
+ and strings, e.g., (2, 5, 1, beta). (None, None) will be returned if the file is not a valid NWB file
157
+ or the nwb_version is missing, e.g., in the case when no data has been written to the file yet.
158
+ """
159
+ # Get the version string for the NWB file
160
+ try :
161
+ nwb_version_string = h5py_file .attrs ['nwb_version' ]
162
+ # KeyError occurs when the file is empty (e.g., when creating a new file nothing has been written)
163
+ # or when the HDF5 file is not a valid NWB file
164
+ except KeyError :
165
+ return None , None
166
+ # Other system may have written nwb_version as a fixed-length string, resulting in a numpy.bytes_ object
167
+ # on read, rather than a variable-length string. To address this, decode the bytes if necessary.
168
+ if not isinstance (nwb_version_string , str ):
169
+ nwb_version_string = nwb_version_string .decode ()
170
+
171
+ # Parse the version string
172
+ nwb_version_parts = nwb_version_string .replace ("-" , "." ).replace ("_" , "." ).split ("." )
173
+ nwb_version = tuple ([int (i ) if i .isnumeric () else i
174
+ for i in nwb_version_parts ])
175
+ return nwb_version_string , nwb_version
176
+
177
+
151
178
# a function to register an object mapper for a container class
152
179
@docval ({"name" : "container_cls" , "type" : type ,
153
180
"doc" : "the Container class for which the given ObjectMapper class gets used" },
@@ -201,6 +228,17 @@ def get_sum(self, a, b):
201
228
202
229
class NWBHDF5IO (_HDF5IO ):
203
230
231
+ @staticmethod
232
+ def can_read (path : str ):
233
+ """Determine whether a given path is readable by this class"""
234
+ if not os .path .isfile (path ): # path is file that exists
235
+ return False
236
+ try :
237
+ with h5py .File (path , "r" ) as file : # path is HDF5 file
238
+ return get_nwbfile_version (file )[1 ][0 ] >= 2 # Major version of NWB >= 2
239
+ except IOError :
240
+ return False
241
+
204
242
@docval ({'name' : 'path' , 'type' : (str , Path ), 'doc' : 'the path to the HDF5 file' , 'default' : None },
205
243
{'name' : 'mode' , 'type' : str ,
206
244
'doc' : 'the mode to open the HDF5 file with, one of ("w", "r", "r+", "a", "w-", "x")' ,
@@ -263,23 +301,7 @@ def nwb_version(self):
263
301
and strings, e.g., (2, 5, 1, beta). (None, None) will be returned if the nwb_version
264
302
is missing, e.g., in the case when no data has been written to the file yet.
265
303
"""
266
- # Get the version string for the NWB file
267
- try :
268
- nwb_version_string = self ._file .attrs ['nwb_version' ]
269
- # KeyError occurs when the file is empty (e.g., when creating a new file nothing has been written)
270
- # or when the HDF5 file is not a valid NWB file
271
- except KeyError :
272
- return None , None
273
- # Other system may have written nwb_version as a fixed-length string, resulting in a numpy.bytes_ object
274
- # on read, rather than a variable-length string. To address this, decode the bytes if necessary.
275
- if not isinstance (nwb_version_string , str ):
276
- nwb_version_string = nwb_version_string .decode ()
277
-
278
- # Parse the version string
279
- nwb_version_parts = nwb_version_string .replace ("-" , "." ).replace ("_" , "." ).split ("." )
280
- nwb_version = tuple ([int (i ) if i .isnumeric () else i
281
- for i in nwb_version_parts ])
282
- return nwb_version_string , nwb_version
304
+ return get_nwbfile_version (self ._file )
283
305
284
306
@docval (* get_docval (_HDF5IO .read ),
285
307
{'name' : 'skip_version_check' , 'type' : bool , 'doc' : 'skip checking of NWB version' , 'default' : False })
0 commit comments