In [3]:
from __future__ import print_function
import os
import numpy as np
import pyemu
from pyemu import Pst
We need to pass the name of a pest control file to instantiate the class. The class instance (or object) is assigned to the variable p.
In [4]:
pst_name = os.path.join("..", "..", "examples", "henry","pest.pst")
p = Pst(pst_name)
Now all of the relevant parts of the pest control file are attributes of the object. For example, the parameter_data, observation data, and prior information are available as pandas dataframes.
In [5]:
p.parameter_data.head()
Out[5]:
In [6]:
p.observation_data.head()
Out[6]:
In [7]:
p.prior_information.head()
Out[7]:
A residual file (.rei or res) can also be passed to the resfile argument at instantiation to enable some simple residual analysis and weight adjustments. If the residual file is in the same directory as the pest control file and has the same base name, it will be accessed automatically:
In [8]:
p.res.head()
Out[8]:
The pst class has some @decorated convience methods related to the residuals allowing the user
to access the values and print in a straightforward way.
In [9]:
print(p.phi,p.phi_components)
Some additional @decorated convience methods:
In [10]:
print(p.npar,p.nobs,p.nprior)
In [11]:
print(p.par_groups,p.obs_groups)
Printing the attribue type shows that some are returned as lists and others single values.
In [14]:
print(type(p.par_names)) # all parameter names
print(type(p.adj_par_names)) # adjustable parameter names
print(type(p.obs_names)) # all observation names
print(type(p.nnz_obs_names)) # non-zero weight observations
print(type(p.phi)) # float value that is the weighted total objective function
The "control_data" section of the pest control file is accessible in the Pst.control_data attribute:
In [15]:
print('jacupdate = {0}'.format(p.control_data.jacupdate))
print('numlam = {0}'.format(p.control_data.numlam))
p.control_data.numlam = 100
print('numlam has been changed to --> {0}'.format(p.control_data.numlam))
The Pst class also exposes a method to get a new Pst instance with a subset of parameters and or obseravtions. Note this method does not propogate prior information to the new instance:
In [16]:
pnew = p.get(p.par_names[:10],p.obs_names[-10:])
print(pnew.prior_information)
You can also write a pest control file with altered parameters, observations, and/or prior information:
In [17]:
pnew.write("test.pst")
Some other methods in Pst include:
In [18]:
# add preferred value regularization with weights proportional to parameter bounds
pyemu.utils.helpers.zero_order_tikhonov(pnew)
pnew.prior_information.head()
Out[18]:
In [19]:
# add preferred value regularization with unity weights
pyemu.utils.helpers.zero_order_tikhonov(pnew,parbounds=False)
pnew.prior_information.head()
Out[19]:
Some more res functionality
In [20]:
# adjust observation weights to account for residual phi components
#pnew = p.get()
print(p.phi, p.nnz_obs, p.phi_components)
p.adjust_weights_resfile()
print(p.phi, p.nnz_obs, p.phi_components)
adjust observation weights by an arbitrary amount by groups:
In [21]:
print(p.phi, p.nnz_obs, p.phi_components)
grp_dict = {"head":100}
p.adjust_weights(obsgrp_dict=grp_dict)
print(p.phi, p.nnz_obs, p.phi_components)
adjust observation weights by an arbitrary amount by individual observations:
In [22]:
print(p.phi, p.nnz_obs, p.phi_components)
obs_dict = {"h_obs01_1":25}
p.adjust_weights(obs_dict=obs_dict)
print(p.phi, p.nnz_obs, p.phi_components)
setup weights inversely proportional to the observation values
In [23]:
p.adjust_weights_resfile()
print(p.phi, p.nnz_obs, p.phi_components)
p.proportional_weights(fraction_stdev=0.1,wmax=20.0)
print(p.phi, p.nnz_obs, p.phi_components)