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_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
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
# 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.)
# 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
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()
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
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:
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)
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):])
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()
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,