Ejemplo n.º 1
0
def test_update_ts_settings(request, pstore):
    pstore.set_check_model_series_values(False)

    o = pstore.get_oseries("oseries2")
    ml = ps.Model(o.loc[:"2013"], name="ml_oseries2")

    pnam = pstore.get_nearest_stresses("oseries2", kind="prec").iloc[0]
    p = pstore.get_stresses(pnam)
    enam = pstore.get_nearest_stresses("oseries2", kind="evap").iloc[0]
    e = pstore.get_stresses(enam)
    rm = ps.RechargeModel(p.loc[:"2013"], e.loc[:"2013"])
    ml.add_stressmodel(rm)
    tmax = p.index.intersection(e.index).max()

    p2 = pstore.get_stresses("prec1")
    sm = ps.StressModel(p2.loc[:"2013"], ps.Exponential, "prec")
    ml.add_stressmodel(sm)

    pstore.add_model(ml)

    ml2 = pstore.get_models(ml.name, update_ts_settings=True)

    try:
        assert ml2.oseries.settings["tmax"] == o.index[-1]
        assert ml2.stressmodels["recharge"].prec.settings["tmax"] == tmax
        assert ml2.stressmodels["recharge"].evap.settings["tmax"] == tmax
        assert ml2.stressmodels["prec"].stress[0].settings["tmax"] == \
            p2.index[-1]
    except AssertionError:
        pstore.del_models("ml_oseries2")
        pstore.set_check_model_series_values(True)
        raise
    return
Ejemplo n.º 2
0
def test_save_and_load_model(request, pstore):
    ml = pstore.create_model("oseries2")
    sm = ps.StressModel(pstore.get_stresses('well1'), ps.Gamma,
                        name='well1', settings="well")
    ml.add_stressmodel(sm)
    ml.solve(tmin='1993-1-1')
    evp_ml = ml.stats.evp()
    pstore.add_model(ml, overwrite=True)
    ml2 = pstore.get_models(ml.name)
    evp_ml2 = ml2.stats.evp()
    assert allclose(evp_ml, evp_ml2)
    assert pst.util.compare_models(ml, ml2)
    return ml, ml2
Ejemplo n.º 3
0
    def pastas_model(self, figdir=None):
        """Create and sove Pastas model using generated head and noise"""

        # create Pasytas model
        head_noise = self.head + self.noise
        self.ml = ps.Model(head_noise)
        self.sm = ps.StressModel(self.rain,
                                 ps.Gamma,
                                 name='recharge',
                                 settings='prec')
        self.ml.add_stressmodel(self.sm)
        self.ml.add_noisemodel(ps.ArmaModel())

        # solve Pastas model
        self.ml.solve(noise=True, report=False)

        if figdir is not None:
            # plot figure with model diagnostics

            axes = self.ml.plots.results(figsize=(10, 5))
            fig = axes[0].get_figure()

            # add real step function to plot
            Atrue = self.detpar['Atrue']
            ntrue = self.detpar['ntrue']
            atrue = self.detpar['atrue']
            axes[-1].plot(ps.Gamma().step([Atrue, ntrue, atrue]))

            # figname = f'Atrue={Atrue} ntrue={ntrue} atrue={atrue}'
            figname = self.model_name()
            fig.suptitle(figname, fontsize=12)

            figpath = f'{figdir}Model {figname}.jpg'
            fig.savefig(figpath)
            plt.close()

        return self.ml
Ejemplo n.º 4
0
# Add precipitation
IN = meny.IN['Precipitation']['values']
IN.index = IN.index.round("D")
IN.name = 'Precipitation'
IN2 = meny.IN['Evaporation']['values']
IN2.index = IN2.index.round("D")
IN2.name = 'Evaporation'
sm = ps.RechargeModel(IN, IN2, ps.Gamma, 'Recharge')
ml.add_stressmodel(sm)

# Add well extraction 2
IN = meny.IN['Extraction 2']
well = ps.TimeSeries(IN["values"], settings="well")
# extraction amount counts for the previous month
sm1 = ps.StressModel(well, ps.Hantush, 'Extraction_2', up=False)

# Add well extraction 3
IN = meny.IN['Extraction 3']
well = ps.TimeSeries(IN["values"], settings="well")
# extraction amount counts for the previous month
sm2 = ps.StressModel(well, ps.Hantush, 'Extraction_3', up=False)

# add_stressmodels also allows addings multiple stressmodels at once
ml.add_stressmodel([sm1, sm2])

# Solve
ml.solve(tmax="1995")

ax = ml.plots.decomposition(ytick_base=1.)
Ejemplo n.º 5
0
# Create the time series model
ml = ps.Model(obs)

# Read weather data
prec = ps.read_knmi('data/neerslaggeg_HEIBLOEM-L_967-2.txt', variables='RD')
evap = ps.read_knmi('data/etmgeg_380.txt', variables='EV24')

# Create stress
if False:
    sm = ps.StressModel2(stress=[prec, evap],
                         rfunc=ps.Exponential,
                         name='recharge')
    ml.add_stressmodel(sm)
elif False:
    sm = ps.StressModel(prec, rfunc=ps.Exponential, name='prec')
    ml.add_stressmodel(sm)
    sm = ps.StressModel(evap, rfunc=ps.Exponential, name='evap', up=False)
    ml.add_stressmodel(sm)
else:
    sm = ps.stressmodels.NoConvModel(prec,
                                     rfunc=ps.Exponential,
                                     name='prec_no_conv')
    ml.add_stressmodel(sm)
    sm = ps.stressmodels.NoConvModel(evap,
                                     rfunc=ps.Exponential,
                                     name='evap_no_conv',
                                     up=False)
    ml.add_stressmodel(sm)

# Solve and plot
Ejemplo n.º 6
0
                   index_col="Date",
                   parse_dates=True)

# Create the time series model
ml = ps.Model(head, name="head")

# read weather data
rain = pd.read_csv("notebooks/data_notebook_5/prec_wellex.csv",
                   index_col="Date",
                   parse_dates=True)
evap = pd.read_csv("notebooks/data_notebook_5/evap_wellex.csv",
                   index_col="Date",
                   parse_dates=True)

# Create stress
rm = ps.RechargeModel(prec=rain,
                      evap=evap,
                      rfunc=ps.Exponential,
                      name='recharge')
ml.add_stressmodel(rm)

well = pd.read_csv("notebooks/data_notebook_5/well_wellex.csv",
                   index_col="Date",
                   parse_dates=True) / 1e6
sm = ps.StressModel(well, rfunc=ps.Exponential, name="well", up=False)
ml.add_stressmodel(sm)

# Solve
ml.solve(noise=True)
ml.plots.results()
Ejemplo n.º 7
0
def test_add_stressmodels():
    ml = test_create_model()
    sm1 = ps.StressModel(rain, rfunc=ps.Exponential, name='prec')
    sm2 = ps.StressModel(evap, rfunc=ps.Exponential, name='evap')
    ml.add_stressmodel([sm1, sm2])
    return ml
Ejemplo n.º 8
0
evap1_r = evap_r.resample('D').sum()
evap2_r = evap_r.resample('D').sum()
evap1_p = evap_p.resample('D').sum()
evap2_p = evap_p.resample('D').sum().loc[gw_val.index, ]

# Calculate precipitation excess
recharge1 = recharge[:gw.index[len(gw.index) - 1]]
recharge2 = recharge[gw_val.index[0]:gw_val.index[len(gw_val.index) - 1]]
"""
Create initial Pastas model with historical dataset

"""

ml = ps.Model(gwl1, name="GWL")  # Create the Pastas model
ts1 = ps.StressModel(
    recharge1, ps.FourParam,
    name='recharge')  # create stressmodel for precipitation excess *
ml.add_stressmodel(ts1)  # Add stressmodel to Pastas model
ml.solve()  # Solve the Pastas model

# Analyse results
ml.stats.summary()
ml.plots.results()
"""
Real time simulation

"""
# Create real-time simulation object
rtc = rt_simulation(ml, "test")

# Forecasts of the groundwater level for a year ahead based on observed precipitation excess:
Ejemplo n.º 9
0
    def update(self, forcing, oseries, selection):
        """ 
        Update the model with newly observed data
        
        Parameters
        ----------
        forcing: Pandas dataframe
            Dataframe that holds the newly observed values of the stresses. 
            NOTE: column names should correspond to the names of the stresses
            in the stressmodels of the Pastas model. The index column should consist
            of the dates of observations (Timestamps). The first date should succeed 
            the last date of the oseries & forcing dataset that are currently 
            included in the Pastas model.
        oseries: Pandas dataframe
            Dataframe that holds the newly observed values of the oseries. It
            should consist of one column containing the oseries.
            NOTE: the column name should equal the column name of the oseries 
            in the Pastas model. The index should consist of the dates of 
            observation (Timestamps). The first date should succeed the last date 
            of the oseries & forcing dataset that are currently included in the 
            Pastas model.
        """

        # Update forcing data
        forc = forcing.copy()
        initial_data = self.model.get_stress(
            self.stressmodelnames[0])[:].to_frame()
        initial_data.columns = [self.stressmodelnames[0]]
        for i in range(len(list(forcing.columns)) - 1):
            initial_data[self.stressmodelnames[i + 1]] = self.model.get_stress(
                self.stressmodelnames[i + 1])[:]
        forc = initial_data.append(forc[:])

        # Update oseries
        new_oseries = self.model.oseries.series.to_frame().append(oseries[:])
        if selection != 'total':
            new_oseries = new_oseries[new_oseries.index[len(new_oseries) - 1] -
                                      timedelta(days=selection):]

        # Create new model
        new_model = ps.Model(new_oseries, name="forecast")

        # Add stressmodels
        for i in range(len(self.stressmodelnames)):
            # The forecast function automaticly infers the response functions from the stressmodels
            if self.stressmodeltypes[i] == 'Gamma':
                responsefunc = ps.Gamma
            elif self.stressmodeltypes[i] == 'Hantush':
                responsefunc = ps.Hantush
            elif self.stressmodeltypes[i] == 'Exponential':
                responsefunc = ps.Exponential
            elif self.stressmodeltypes[i] == 'One':
                responsefunc = ps.One
            elif self.stressmodeltypes[i] == 'FourParam':
                responsefunc = ps.FourParam
            elif self.stressmodeltypes[i] == 'DoubleExponential':
                responsefunc = ps.DoubleExponential
            elif self.stressmodeltypes[i] == 'Polder':
                responsefunc = ps.Polder
            ts = ps.StressModel(forc[self.stressmodelnames[i]],
                                responsefunc,
                                name=self.stressmodelnames[i])

            # Add the stressmodels to the new model
            new_model.add_stressmodel(ts)

            if self.model.constant:
                c = ps.Constant()
                new_model.add_constant(c)
            if self.model.noisemodel:
                n = ps.NoiseModel()
                new_model.add_noisemodel(n)
            if self.model.transform:
                tt = ps.ThresholdTransform()
                new_model.add_transform(tt)

        # Solve the new model and initialise the real-time simulation overnew
        new_model.solve()
        self.__init__(new_model, self.name)
Ejemplo n.º 10
0
    def forecast(self, forcing):
        """ 
        Perform a forecast with timeseries containing the expected future values
        of the stresses. The timeseries of stresses in the Pastas model are 
        temporarly complemented with future values and a simulation is performed
        using the current parameter settings.
        
        Parameters:
        -----------
        forcing: Pandas Dataframe
            Dataframe that holds expected values of the stresses in the future. 
            NOTE: column names should correspond to the names of the stresses
            in the stressmodels of the Pastas model. The index column should consist
            of the dates (Timestamps). The first date should succeed the last date 
            of the oseries & forcing dataset that are currently included in the 
            Pastas model.
            
        Returns: Dataframe with forecasted values 
            
        """

        # Check wether stresses in forcing dataframe correspond with the stresses in the model
        if self.stressmodelnames != list(forcing.columns):
            return (
                "stresses in forcing data do not correspond with stresses in stressmodels"
            )

        # Create forecasting dataset (stresses)
        initial_data = self.model.get_stress(
            self.stressmodelnames[0])[:].to_frame()
        initial_data.columns = [self.stressmodelnames[0]]
        for ii in range(len(list(forcing.columns)) - 1):
            initial_data[self.stressmodelnames[ii +
                                               1]] = self.model.get_stress(
                                                   self.stressmodelnames[ii +
                                                                         1])[:]
        forc = initial_data.append(forcing[:])

        # Create a temporary model for forecasting
        forecast_ml = ps.Model(self.model.oseries, name="forecast")
        for i in range(len(self.stressmodelnames)):
            # The forecast function automaticly infers the response functions from the stressmodels
            if self.stressmodeltypes[i] == 'Gamma':
                responsefunc = ps.Gamma
            elif self.stressmodeltypes[i] == 'Hantush':
                responsefunc = ps.Hantush
            elif self.stressmodeltypes[i] == 'Exponential':
                responsefunc = ps.Exponential
            elif self.stressmodeltypes[i] == 'One':
                responsefunc = ps.One
            elif self.stressmodeltypes[i] == 'FourParam':
                responsefunc = ps.FourParam
            elif self.stressmodeltypes[i] == 'DoubleExponential':
                responsefunc = ps.DoubleExponential
            elif self.stressmodeltypes[i] == 'Polder':
                responsefunc = ps.Polder
            ts = ps.StressModel(forc[self.stressmodelnames[i]],
                                responsefunc,
                                name=self.stressmodelnames[i])
            # The created stressmodels are added to the forecast model
            forecast_ml.add_stressmodel(ts)
        if self.model.constant:
            forecast_ml.constant = self.model.copy().constant
        if self.model.noisemodel:
            forecast_ml.noisemodel = self.model.copy().noisemodel
        if self.model.transform:
            forecast_ml.transform = self.model.copy().transform

        # Perform a simulation with the forecast model and return the forecasted values of the oseries
        forecast = forecast_ml.simulate(parameters=self.p)
        return (forecast[len(forc) - len(forcing):])
Ejemplo n.º 11
0
                   parse_dates=True)

# Create the time series model
ml = ps.Model(head, name="groundwater head")

# read weather data
rain = pd.read_csv("notebooks/data_notebook_7/prec_wellex.csv",
                   index_col="Date",
                   parse_dates=True)
evap = pd.read_csv("notebooks/data_notebook_7/evap_wellex.csv",
                   index_col="Date",
                   parse_dates=True)

# Create stress
rm = ps.RechargeModel(prec=rain,
                      evap=evap,
                      rfunc=ps.Exponential,
                      recharge="Linear",
                      name='recharge')
ml.add_stressmodel(rm)

well = pd.read_csv("notebooks/data_notebook_7/well_wellex.csv",
                   index_col="Date",
                   parse_dates=True)
sm = ps.StressModel(well, rfunc=ps.Gamma, name="well", up=False)
ml.add_stressmodel(sm)

# Solve
ml.solve(noise=True, tmax="2010")
ml.plots.results()
Ejemplo n.º 12
0
IN2 = meny.IN['Evaporation']['values']
IN2.index = IN2.index.round("D")
IN2.name = 'Evaporation'
sm = ps.StressModel2([IN, IN2], ps.Gamma, 'Recharge')
ml.add_stressmodel(sm)

# Add well extraction 1
IN = meny.IN['Extraction 1']
well = ps.TimeSeries(IN["values"],
                     freq_original="M",
                     freq="D",
                     settings="well")
# extraction amount counts for the previous month
sm = ps.StressModel(well,
                    ps.Hantush,
                    'Extraction_1',
                    up=False,
                    settings="well")
ml.add_stressmodel(sm)

# Add well extraction 2
IN = meny.IN['Extraction 2']
well = ps.TimeSeries(IN["values"],
                     freq_original="M",
                     freq="D",
                     settings="well")
# extraction amount counts for the previous month
sm = ps.StressModel(well,
                    ps.Hantush,
                    'Extraction_2',
                    up=False,
ml_lwph4b = ps.Model(lwph4b, name="LWPH4b")

## build stress models:
# recharge
precSurplus_mm = metdata["prcp_mm"] - metdata["ETo_mm"]
#sm_rech = ps.RechargeModel(metdata["prcp_mm"], metdata["ETo_mm"], rfunc=ps.Gamma, name="recharge")
sm_rech = ps.RechargeModel(metdata["prcp_mm"],
                           metdata["ETo_mm"],
                           rfunc=ps.Exponential,
                           recharge=ps.rch.FlexModel(),
                           name="recharge")

# pumping
wuse = ps.StressModel(wusedata,
                      rfunc=ps.Hantush,
                      name="well",
                      settings="well",
                      up=False)

# river stage
river = (hydrodata["stage_masl"] -
         hydrodata["stage_masl"].min()).asfreq("D").fillna(0)
sm_river = ps.StressModel(river,
                          rfunc=ps.One,
                          name="river",
                          settings="waterlevel")

# HPA water levels
lwph4c = (hydrodata["LWPH4c"] - hydrodata["LWPH4c"].min()).asfreq(
    "D")  # normalized to minimum observed value
sm_lwph4c = ps.StressModel(lwph4c,