1414import numpy as np
1515
1616from . import error , misc , phyvars , stagyyparsers
17-
18-
19- UNDETERMINED = object ()
20- # dummy object with a unique identifier,
21- # useful to mark stuff as yet undetermined,
22- # as opposed to either some value or None if
23- # non existent
17+ from .misc import CachedReadOnlyProperty as crop
2418
2519
2620class _Geometry :
@@ -209,8 +203,6 @@ class _Fields(Mapping):
209203
210204 def __init__ (self , step , variables , extravars , files , filesh5 ):
211205 self .step = step
212- self ._header = UNDETERMINED
213- self ._geom = UNDETERMINED
214206 self ._vars = variables
215207 self ._extra = extravars
216208 self ._files = files
@@ -232,7 +224,7 @@ def __getitem__(self, name):
232224 raise error .MissingDataError (
233225 f'Missing field { name } in step { self .step .istep } ' )
234226 header , fields = parsed_data
235- self ._header = header
227+ self ._cropped__header = header
236228 for fld_name , fld in zip (fld_names , fields ):
237229 if self ._header ['xyp' ] == 0 :
238230 if not self .geom .twod_yz :
@@ -281,7 +273,6 @@ def _get_raw_data(self, name):
281273 if filestem in phyvars .SFIELD_FILES_H5 :
282274 xmff = 'Data{}.xmf' .format (
283275 'Bottom' if name .endswith ('bot' ) else 'Surface' )
284- _ = self .geom
285276 header = self ._header
286277 else :
287278 xmff = 'Data.xmf'
@@ -304,31 +295,25 @@ def __delitem__(self, name):
304295 if name in self ._data :
305296 del self ._data [name ]
306297
307- @property
298+ @crop
299+ def _header (self ):
300+ binfiles = self .step .sdat ._binfiles_set (self .step .isnap )
301+ if binfiles :
302+ return stagyyparsers .fields (binfiles .pop (), only_header = True )
303+ elif self .step .sdat .hdf5 :
304+ xmf = self .step .sdat .hdf5 / 'Data.xmf'
305+ return stagyyparsers .read_geom_h5 (xmf , self .step .isnap )[0 ]
306+
307+ @crop
308308 def geom (self ):
309309 """Geometry information.
310310
311311 :class:`_Geometry` instance holding geometry information. It is
312312 issued from binary files holding field information. It is set to
313313 None if not available for this time step.
314314 """
315- if self ._header is UNDETERMINED :
316- binfiles = self .step .sdat ._binfiles_set (self .step .isnap )
317- if binfiles :
318- self ._header = stagyyparsers .fields (binfiles .pop (),
319- only_header = True )
320- elif self .step .sdat .hdf5 :
321- xmf = self .step .sdat .hdf5 / 'Data.xmf'
322- self ._header , _ = stagyyparsers .read_geom_h5 (xmf ,
323- self .step .isnap )
324- else :
325- self ._header = None
326- if self ._geom is UNDETERMINED :
327- if self ._header is None :
328- self ._geom = None
329- else :
330- self ._geom = _Geometry (self ._header , self .step .sdat .par )
331- return self ._geom
315+ if self ._header is not None :
316+ return _Geometry (self ._header , self .step .sdat .par )
332317
333318
334319class _Tracers :
@@ -393,17 +378,15 @@ class _Rprofs:
393378
394379 def __init__ (self , step ):
395380 self .step = step
396- self ._data = UNDETERMINED
397381 self ._cached_extra = {}
398- self ._centers = UNDETERMINED
399- self ._walls = UNDETERMINED
400- self ._bounds = UNDETERMINED
382+
383+ @crop
384+ def _data (self ):
385+ step = self .step
386+ return step .sdat ._rprof_and_times [0 ].get (step .istep )
401387
402388 @property
403389 def _rprofs (self ):
404- if self ._data is UNDETERMINED :
405- step = self .step
406- self ._data = step .sdat ._rprof_and_times [0 ].get (step .istep )
407390 if self ._data is None :
408391 step = self .step
409392 raise error .MissingDataError (
@@ -434,43 +417,38 @@ def __getitem__(self, name):
434417
435418 return Rprof (rprof , rad , meta )
436419
437- @property
420+ @crop
438421 def centers (self ):
439422 """Radial position of cell centers."""
440- if self ._centers is UNDETERMINED :
441- self ._centers = self ._rprofs ['r' ].values + self .bounds [0 ]
442- return self ._centers
423+ return self ._rprofs ['r' ].values + self .bounds [0 ]
443424
444- @property
425+ @crop
445426 def walls (self ):
446427 """Radial position of cell walls."""
447- if self ._walls is UNDETERMINED :
448- rbot , rtop = self .bounds
449- centers = self .centers
450- # assume walls are mid-way between T-nodes
451- # could be T-nodes at center between walls
452- self ._walls = (centers [:- 1 ] + centers [1 :]) / 2
453- self ._walls = np .insert (self ._walls , 0 , rbot )
454- self ._walls = np .append (self ._walls , rtop )
455- return self ._walls
456-
457- @property
428+ rbot , rtop = self .bounds
429+ centers = self .centers
430+ # assume walls are mid-way between T-nodes
431+ # could be T-nodes at center between walls
432+ walls = (centers [:- 1 ] + centers [1 :]) / 2
433+ walls = np .insert (walls , 0 , rbot )
434+ walls = np .append (walls , rtop )
435+ return walls
436+
437+ @crop
458438 def bounds (self ):
459439 """Radial or vertical position of boundaries.
460440
461441 Radial/vertical positions of boundaries of the domain.
462442 """
463- if self ._bounds is UNDETERMINED :
464- step = self .step
465- if step .geom is not None :
466- rcmb = step .geom .rcmb
467- else :
468- rcmb = step .sdat .par ['geometry' ]['r_cmb' ]
469- if step .sdat .par ['geometry' ]['shape' ].lower () == 'cartesian' :
470- rcmb = 0
471- rcmb = max (rcmb , 0 )
472- self ._bounds = rcmb , rcmb + 1
473- return self ._bounds
443+ step = self .step
444+ if step .geom is not None :
445+ rcmb = step .geom .rcmb
446+ else :
447+ rcmb = step .sdat .par ['geometry' ]['r_cmb' ]
448+ if step .sdat .par ['geometry' ]['shape' ].lower () == 'cartesian' :
449+ rcmb = 0
450+ rcmb = max (rcmb , 0 )
451+ return rcmb , rcmb + 1
474452
475453
476454class Step :
@@ -520,7 +498,7 @@ def __init__(self, istep, sdat):
520498 phyvars .SFIELD_FILES , phyvars .SFIELD_FILES_H5 )
521499 self .tracers = _Tracers (self )
522500 self .rprofs = _Rprofs (self )
523- self ._isnap = UNDETERMINED
501+ self ._isnap = - 1
524502
525503 def __repr__ (self ):
526504 if self .isnap is not None :
@@ -549,7 +527,7 @@ def isnap(self):
549527
550528 It is set to None if no snapshot exists for the time step.
551529 """
552- if self ._isnap is UNDETERMINED :
530+ if self ._isnap == - 1 :
553531 istep = None
554532 isnap = - 1
555533 # could be more efficient if do 0 and -1 then bisection
0 commit comments