def test_masked_exclude(self): "Make sure that masked values are not allowed to cause FP overflow" # ensure masked values are not allowed to cause floating point # overflow problems ser_a = ma.array(range(150), dtype=np.float32) ser_a[:50] = ma.masked ser_b = ser_a.copy() # insert a very high value in the middle of the masked section of the # array. This should have no impact on the final result because it is # surround by masked values ser_b[45] = 5.0e34 res_a = mf.mov_sum(ser_a, 60) res_b = mf.mov_sum(ser_b, 60) assert_almost_equal(res_a, res_b)
def spi(rainfall, span=3, freq='monthly', start_reference=None, end_reference=None, distribution='gamma'): """ Computes the standardized precipitation index for the precipitation series at the given span. Parameters ---------- rainfall : TimeSeries Series of monthly cumulative precipitation. span : {3, int} optional Span, in months. freq : {'monthly','weekly'} optional Frequency start_reference : {None, Date} optional Starting date of the reference period. If None, use the first date of the series. end_reference : {None, Date} optional Ending date of the reference period. If None, use the last date of the series. distribution : {'gamma','normal'} optional Type of distribution for the data of each period. """ if not isinstance(rainfall, TimeSeries): raise TypeError,\ "The precipitation input should be a valid TimeSeries object!" _freq = freq.upper()[0] if _freq not in ['M', 'W']: raise ValueError,"Invalid frequency! Should be in ('Monthly','Weekly')"\ " (got '%s' instead)" % freq rain = rainfall.convert(_freq, func=ma.sum) dates = rain.dates # Convert to cumulative over span (mm) and as a Nx12 or Nx53 array... arain = mov_sum(rain, span).convert('A') # Define the reference period ................... if start_reference is None: startd = dates[0] elif not isinstance(start_reference, Date): startd = Date(_freq, start_reference) else: startd = start_reference.asfreq(_freq) if end_reference is None: endd = dates[-1] elif not isinstance(end_reference, Date): endd = Date(_freq, end_reference) else: endd = end_reference.asfreq(_freq) condition = time_series((dates < startd) | (dates > endd), dates=dates).convert('A') # Get the cumulative distribution try: cdffunc = _cdfdict[distribution] except KeyError: raise ValueError("Unrecognized distribution '%s':"\ "Should be in %s)" % (distribution, ','.join(_cdfdict.keys()))) cdf = cdffunc(arain, condition) # Get the corresponding normal scores zscores = ma.fix_invalid(ssd.norm.ppf(cdf)) zscores._mask |= ma.getmaskarray(arain) # Retransform to a regular time series if _freq == 'M': kwargs = {'month': 1} else: kwargs = {'week': 1} kwargs.update({'year': dates[0].year}) spi = time_series( zscores.ravel(), start_date=Date(_freq, **kwargs), ).view(type(rainfall)) return spi
def spi(rainfall, span=3, freq='monthly', start_reference=None, end_reference=None, distribution='gamma'): """ Computes the standardized precipitation index for the precipitation series at the given span. Parameters ---------- rainfall : TimeSeries Series of monthly cumulative precipitation. span : {3, int} optional Span, in months. freq : {'monthly','weekly'} optional Frequency start_reference : {None, Date} optional Starting date of the reference period. If None, use the first date of the series. end_reference : {None, Date} optional Ending date of the reference period. If None, use the last date of the series. distribution : {'gamma','normal'} optional Type of distribution for the data of each period. """ if not isinstance(rainfall, TimeSeries): raise TypeError,\ "The precipitation input should be a valid TimeSeries object!" _freq = freq.upper()[0] if _freq not in ['M','W']: raise ValueError,"Invalid frequency! Should be in ('Monthly','Weekly')"\ " (got '%s' instead)" % freq rain = rainfall.convert(_freq, func=ma.sum) dates = rain.dates # Convert to cumulative over span (mm) and as a Nx12 or Nx53 array... arain = mov_sum(rain, span).convert('A') # Define the reference period ................... if start_reference is None: startd = dates[0] elif not isinstance(start_reference, Date): startd = Date(_freq, start_reference) else: startd = start_reference.asfreq(_freq) if end_reference is None: endd = dates[-1] elif not isinstance(end_reference, Date): endd = Date(_freq, end_reference) else: endd = end_reference.asfreq(_freq) condition = time_series((dates < startd) | (dates > endd), dates=dates).convert('A') # Get the cumulative distribution try: cdffunc = _cdfdict[distribution] except KeyError: raise ValueError("Unrecognized distribution '%s':"\ "Should be in %s)" % (distribution, ','.join(_cdfdict.keys()))) cdf = cdffunc(arain, condition) # Get the corresponding normal scores zscores = ma.fix_invalid(ssd.norm.ppf(cdf)) zscores._mask |= ma.getmaskarray(arain) # Retransform to a regular time series if _freq == 'M': kwargs = {'month':1} else: kwargs = {'week':1} kwargs.update({'year':dates[0].year}) spi = time_series(zscores.ravel(), start_date=Date(_freq,**kwargs), ).view(type(rainfall)) return spi