@@ -150,22 +150,51 @@ def recursive_replace(raw_metadata, context):
150150 def channels (self ):
151151 instrument_info = {"vendor" : "Zygo" }
152152
153- def find_key (d , target_key ):
154- if target_key in d :
155- return d [target_key ]
156- for v in d .values ():
157- if isinstance (v , dict ):
158- res = find_key (v , target_key )
159- if res is not None :
160- return res
161- return None
162-
163- name = find_key (self ._metadata , "Instrument" )
164- if name is not None :
165- instrument_info ["name" ] = str (name )
166- serial = find_key (self ._metadata , "System Serial Number" )
167- if serial is not None :
168- instrument_info ["serial" ] = str (serial )
153+ fobj = self ._fobj
154+ if callable (fobj ):
155+ fobj = fobj ()
156+ with h5py .File (fobj , 'r' ) as h5 :
157+ def find_attr (obj , target_key ):
158+ for key , val in obj .attrs .items ():
159+ if key .endswith (target_key ):
160+ if isinstance (val , np .ndarray ) and len (val ) > 0 :
161+ return val [0 ]
162+ return val
163+ return None
164+
165+ # Search in the attributes of the group containing the surface data
166+ # or any parent group.
167+ node = h5 [self ._surface_path ]
168+ serial = None
169+ instrument_name = None
170+ while node .name != '/' :
171+ serial = find_attr (node , 'System Serial Number' )
172+ instrument_name = find_attr (node , 'System Type' )
173+ if serial is not None and instrument_name is not None :
174+ break
175+ node = node .parent
176+
177+ # If not found yet, also check if there is an Attributes group
178+ if serial is None or instrument_name is None :
179+ def visit_func (name , obj ):
180+ nonlocal serial , instrument_name
181+ if serial is None :
182+ serial = find_attr (obj , 'System Serial Number' )
183+ if instrument_name is None :
184+ instrument_name = find_attr (obj , 'System Type' )
185+
186+ if 'Attributes' in h5 :
187+ h5 ['Attributes' ].visititems (visit_func )
188+
189+ if serial is not None :
190+ if isinstance (serial , bytes ):
191+ serial = serial .decode ('utf-8' )
192+ instrument_info ["serial" ] = str (serial )
193+
194+ if instrument_name is not None :
195+ if isinstance (instrument_name , bytes ):
196+ instrument_name = instrument_name .decode ('utf-8' )
197+ instrument_info ["name" ] = str (instrument_name )
169198
170199 return [
171200 ChannelInfo (
@@ -205,6 +234,7 @@ def topography(self, channel_index=None, physical_sizes=None, height_scale_facto
205234
206235 _info = self .channels [channel_index ].info .copy ()
207236 _info .update (info )
237+ _info .update ({'instrument' : self .channels [channel_index ].info ['instrument' ]})
208238
209239 fobj = self ._fobj
210240 if callable (fobj ):
0 commit comments