def setUp(self):
     data = [
         1,
         4,
         3,
         2,
         0,
         1,
         0,
         0,
         0,
         0,
         3,
         3,
         3,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         0,
         7,
         0.1,
         5,
     ]
     self.rainfall = hydro.time_series(data,
                                       start_date=hydro.Date(
                                           'M', '2001-01'))
     self.data = data
 def test_wet_and_dry_spells(self):
     "Test wet and dry spells"
     data = self.data + [-3]
     rainfall = hydro.time_series(data, mask=24 * [0] + [1], start_date=hydro.Date("M", "2001-01"))
     threshold = 0.254
     dspells = dry_spells(rainfall, threshold=threshold)
     wspells = wet_spells(rainfall, threshold=threshold)
     assert_equal(dspells.sum() + wspells.durations.sum(), rainfall.count())
Exemple #3
0
 def test_daily_random(self):
     "Test some PET models on some random daily data"
     (freq, base) = ('D', 365)
     wave = -10 * np.cos(np.arange(120) * (2. * np.pi) / base)
     tmin = hydro.time_series(5 + wave + np.random.rand(120) * 3,
                              start_date=hydro.Date(freq, '1990-01-01'))
     tmax = hydro.time_series(10 + wave + np.random.rand(120) * 3,
                              start_date=hydro.Date(freq, '1990-01-01'))
     ma.putmask(tmax, (tmax < tmin), tmin + 1)
     freeze = ((tmin + tmax) / 2. <= 0)
     PET = evapo.PotentialEvapoTranspiration(tmin, tmax, self.latitude)
     for d in self.defaults:
         err_msg = "Error w/ model '%s' : the PET should be masked" % d
         P = ma.masked_values(getattr(PET, d).__call__(), 0)
         if d in ['Hamon', 'Kharrufa', 'Turc']:
             assert_equal(ma.getmaskarray(P), freeze, err_msg=err_msg)
         else:
             assert (not ma.getmaskarray(P).any())
 def test_daily_random(self):
     "Test some PET models on some random daily data"
     (freq, base) = ('D', 365)
     wave = -10 * np.cos(np.arange(120) * (2.*np.pi)/base)
     tmin = hydro.time_series(5 + wave + np.random.rand(120) * 3,
                              start_date=hydro.Date(freq, '1990-01-01'))
     tmax = hydro.time_series(10 + wave + np.random.rand(120) * 3,
                              start_date=hydro.Date(freq, '1990-01-01'))
     ma.putmask(tmax, (tmax < tmin), tmin+1)
     freeze = ((tmin + tmax)/2. <= 0)
     PET = evapo.PotentialEvapoTranspiration(tmin, tmax, self.latitude)
     for d in self.defaults:
         err_msg = "Error w/ model '%s' : the PET should be masked" % d
         P = ma.masked_values(getattr(PET, d).__call__(), 0)
         if d in ['Hamon', 'Kharrufa', 'Turc']:
             assert_equal(ma.getmaskarray(P), freeze, err_msg=err_msg)
         else:
             assert(not ma.getmaskarray(P).any())
 def test_wet_and_dry_spells(self):
     "Test wet and dry spells"
     data = self.data + [-3]
     rainfall = hydro.time_series(data,
                                  mask=24 * [0] + [1],
                                  start_date=hydro.Date('M', '2001-01'))
     threshold = 0.254
     dspells = dry_spells(rainfall, threshold=threshold)
     wspells = wet_spells(rainfall, threshold=threshold)
     assert_equal(dspells.sum() + wspells.durations.sum(), rainfall.count())
def dump_seasonal_averages(observations, dbname="coaps.sqlite",
                           period="monthly", ensostr="ONI"):
    """
    Dump seasonal averages of observations in a SQLite database.

    The database is named following the template ``avg%(observations)s.sdb``.
    For each season, there are four tables named following the template 
    ``%(period)s_%(phase)s_%(ENSOindicator)``.
    Each table has N+1 columns: 
        * Station COOP ID (format ``COOP%06i``)
        * ENSO indicator (used to define the phase): in ('ONI', 'JMAI', 'MEI')
        * ENSO phase : in ('A', 'C', 'N', 'W')
        * N values for each season

    Parameters
    ----------
    observations: string
        String representing the observations to store.
    period : ('M', 'NDJ', 'DJF', 'JFM'), optional
        String representing the seasons. 
        Use 'M' for monthly, 'DJF' for 'DJF,MAM,JJA,SON'...
    ensostr : ('ONI', 'JMAI', 'MEI'), optional
        String representing the ENSO indicator to define ENSO phases
    """
    seasons = dict(monthly=['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN',
                            'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC', ],
                   JFM=['JFM', 'AMJ', 'JAS', 'OND'],
                   DJF=['DJF', 'MAM', 'JJA', 'SON'],
                   NDJ=['NDJ', 'FMA', 'MJJ', 'ASO'])

    # Get the seasonal frequency
    period = period.upper()
    period_to_freq = dict(M=hydro._c.FR_MTH,
                          MONTHLY=hydro._c.FR_MTH,
                          NDJ=hydro._c.FR_QTREOCT,
                          DJF=hydro._c.FR_QTRENOV,
                          JFM=hydro._c.FR_QTREDEC,)
    try:
        freq = period_to_freq[period]
    except KeyError:
        errmsg = "Invalid period '%s': should be in %s."
        raise ValueError(errmsg % (period, period_to_freq.keys()))

    # Get the names of the fields
    # fieldslist = ["COOPID text primary key", "ENSOI text", "phase text"]
    fieldslist = ["id integer primary key autoincrement",
                  "COOPID text", "ENSOI text", "phase text"]
    if period in ("M", "MONTHLY"):
        period = "monthly"
    fieldslist += ["%s real" % _ for _ in seasons[period]]
    nbfields = len(fieldslist)

    # Get the conversion function:
    if freq == hydro._c.FR_MTH:
        conversion_func = None
    else:
        if observations == 'rain':
            conversion_func = ma.sum
        else:
            conversion_func = ma.mean

    # Load the ENSO information
    ensostr = ensostr.upper()
    if ensostr == 'ONI':
        ENSO = enso.load_oni()
    elif ensostr == 'JMAI':
        ENSO = enso.load_jma()
    elif ensostr == 'MEI':
        raise NotImplementedError
    else:
        errmsg = "Invalid ENSO indicator '%s': should be in ('ONI','JMAI','MEI')"
        raise ValueError(errmsg % ensostr)

    # Get the monthly series from the datatable and set the ENSO indicator
    tbname = "series_monthly_%s" % observations
    monthly = sql.tsfromsqlite(dbname, tbname, freq="M")
    monthly = enso.set_ensoindicator(monthly, ENSO)

    # Define dictionaries storing the averages
    avg_r = {}
    # Loop on the stations
    for station in monthly.dtype.names:
	    # Get the current station
        current = monthly[station]
        # Get the season
        seasonal = current.convert(freq, func=conversion_func)
        if (observations == "rain") and (freq != hydro._c.FR_MTH):
            mask = hydro.time_series(current.mask, dates=current.dates)
            seasonal.mask = mask.convert(freq, func=ma.sum)
        # Get the values per phase
        coopid = station[-6:]
        avg_r[(coopid, ensostr, 'A')] = seasonal.convert("A").mean(0)
        avg_r[(coopid, ensostr, 'C')] = seasonal.cold.convert("A").mean(0)
        avg_r[(coopid, ensostr, 'N')] = seasonal.neutral.convert("A").mean(0)
        avg_r[(coopid, ensostr, 'W')] = seasonal.warm.convert("A").mean(0)

    # Get the database name
    detect_types = sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES
    connection = sqlite3.connect(dbname, detect_types=detect_types)
    # Define the creation/insertion lines
    tbname = "averages_%(period)s_%(observations)s" % locals()
    createstr = "create table %s (%s)" % (tbname, ", ".join(fieldslist))
    insertstr_template = "insert into %s values (%s)"
    insertstr = insertstr_template % (tbname, ", ".join(['?']*nbfields))
    # Create the table
    try:
        connection.execute(createstr)
    except sqlite3.OperationalError:
        pass
    # Define a generator for the values
    generator = ([None, ] + list(k) + list(v.astype(np.object).filled((None,)))
                 for (k, v) in avg_r.items())
    connection.executemany(insertstr, generator)
    connection.commit()
    connection.close()
Exemple #7
0
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
Exemple #8
0
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 setUp(self):
     data = [1, 4, 3, 2, 0, 1, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0.1, 5]
     self.rainfall = hydro.time_series(data, start_date=hydro.Date("M", "2001-01"))
     self.data = data