Esempio 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
Esempio n. 2
0
def test_create_model():
    obs = read_csv("tests/data/obs.csv",
                   index_col=0,
                   parse_dates=True,
                   squeeze=True)
    ml = ps.Model(obs, name="Test_Model")
    return ml
Esempio n. 3
0
def test_create_model():
    obs = read_csv("tests/data/obs.csv",
                   index_col=0,
                   parse_dates=True,
                   squeeze=True)
    ml = ps.Model(obs, name="Test_Model")
    sm = test_create_rechargemodel()
    ml.add_stressmodel(sm)
    return ml
Esempio n. 4
0
def create_model():
    obs = read_csv("tests/data/obs.csv", index_col=0, parse_dates=True,
                   squeeze=True)
    rain = read_csv("tests/data/rain.csv", index_col=0, parse_dates=True,
                    squeeze=True)
    evap = read_csv("tests/data/evap.csv", index_col=0, parse_dates=True,
                    squeeze=True)
    ml = ps.Model(obs, name="Test_Model")
    sm = ps.RechargeModel(prec=rain, evap=evap, rfunc=ps.Exponential,
                          name='recharge')
    ml.add_stressmodel(sm)
    return ml
Esempio n. 5
0
    def create_model(self,
                     name: str,
                     modelname: str = None,
                     add_recharge: bool = True,
                     recharge_name: str = "recharge") -> ps.Model:
        """Create a pastas Model.

        Parameters
        ----------
        name : str
            name of the oseries to create a model for
        modelname : str, optional
            name of the model, default is None, which uses oseries name
        add_recharge : bool, optional
            add recharge to the model by looking for the closest
            precipitation and evaporation timeseries in the stresses
            library, by default True
        recharge_name : str
            name of the RechargeModel

        Returns
        -------
        pastas.Model
            model for the oseries

        Raises
        ------
        KeyError
            if data is stored as dataframe and no column is provided
        ValueError
            if timeseries is empty
        """
        # get oseries metadata
        meta = self.conn.get_metadata("oseries", name, as_frame=False)
        ts = self.conn.get_oseries(name)

        # convert to Timeseries and create model
        if not ts.dropna().empty:
            ts = ps.TimeSeries(ts,
                               name=name,
                               settings="oseries",
                               metadata=meta)
            if modelname is None:
                modelname = name
            ml = ps.Model(ts, name=modelname, metadata=meta)

            if add_recharge:
                self.add_recharge(ml, recharge_name=recharge_name)
            return ml
        else:
            raise ValueError("Empty timeseries!")
Esempio n. 6
0
def test_rfunc(rfunc_name):
    if rfunc_name not in []:
        # Import and check the observed groundwater time series
        obs = ps.read_dino('tests/data/dino_gwl_data.csv')

        # read weather data
        rain = ps.read_knmi('tests/data/knmi_rain_data.txt', variables='RD')
        evap = ps.read_knmi('tests/data/knmi_evap_data.txt', variables='EV24')

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

        ## Create stress
        rfunc = getattr(ps.rfunc, rfunc_name)
        sm = ps.StressModel2(stress=[rain, evap], rfunc=rfunc, name='test_sm')
        ml.add_stressmodel(sm)

        # Solve the time series model
        ml.solve()
Esempio n. 7
0
    def create_model(self, name: str, add_recharge: bool = True) -> ps.Model:
        """Create a new pastas Model.

        Parameters
        ----------
        name : str
            name of the oseries to create a model for
        add_recharge : bool, optional
            add recharge to the model by looking for the closest
            precipitation and evaporation timeseries in the stresses
            library, by default True

        Returns
        -------
        pastas.Model
            model for the oseries

        Raises
        ------
        KeyError
            if data is stored as dataframe and no column is provided
        ValueError
            if timeseries is empty
        """
        # get oseries metadata
        meta = self.conn.get_metadata("oseries", name, as_frame=False)
        ts = self.conn.get_oseries(name)
        # get right column of data
        ts = self.conn._get_dataframe_values(
            "oseries", name, ts, metadata=meta)

        # convert to Timeseries and create model
        if not ts.dropna().empty:
            ts = ps.TimeSeries(ts, name=name, settings="oseries",
                               metadata=meta)
            ml = ps.Model(ts, name=name, metadata=meta)

            if add_recharge:
                self.add_recharge(ml)
            return ml
        else:
            raise ValueError("Empty timeseries!")
Esempio n. 8
0
def test_model():
    # Import and check the observed groundwater time series
    obs = ps.read_dino('tests/data/dino_gwl_data.csv')

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

    # read weather data
    rain = ps.read_knmi('tests/data/knmi_rain_data.txt', variables='RD')
    evap = ps.read_knmi('tests/data/knmi_evap_data.txt', variables='EV24')

    ## Create stress
    sm = ps.StressModel2(stress=[rain, evap],
                         rfunc=ps.Exponential,
                         name='recharge')
    ml.add_stressmodel(sm)

    # Solve the time series model
    ml.solve()

    return 'model succesfull'
Esempio n. 9
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
Esempio n. 10
0
    def add_model(self, oseries, model_name=None, **kwargs):
        """Method to add a Pastas Model instance based on one of the oseries.

        Parameters
        ----------
        oseries: str
            string with the exact names of one of the oseries indices.
        model_name: str
            Name of the model
        kwargs: dict
            any arguments that are taken by the Pastas Model instance can be
            provided.

        Returns
        -------
        ml: pastas.Model
            Pastas Model generated with the oseries and arguments provided.

        """
        if model_name is None:
            model_name = oseries

        # Validate name and ml_name before continuing
        if model_name in self.models.keys():
            logger.error("Model name is not unique, provide a new ml_name.")
        if oseries not in self.oseries.index:
            logger.error("Oseries name is not present in the database. "
                         "Make sure to provide a valid oseries name.")

        oseries = self.oseries.loc[oseries, "series"]
        ml = ps.Model(oseries, name=model_name, **kwargs)

        # Add new model to the models dictionary
        self.models[model_name] = ml

        return ml
Esempio n. 11
0
def load_model(data):
    # Create model
    oseries = ps.TimeSeries(**data["oseries"])

    if "constant" in data.keys():
        constant = data["constant"]
    else:
        constant = False

    if "settings" in data.keys():
        settings = data["settings"]
    else:
        settings = dict()

    if "metadata" in data.keys():
        metadata = data["metadata"]
    else:
        metadata = dict(name="Model")  # Make sure there is a name

    if "name" in data.keys():
        name = data["name"]
    else:
        name = metadata["name"]

    if "noisemodel" in data.keys():
        noise = True
    else:
        noise = False

    ml = ps.Model(oseries, constant=constant, noisemodel=noise, name=name,
                  metadata=metadata, settings=settings)
    if "file_info" in data.keys():
        ml.file_info.update(data["file_info"])

    # Add stressmodels
    for name, ts in data["stressmodels"].items():
        stressmodel = getattr(ps.stressmodels, ts["stressmodel"])
        ts.pop("stressmodel")
        ts["rfunc"] = getattr(ps.rfunc, ts["rfunc"])
        for i, stress in enumerate(ts["stress"]):
            ts["stress"][i] = ps.TimeSeries(**stress)
        stressmodel = stressmodel(**ts)
        ml.add_stressmodel(stressmodel)

    # Add transform
    if "transform" in data.keys():
        transform = getattr(ps.transform, data["transform"]["transform"])
        data["transform"].pop("transform")
        transform = transform(**data["transform"])
        ml.add_transform(transform)

    # Add noisemodel if present
    if "noisemodel" in data.keys():
        n = getattr(ps.noisemodels, data["noisemodel"]["type"])()
        ml.add_noisemodel(n)

    # Add parameters, use update to maintain correct order
    ml.parameters = ml.get_init_parameters(noise=ml.settings["noise"])
    ml.parameters.update(data["parameters"])
    ml.parameters = ml.parameters.apply(pd.to_numeric, errors="ignore")
    return ml
Esempio n. 12
0
test the functioning of Pastas recharge module during development.

Author: R.A. Collenteur, University of Graz.

"""
import pandas as pd

import pastas as ps

# read observations
head = pd.read_csv("notebooks/data_notebook_5/head_wellex.csv",
                   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)
Esempio n. 13
0
    def load(self, fyaml: str) -> List[ps.Model]:
        """Load Pastas YAML file.

        Note: currently supports RechargeModel, StressModel and WellModel.

        Parameters
        ----------
        fyaml : str
            path to file

        Returns
        -------
        models : list
            list containing pastas model(s)

        Raises
        ------
        ValueError
            if insufficient information is provided to construct pastas model
        NotImplementedError
            if unsupported stressmodel is encountered
        """

        with open(fyaml, "r") as f:
            yml = yaml.load(f, Loader=yaml.CFullLoader)

        models = []

        for mlnam in yml.keys():

            mlyml = yml[mlnam]

            # get oseries + metadata
            if isinstance(mlyml["oseries"], dict):
                onam = str(mlyml["oseries"]["name"])
                settings = mlyml["oseries"].pop("settings", "oseries")
                _ = mlyml.pop("oseries")
            else:
                onam = str(mlyml.pop("oseries"))
                settings = "oseries"

            logger.info(f"Building model '{mlnam}' for oseries '{onam}'")
            o, ometa = self.pstore.get_oseries(
                onam, return_metadata=True)

            # create model to obtain default model settings
            o_ts = ps.TimeSeries(o, metadata=ometa, settings=settings)
            ml = ps.Model(o_ts, name=mlnam, metadata=ometa)
            mldict = ml.to_dict(series=True)

            # update with stored model settings
            if "settings" in mlyml:
                mldict["settings"].update(mlyml["settings"])

            # stressmodels
            for smnam, smyml in mlyml["stressmodels"].items():

                # set name if not provided
                if smyml is not None:
                    name = smyml.get("name", smnam)
                else:
                    name = smnam
                logger.info(f"| parsing stressmodel: '{name}'")

                # check whether smtyp is defined
                if smyml is not None:
                    if "stressmodel" in smyml:
                        smtyp = True
                    else:
                        smtyp = False
                else:
                    smtyp = False

                # check if RechargeModel based on name if smtyp not defined
                if (smnam.lower() in ["rch", "rech", "recharge",
                                      "rechargemodel"]) and not smtyp:
                    logger.info(
                        "| assuming RechargeModel based on stressmodel name.")
                    # check if stressmodel dictionary is empty, create (nearly
                    # empty) dict so defaults are used
                    if smyml is None:
                        mlyml["stressmodels"][smnam] = {"name": "recharge"}
                        smyml = mlyml["stressmodels"][smnam]
                    if "name" not in smyml:
                        smyml["name"] = smnam
                    smtyp = smyml.get("stressmodel", "RechargeModel")
                else:
                    # if no info is provided, raise error,
                    # cannot make any assumptions for non-RechargeModels
                    if smyml is None:
                        raise ValueError("Insufficient information "
                                         f"for stressmodel '{name}'!")
                    # get stressmodel type, with default StressModel
                    if "stressmodel" in smyml:
                        smtyp = smyml["stressmodel"]
                    else:
                        logger.info(
                            "| no 'stressmodel' type provided, "
                            "using 'StressModel'")
                        smtyp = "StressModel"

                # parse dictionary based on smtyp
                if smtyp in ["RechargeModel", "TarsoModel"]:
                    # parse RechargeModel
                    sm = self._parse_rechargemodel_dict(smyml, onam=onam)

                    # turn off constant for TarsoModel
                    if smtyp == "TarsoModel":
                        mldict["constant"] = False
                elif smtyp == "StressModel":
                    # parse StressModel
                    sm = self._parse_stressmodel_dict(smyml, onam=onam)
                elif smtyp == "WellModel":
                    # parse WellModel
                    sm = self._parse_wellmodel_dict(smyml, onam=onam)
                else:
                    raise NotImplementedError(
                        "PastaStore.yaml interface does "
                        f"not (yet) support '{smtyp}'!")

                # add to list
                smyml.update(sm)

            # update model dict w/ default settings with loaded data
            mldict.update(mlyml)

            # add name to dictionary if not already present
            if "name" not in mldict:
                mldict["name"] = mlnam

            # convert warmup and time_offset to panads.Timedelta
            if "warmup" in mldict["settings"]:
                mldict["settings"]["warmup"] = pd.Timedelta(
                    mldict["settings"]["warmup"])
            if "time_offset" in mldict["settings"]:
                mldict["settings"]["time_offset"] = pd.Timedelta(
                    mldict["settings"]["time_offset"])

            # load model
            ml = ps.io.base._load_model(mldict)
            models.append(ml)

        return models
Esempio n. 14
0
def _load_model(data):
    """Internal method to create a model from a dictionary."""
    # Create model
    _remove_keyword(data["oseries"])
    oseries = ps.TimeSeries(**data["oseries"])

    if "constant" in data.keys():
        constant = data["constant"]
    else:
        constant = False

    if "metadata" in data.keys():
        metadata = data["metadata"]
    else:
        metadata = None

    if "name" in data.keys():
        name = data["name"]
    else:
        name = None

    if "noisemodel" in data.keys():
        noise = True
    else:
        noise = False

    ml = ps.Model(oseries,
                  constant=constant,
                  noisemodel=noise,
                  name=name,
                  metadata=metadata)

    if "settings" in data.keys():
        ml.settings.update(data["settings"])
    if "file_info" in data.keys():
        ml.file_info.update(data["file_info"])

    # Add stressmodels
    for name, ts in data["stressmodels"].items():
        stressmodel = getattr(ps.stressmodels, ts["stressmodel"])
        ts.pop("stressmodel")
        if "rfunc" in ts.keys():
            ts["rfunc"] = getattr(ps.rfunc, ts["rfunc"])
        if "recharge" in ts.keys():
            ts["recharge"] = getattr(ps.recharge, ts["recharge"])()
        if "stress" in ts.keys():
            for i, stress in enumerate(ts["stress"]):
                _remove_keyword(stress)
                ts["stress"][i] = ps.TimeSeries(**stress)
        if "prec" in ts.keys():
            _remove_keyword(ts["prec"])
            ts["prec"] = ps.TimeSeries(**ts["prec"])
        if "evap" in ts.keys():
            _remove_keyword(ts["evap"])
            ts["evap"] = ps.TimeSeries(**ts["evap"])
        if "temp" in ts.keys() and ts["temp"] is not None:
            ts["temp"] = ps.TimeSeries(**ts["temp"])
        stressmodel = stressmodel(**ts)
        ml.add_stressmodel(stressmodel)

    # Add transform
    if "transform" in data.keys():
        transform = getattr(ps.transform, data["transform"]["transform"])
        data["transform"].pop("transform")
        transform = transform(**data["transform"])
        ml.add_transform(transform)

    # Add noisemodel if present
    if "noisemodel" in data.keys():
        n = getattr(ps.noisemodels, data["noisemodel"]["type"])()
        ml.add_noisemodel(n)

    # Add fit object to the model
    if "fit" in data.keys():
        fit = getattr(ps.solver, data["fit"]["name"])
        data["fit"].pop("name")
        ml.fit = fit(ml=ml, **data["fit"])

    # Add parameters, use update to maintain correct order
    ml.parameters = ml.get_init_parameters(noise=ml.settings["noise"])
    ml.parameters.update(data["parameters"])
    ml.parameters = ml.parameters.apply(to_numeric, errors="ignore")

    # When initial values changed
    for param, value in ml.parameters.loc[:, "initial"].iteritems():
        ml.set_parameter(name=param, initial=value)

    collect()

    return ml
Esempio n. 15
0
Author: R.A. Collenteur, University of Graz.

"""
import pandas as pd

import pastas as ps

ps.set_log_level("ERROR")

# read observations and create the time series model and make meters
obs = pd.read_csv("data/B32C0639001.csv", parse_dates=['date'],
                  index_col='date', squeeze=True)

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

# read weather data and make mm/d !
evap = ps.read_knmi("data/etmgeg_260.txt", variables="EV24").series * 1e3
rain = ps.read_knmi("data/etmgeg_260.txt", variables="RH").series * 1e3

# Initialize recharge model and create stressmodel
rch = ps.rch.FlexModel()
# rch = ps.rch.Berendrecht()
# rch = ps.rch.Linear()
sm = ps.RechargeModel(prec=rain, evap=evap, rfunc=ps.Gamma, recharge=rch)

ml.add_stressmodel(sm)

ml.solve(noise=True, tmin="1990")
Esempio n. 16
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):])
Esempio n. 17
0
"""
This test file is meant for developing purposes, providing an easy method to
test the functioning of Pastas recharge module during development.

Author: R.A. Collenteur, University of Graz.

"""
import pastas as ps

# read observations
obs = ps.read_dino('data/B58C0698001_1.csv')

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

# read weather data
rain = ps.read_knmi('data/neerslaggeg_HEIBLOEM-L_967-2.txt', variables='RD')
rain.multiply(1000)
evap = ps.read_knmi('data/etmgeg_380.txt', variables='EV24')
evap.multiply(1000)

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

## Solve
ml.solve()
Esempio n. 18
0
def test_create_model():
    ml = ps.Model(obs, name="Test_Model")
    return ml
wusedata = inputdata[["WaterUse_m3d"]] / 1e4
wusedata.plot(figsize=(10, 4))
plt.title('Pumping Data')
plt.ylabel('Flux [x1e4 m3/day]')
plt.xlabel('Time [annual data distributed within pumping season]')

## build model for full period (not separate wet/dry)
# identify min groundwater level
gw_min = hydrodata["LWPH4b"].min()

# normalize groundwater levels to min value
lwph4b = (hydrodata["LWPH4b"] - gw_min).asfreq("D")

# Create a model object by passing it the observed series
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",
Esempio n. 20
0
test the functioning of Pastas recharge module during development.

Author: R.A. Collenteur, University of Graz.

"""
import pandas as pd

import pastas as ps

# read observations
head = pd.read_csv("notebooks/data_notebook_7/head_wellex.csv",
                   index_col="Date",
                   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')
Esempio n. 21
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)
Esempio n. 22
0
"""
This test file is meant for developing purposes. Providing an easy method to
test the functioning of PASTAS during development.

"""
import pandas as pd
import pastas as ps

# Read observations
obs = ps.read_dino('data/B58C0698001_1.csv')
obs = obs.iloc[::5]
obs = obs[obs.index > pd.to_datetime('1-1-2010')]

# 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)
Esempio n. 23
0
def load_model(data):
    # Create model
    oseries = ps.TimeSeries(**data["oseries"])

    if "constant" in data.keys():
        constant = data["constant"]
    else:
        constant = False

    if "metadata" in data.keys():
        metadata = data["metadata"]
    else:
        metadata = None

    if "name" in data.keys():
        name = data["name"]
    else:
        name = None

    if "noisemodel" in data.keys():
        noise = True
    else:
        noise = False

    ml = ps.Model(oseries,
                  constant=constant,
                  noisemodel=noise,
                  name=name,
                  metadata=metadata)

    if "settings" in data.keys():
        ml.settings.update(data["settings"])
    if "file_info" in data.keys():
        ml.file_info.update(data["file_info"])
        ml.file_info["version"] = ps.__version__

    # Add stressmodels
    for name, ts in data["stressmodels"].items():
        stressmodel = getattr(ps.stressmodels, ts["stressmodel"])
        ts.pop("stressmodel")
        if "rfunc" in ts.keys():
            ts["rfunc"] = getattr(ps.rfunc, ts["rfunc"])
        if "stress" in ts.keys():
            for i, stress in enumerate(ts["stress"]):
                ts["stress"][i] = ps.TimeSeries(**stress)
        stressmodel = stressmodel(**ts)
        ml.add_stressmodel(stressmodel)

    # Add transform
    if "transform" in data.keys():
        transform = getattr(ps.transform, data["transform"]["transform"])
        data["transform"].pop("transform")
        transform = transform(**data["transform"])
        ml.add_transform(transform)

    # Add noisemodel if present
    if "noisemodel" in data.keys():
        n = getattr(ps.noisemodels, data["noisemodel"]["type"])()
        ml.add_noisemodel(n)

    # Add parameters, use update to maintain correct order
    ml.parameters = ml.get_init_parameters(noise=ml.settings["noise"])
    ml.parameters.update(data["parameters"])
    ml.parameters = ml.parameters.apply(to_numeric, errors="ignore")

    # When initial values changed
    for param, value in ml.parameters.loc[:, "initial"].iteritems():
        ml.set_initial(name=param, value=value)

    gc.collect()

    return ml
Esempio n. 24
0
Below is an example of a short script to simulate groundwater levels
(the csv-files with the data can be found in the examples directory on GitHub)
"""

import pandas as pd

import pastas as ps

oseries = pd.read_csv('data/head_nb1.csv',
                      parse_dates=['date'],
                      index_col='date',
                      squeeze=True)
rain = pd.read_csv('data/rain_nb1.csv',
                   parse_dates=['date'],
                   index_col='date',
                   squeeze=True)
evap = pd.read_csv('data/evap_nb1.csv',
                   parse_dates=['date'],
                   index_col='date',
                   squeeze=True)

ml = ps.Model(oseries)
sm = ps.RechargeModel(prec=rain,
                      evap=evap,
                      rfunc=ps.Exponential,
                      recharge="Linear",
                      name='recharge')
ml.add_stressmodel(sm)
ml.solve()
ml.plots.decomposition()
Esempio n. 25
0
"""
This test file is meant for developing purposes. Providing an easy method to
test the functioning of PASTA during development.

"""
import pastas as ps

# read observations
fname = 'data/B32D0136001_1.csv'
obs = ps.read.dinodata(fname)

# Create the time series model
ml = ps.Model(obs.series)

# read climate data
fname = 'data/KNMI_Bilt.txt'
RH = ps.read.knmidata(fname, variable='RH')
EV24 = ps.read.knmidata(fname, variable='EV24')
#rech = RH.series - EV24.series

# Create stress
#ts = Recharge(RH.series, EV24.series, Gamma, Preferential, name='recharge')
# ts = Recharge(RH.series, EV24.series, Gamma, Combination, name='recharge')
# ts = Tseries2(RH.series, EV24.series, Gamma, name='recharge')
ts = ps.Tseries(RH.series, ps.Gamma, name='precip', freq='D')
ts1 = ps.Tseries(EV24.series, ps.Gamma, name='evap', freq='D')
ml.add_tseries(ts)
ml.add_tseries(ts1)

# Add noise model
n = ps.NoiseModel()
Esempio n. 26
0
# In this example the MultiWell StressModel is showcased and tested.
# R.A. Collenteur - Artesia Water 2018

import pastas as ps
from pastas.stressmodels import WellModel

fname = 'data/MenyanthesTest.men'
meny = ps.read.MenyData(fname)

# Create the time series model
H = meny.H['Obsevation well']
ml = ps.Model(H['values'])

# Add precipitation
IN = meny.IN['Precipitation']['values']
IN.index = IN.index.round("D")
IN2 = meny.IN['Evaporation']['values']
IN2.index = IN2.index.round("D")
sm = ps.StressModel2([IN, IN2], ps.Gamma, 'Recharge')
ml.add_stressmodel(sm)

stresses = [
    meny.IN['Extraction 1']["values"], meny.IN['Extraction 2']["values"],
    meny.IN['Extraction 3']["values"]
]

w = WellModel(stresses, ps.Theis, radius=[1, 1, 1], name="Wells")

ml.add_stressmodel(w)
ml.solve()
ml.plots.decomposition()
rain1 = rain.resample('D').sum()
rain2 = rain.resample('D').sum()
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")