示例#1
0
    def __getattribute__(self, key):
        """Support deep and abbreviated lookup."""

        # key = abbrevs[key] # Instead of this, also support rmse.a:
        key = '.'.join(Avrgs.abbrevs.get(seg, seg) for seg in key.split('.'))

        if "." in key:
            return dict_tools.deep_getattr(self, key)
        else:
            return super().__getattribute__(key)
示例#2
0
    def new_series(self, name, shape, length='FAUSt', MS=False, **kws):
        """Create (and register) a statistics time series.

        Series are initialized with nan's.

        Example: Create ndarray of length KObs+1 for inflation time series:
        >>> self.new_series('infl', 1, KObs+1)

        NB: The ``sliding_diagnostics`` liveplotting relies on detecting ``nan``'s
            to avoid plotting stats that are not being used.
            => Cannot use ``dtype=bool`` or ``int`` for stats that get plotted.
        """

        # Convert int shape to tuple
        if not hasattr(shape, '__len__'):
            if shape == 1:
                shape = ()
            else:
                shape = (shape, )

        def make_series(parent, name, shape):
            if length == 'FAUSt':
                total_shape = self.K, self.KObs, shape
                store_opts = self.store_u, self.store_s
                tseries = series.FAUSt(*total_shape, *store_opts, **kws)
            else:
                total_shape = (length, ) + shape
                tseries = DataSeries(total_shape, *kws)
            register_stat(parent, name, tseries)

        # Principal series
        make_series(self, name, shape)

        # Summary (scalar) series:
        if shape != ():
            if MS:
                for suffix in self.field_summaries:
                    make_series(getattr(self, name), suffix, ())
            # Make a nested level for sectors
            if MS == 'sec':
                for ss in self.sector_summaries:
                    suffix, sector = ss.split('.')
                    make_series(
                        dict_tools.deep_getattr(self, f"{name}.{suffix}"),
                        sector, ())
示例#3
0
 def finalize_init(ax, lines, mm):
     # Rm lines that only contain NaNs
     for name in list(lines):
         ln = lines[name]
         stat = deep_getattr(stats, name)
         if not stat.were_changed:
             ln['handle'].remove()  # rm from axes
             del lines[name]  # rm from dict
     # Add legends
     if lines:
         ax.legend(loc='upper left',
                   bbox_to_anchor=(1.01, 1),
                   borderaxespad=0)
         if mm:
             ax.annotate(star + ": mean of\nmarginals",
                         xy=(0, -1.5 / len(lines)),
                         xycoords=ax.get_legend().get_frame(),
                         bbox=dict(alpha=0.0),
                         fontsize='small')
     # coz placement of annotate needs flush sometimes:
     plot_pause(0.01)
示例#4
0
        def init_ax(ax, style_table):
            lines = {}
            for name in style_table:

                # SKIP -- if stats[name] is not in existence
                # Note: The nan check/deletion comes after the first kObs.
                try:
                    stat = deep_getattr(stats, name)
                except AttributeError:
                    continue
                # try: val0 = stat[key0[0]]
                # except KeyError: continue
                # PS: recall (from series.py) that even if store_u is false, stat[k] is
                # still present if liveplots=True via the k_tmp functionality.

                # Unpack style
                ln = {}
                ln['transf'] = style_table[name][0] or (lambda x: x)
                ln['shape'] = style_table[name][1]
                ln['plt'] = style_table[name][2]

                # Create series
                if isinstance(stat, FAUSt):
                    ln['plot_u'] = plot_u
                    K_plot = comp_K_plot(K_lag, a_lag, ln['plot_u'])
                else:
                    ln['plot_u'] = False
                    K_plot = a_lag
                ln['data'] = RollingArray(K_plot)
                ln['tt'] = RollingArray(K_plot)

                # Plot (init)
                ln['handle'], = ax.plot(ln['tt'], ln['data'], **ln['plt'])

                # Plotting only nans yield ugly limits. Revert to defaults.
                ax.set_xlim(0, 1)
                ax.set_ylim(0, 1)

                lines[name] = ln
            return lines
示例#5
0
 def update_arrays(lines):
     for name, ln in lines.items():
         stat = deep_getattr(stats, name)
         t = chrono.tt[k]  # == chrono.ttObs[kObs]
         if isinstance(stat, FAUSt):
             # ln['data'] will contain duplicates for f/a times.
             if ln['plot_u']:
                 val = stat[key]
                 ln['tt'].insert(k, t)
                 ln['data'].insert(k, ln['transf'](val))
             elif 'u' not in faus:
                 val = stat[key]
                 ln['tt'].insert(kObs, t)
                 ln['data'].insert(kObs, ln['transf'](val))
         else:
             # ln['data'] will not contain duplicates, coz only 'a' is input.
             if 'a' in faus:
                 val = stat[kObs]
                 ln['tt'].insert(kObs, t)
                 ln['data'].insert(kObs, ln['transf'](val))
             elif 'f' in faus:
                 pass
示例#6
0
 def get_val(i):
     try:
         return deep_getattr(xps[i].avrgs, 'err.rms.' + sub).val
     except AttributeError:
         return np.nan
示例#7
0
    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 = dict_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)