def replay(self, figlist="default", speed=np.inf, t1=0, t2=None, **kwargs): """Replay LivePlot with what's been stored in 'self'. - t1, t2: time window to plot. - 'figlist' and 'speed': See LivePlot's doc. .. note:: `store_u` (whether to store non-obs-time stats) must have been `True` to have smooth graphs as in the actual LivePlot. .. note:: Ensembles are generally not stored in the stats and so cannot be replayed. """ # Time settings tseq = self.HMM.tseq if t2 is None: t2 = t1 + tseq.Tplot # Ens does not get stored in stats, so we cannot replay that. # If the LPs are initialized with P0!=None, then they will avoid ens plotting. # TODO 4: This system for switching from Ens to stats must be replaced. # It breaks down when M is very large. try: P0 = np.full_like(self.HMM.X0.C.full, np.nan) except AttributeError: # e.g. if X0 is defined via sampling func P0 = np.eye(self.HMM.Nx) LP = liveplotting.LivePlot(self, figlist, P=P0, speed=speed, Tplot=t2 - t1, replay=True, **kwargs) plt.pause(.01) # required when speed=inf # Remember: must use progbar to unblock read1. # Let's also make a proper description. desc = self.xp.da_method + " (replay)" # Play through assimilation cycles for k, ko, t, _dt in progbar(tseq.ticker, desc): if t1 <= t <= t2: if ko is not None: LP.update((k, ko, 'f'), None, None) LP.update((k, ko, 'a'), None, None) LP.update((k, ko, 'u'), None, None) # Pause required when speed=inf. # On Mac, it was also necessary to do it for each fig. if LP.any_figs: for _name, updater in LP.figures.items(): if plt.fignum_exists(_name) and getattr( updater, 'is_active', 1): plt.figure(_name) plt.pause(0.01)
def assess(self, k, kObs=None, faus=None, E=None, w=None, mu=None, Cov=None): """Common interface for both assess_ens and _ext. The _ens assessment function gets called if E is not None, and _ext if mu is not None. faus: One or more of ['f',' a', 'u'], indicating that the result should be stored in (respectively) the forecast/analysis/universal attribute. Default: 'u' if kObs is None else 'au' ('a' and 'u'). """ # Initial consistency checks. if k == 0: if kObs is not None: raise KeyError("DAPPER convention: no obs at t=0." " Helps avoid bugs.") if faus is None: faus = 'u' if self._is_ens == True: if E is None: raise TypeError("Expected ensemble input but E is None") if mu is not None: raise TypeError( "Expected ensemble input but mu/Cov is not None") else: if E is not None: raise TypeError("Expected mu/Cov input but E is not None") if mu is None: raise TypeError("Expected mu/Cov input but mu is None") # Default. Don't add more defaults. It just gets confusing. if faus is None: faus = 'u' if kObs is None else 'au' # Select assessment call and arguments if self._is_ens: _assess = self.assess_ens _prms = {'E': E, 'w': w} else: _assess = self.assess_ext _prms = {'mu': mu, 'P': Cov} for sub in faus: # Skip assessment if ('u' and stats not stored or plotted) if k != 0 and kObs == None: if not (self.store_u or self.LP_instance.any_figs): continue # Silence repeat warnings caused by zero variance with np.errstate(divide='call', invalid='call'): np.seterrcall(warn_zero_variance) # Assess stats_now = Avrgs() _assess(stats_now, self.xx[k], **_prms) self.derivative_stats(stats_now) self.summarize_marginals(stats_now) # Write current stats to series for name, val in stats_now.items(): stat = struct_tools.deep_getattr(self, name) isFaust = isinstance(stat, series.FAUSt) stat[(k, kObs, sub) if isFaust else kObs] = val # LivePlot -- Both init and update must come after the assessment. try: self.LP_instance.update((k, kObs, sub), E, Cov) except AttributeError: self.LP_instance = liveplotting.LivePlot( self, self.liveplots, (k, kObs, sub), E, Cov)
def assess(self, k, ko=None, faus=None, E=None, w=None, mu=None, Cov=None): """Common interface for both `Stats.assess_ens` and `Stats.assess_ext`. The `_ens` assessment function gets called if `E is not None`, and `_ext` if `mu is not None`. faus: One or more of `['f',' a', 'u', 's']`, indicating that the result should be stored in (respectively) the forecast/analysis/universal attribute. Default: `'u' if ko is None else 'au' ('a' and 'u')`. """ # Initial consistency checks. if k == 0: if ko is not None: raise KeyError( "DAPPER convention: no obs at t=0. Helps avoid bugs.") if self._is_ens == True: if E is None: raise TypeError("Expected ensemble input but E is None") if mu is not None: raise TypeError( "Expected ensemble input but mu/Cov is not None") else: if E is not None: raise TypeError("Expected mu/Cov input but E is not None") if mu is None: raise TypeError("Expected mu/Cov input but mu is None") # Default. Don't add more defaults. It just gets confusing. if faus is None: faus = 'u' if ko is None else 'au' # TODO 4: for faus="au" (e.g.) we don't need to re-**compute** stats, # merely re-write them? for sub in faus: # Skip assessment if ('u' and stats not stored or plotted) if k != 0 and ko == None: if not (self.store_u or self.LP_instance.any_figs): continue # Silence repeat warnings caused by zero variance with np.errstate(divide='call', invalid='call'): np.seterrcall(warn_zero_variance) # Assess stats_now = Avrgs() if self._is_ens: self.assess_ens(stats_now, self.xx[k], E, w) else: self.assess_ext(stats_now, self.xx[k], mu, Cov) self.derivative_stats(stats_now) self.summarize_marginals(stats_now) self.write(stats_now, k, ko, sub) # LivePlot -- Both init and update must come after the assessment. try: self.LP_instance.update((k, ko, sub), E, Cov) except AttributeError: self.LP_instance = liveplotting.LivePlot( self, self.liveplots, (k, ko, sub), E, Cov)