示例#1
0
def quantPeriod(varname=None, datasets=None, fit=None, quantiles=None, name=None, units='years', 
                sampling_period=1, asVar=True,
                lmean=None, lmedian=None, lbootstrap=False, percentiles=(0.025,0.975), lvar=False, 
                reference=0, bootstrap_axis='bootstrap', lsample=False, sample_axis='station', **kwargs):
  ''' Compute the return periods of events with intensities equal to the given quantiles in the 
      reference sample. Confidence intervals can be estimated from bootstrapping or sample 
      distributions. The data is returned as a variable object with axes for quantiles, datasets, 
      and distribution percentiles; quantiles are converted to return periods (years, by default). '''
  
  # input requirements
  if not isinstance(fit, Ensemble): raise TypeError(fit)
  if not all([isinstance(ds, Dataset) for ds in fit]): raise TypeError(fit)
  # cast quantiles as array
  quantiles = np.asarray(quantiles)
  
  # select datasets
  if datasets is not None:
    if not isinstance(datasets,(tuple,list)): raise TypeError(datasets)
    fit = selectDataset(fit, datasets)
    assert datasets == fit.name
  else: 
    datasets = fit.name
      
  if lsample and lmean is None: lmean = True # show mean instead of "true fit" 
  if lsample and lmedian is None: lmedian = False # don't show median 
  
  # compute references quantiles
  if isinstance(reference,(int,np.integer)): reference = fit[reference].name
  if not isinstance(reference,str): raise TypeError(reference)  
  if lsample: 
    refvals = checkVarlist(fit[reference], varname=varname, ndim=2, support=quantiles, method='ppf')[0]
    refvals = refvals.mean(axis=sample_axis, asVar=False)      
  else: 
    refvals = checkVarlist(fit[reference], varname=varname, ndim=1, support=quantiles, method='ppf')[0][:] # just get values

  # compute qunatiles corresponding to reference quantiles
  if ( lsample and any(ds.hasAxis(sample_axis, lany=True) for ds in fit) or 
       lbootstrap and any(ds.hasAxis(bootstrap_axis) for ds in fit) ):
    ciaxis = bootstrap_axis if lbootstrap else sample_axis
    # compute confidence itnervals    
    civars = checkVarlist(fit, varname=varname, ndim=2, support=refvals, method='cdf', bootstrap_axis=None)
    q = (percentiles[0],0.5,percentiles[1]) if lmedian and lsample else percentiles # median is a percentile
    if lmean: qvars = [civar.mean(axis=sample_axis, asVar=True,) for civar in civars]
    civars = [civar.percentile(q=q, axis=ciaxis, asVar=True,) for civar in civars]
    if lmedian: qvars = [civar(percentile=0.5,) for civar in civars]
    lovars = [civar(percentile=percentiles[0],) for civar in civars]
    hivars = [civar(percentile=percentiles[1],) for civar in civars]
  if lbootstrap or not lsample:
    # get the one true realization    
    qvars = checkVarlist(fit, varname=varname, ndim=1, support=refvals, method='cdf', bootstrap_axis=bootstrap_axis)
  # returns a list of variables containing the quantile values
  if lbootstrap or lsample:
    # prepend the true/mean value to CI intervals (percentile axis)
    pax = Axis(coord=np.asarray((-1,)+percentiles), name='percentile', units='')
    tmplist = []
    for qvar,lovar,hivar in zip(qvars,lovars,hivars):
      tmp = concatVars((qvar,lovar,hivar), axis=pax, asVar=True, name=qvar.name, units=qvar.units, 
                       varatts=qvar.atts, lcheckAxis=True, lensembleAxis=True)
      tmplist.append(tmp)
    qvars = tmplist # new qvar list with percentiles / CI's
    
  # concatenate experiments by creating new axis
  if asVar:
    # create experiment axis
    expax = Axis(coord=np.arange(len(datasets)), name='experiment', units='#', atts=dict(datasets=datasets))
    # concat variables
    name = name or varname+'_periods'
    quantvar = concatVars(qvars, axis=expax, asVar=True, name=name, units=units, 
                           lcheckAxis=True, lensembleAxis=True)
    quantvar.data_array = convQuant(quantvar.data_array, smpl_prd=sampling_period, lround=True)
    # rename "_bins" variable
    for axis in quantvar.axes:
      if axis.name[-5:] == '_bins':
        axis.coord = convQuant(quantiles, smpl_prd=sampling_period, lround=True)
        axis.name = 'quantile'; axis.units = units
  else:
    quantvar = {dataset:qvar for dataset,qvar in zip(datasets,qvars)}
    
  # return
  # N.B.: the true/mean/median value is the first one along the percentile axis (percentile = -1)
  return quantvar
示例#2
0
def quantPlot(axes=None, varname=None, datasets=None, fit=None, scl=None, legend=True, quantiles=None, 
              shape_name=None, stnset_name=None, ylim=None, xlim=None, ylabel=True, xlabel=True, 
              xticks=True, yticks=True, axtitle=None, lbootstrap=False, percentiles=(0.025,0.975), 
              band_vars=None,
              lmedian=None, median_fmt='', lrescaleBand=False, sampling_period=1, lmean=None, mean_fmt='', 
              lvar=False, lvarBand=False, lrescale=False, reference=0, bootstrap_axis='bootstrap', 
              lsample=False, sample_axis='station', annotation=None, defaults=None, **kwargs):
  ''' Generate an EVA quantile plot with annotations in a single axes, including (re-)scaled curves. 
      The y-axis is labeled with return periods and specific quantiles can be marked by vertical lines. '''
  
  # cast quantiles as array
  quantiles = np.asarray(quantiles) if quantiles else None
  # y-limits for upper and lower percentiles
  if ylim is None:
    if quantiles is not None:
      if np.min(quantiles) > 0.5: ylim = (0.95,1.01)
      else: ylim = (-0.01,0.065)
    else: ylim = (0.95,1.01)
  bins = ylim+(200,)
  if ylim[1] >= 1: axes.addHline(1, color='k', alpha=0.5) # mark one line
  if ylim[0] <= 0: axes.addHline(0, color='k', alpha=0.5) # mark zero line
  # get reasonable x-limits for variables based on region
  if xlim is None:
    if stnset_name is not None: xlim = annotation[stnset_name].get(varname,None)
    elif shape_name is not None: xlim = annotation[shape_name].get(varname,None)
    elif varname in defaults: xlim = defaults.get(varname,None)    
    else: xlim = axes.get_xlim()
  # select datasets
  if datasets is not None:
    if not isinstance(datasets,(tuple,list)): raise TypeError(datasets)
    fit = selectDataset(fit, datasets)
    scl = selectDataset(scl, datasets)
    
  if lsample and lmean is None: lmean = True # show mean instead of "true fit" 
  if lsample and lmedian is None: lmedian = False # don't show median  
  # generate quantile plot
  if lsample and any(ds.hasAxis(sample_axis, lany=True) for ds in fit):    
    plts = axes.samplePlot(fit,varname, support=bins, method='ppf', linewidth=1.25, title=axtitle,
                         flipxy=True, llabel=True, legend=legend, percentiles=percentiles,
                         sample_axis=sample_axis, bootstrap_axis=bootstrap_axis, band_vars=band_vars,
                         xlim=xlim, ylim=ylim, ylabel=ylabel, xlabel=xlabel, xticks=xticks, yticks=yticks, 
                         lmedian=lmedian, median_fmt=median_fmt, lmean=lmean, mean_fmt=mean_fmt,
                         lsmooth=False, bandalpha=0.25, **kwargs)    
  elif lbootstrap and any(ds.hasAxis(bootstrap_axis) for ds in fit):    
    plts = axes.bootPlot(fit,varname, support=bins, method='ppf', linewidth=1.25, title=axtitle,
                       flipxy=True, llabel=True, legend=legend, percentiles=percentiles, band_vars=band_vars,
                       xlim=xlim, ylim=ylim, ylabel=ylabel, xlabel=xlabel, xticks=xticks, yticks=yticks, 
                       lmedian=lmedian, median_fmt=median_fmt, lmean=lmean, mean_fmt=mean_fmt, 
                       lvar=lvar, lvarBand=lvarBand, lsmooth=False, bandalpha=0.25, **kwargs)
    # N.B.: smoothing causes (resolution-dependent) artifacts near the limit (1 or 0)
  else:
    plts = axes.linePlot(fit, varname, support=bins, method='ppf', linewidth=1.25, title=axtitle, 
                       xlim=xlim, ylim=ylim, ylabel=ylabel, xlabel=xlabel, xticks=xticks, yticks=yticks,
                       flipxy=True, llabel=True, legend=legend, **kwargs)
  # add percentile lines
  if quantiles is not None:    
    iref = fit.idkeys.index(reference) if isinstance(reference,str) else reference
    if lsample: 
      quants = checkVarlist(fit[iref], varname=varname, ndim=2, support=quantiles, method='ppf')[0].mean(asVar=True)      
    else: quants = checkVarlist(fit[iref], varname=varname, ndim=1, support=quantiles, method='ppf')[0]
    qvals = quants.data_array * quants.plot.scalefactor + quants.plot.offset
    axes.addVline(qvals, color=plts[iref].get_color(), alpha=0.5) # linestyle=plts[iref].get_linestyle()

  if lrescale and scl:
    # plot scaled quantile distributions
    if lsample and any(ds.hasAxis(sample_axis, lany=True) for ds in scl):    
      plts = axes.samplePlot(scl,varname, support=bins, method='ppf', linewidth=1., mean_fmt='--',
                           title=None, flipxy=True, llabel=False, legend=legend, 
                           percentiles=percentiles if lrescaleBand else None, band_vars=band_vars,
                           sample_axis=sample_axis, bootstrap_axis=bootstrap_axis, 
                           xlim=xlim, ylim=ylim, ylabel=ylabel, xlabel=xlabel, xticks=xticks, yticks=yticks, 
                           lmedian=lmedian, median_fmt='--', lmean=lmean, #mean_fmt=mean_fmt,
                           lsmooth=False, bandalpha=0.25, **kwargs)    
    elif lbootstrap and any(ds.hasAxis(bootstrap_axis) for ds in scl):    
#       bandalf = kwargs.pop('bandalhpa',0.5) * 0.7
      plts = axes.bootPlot(scl,varname, support=bins, method='ppf', percentiles=percentiles if lrescaleBand else None, 
                         linewidth=1., lineformat='--', bandalpha=0.25, flipxy=True, lmedian=lmedian, median_fmt='--',
                         xlim=xlim, ylim=ylim, ylabel=ylabel, xlabel=xlabel, xticks=xticks, yticks=yticks, 
                         lmean=lmean, mean_fmt='--', lvar=lvar, lvarBand=lvarBand, band_vars=band_vars,
                         llabel=False, lsmooth=False, **kwargs)
      # N.B.: smoothing causes (resolution-dependent) artifacts near the limit (1 or 0)
    else:
      plts = axes.linePlot(scl, varname, support=bins, method='ppf', linewidth=1., linestyle='--',
                         xlim=xlim, ylim=ylim, ylabel=ylabel, xlabel=xlabel, xticks=xticks, yticks=yticks,
                         flipxy=True, llabel=False, legend=None, **kwargs)
    # add percentile lines for scaled distributions
    if quantiles is not None:
      iref = scl.idkeys.index(reference) if isinstance(reference,str) else reference    
      if lsample: 
        quants = checkVarlist(scl[iref], varname=varname, ndim=2, support=quantiles, method='ppf')[0].mean(asVar=True)
      else: quants = checkVarlist(scl[iref], varname=varname, ndim=1, support=quantiles, method='ppf')[0]
      qvals = quants.data_array * quants.plot.scalefactor + quants.plot.offset    
      axes.addVline(qvals, color=plts[iref].get_color(), alpha=0.35) # linestyle=plts[iref].get_linestyle()
      
  # convert y-tick labels to return periods
  yticks = ['{:3.0f}'.format(sampling_period/(1-yt)) if yt < 1 else '' for yt in axes.get_yticks().tolist()]
  axes.set_yticklabels(yticks)
   
  # return
  return plts