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
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
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
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
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!")
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()
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!")
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'
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
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
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
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)
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
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
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")
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):])
""" 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()
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",
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')
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)
""" 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)
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
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()
""" 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()
# 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")