def __load_parcov(self): """private method to set the parcov attribute from: a pest control file (parameter bounds) a pst object a matrix object an uncert file an ascii matrix file """ # if the parcov arg was not passed but the pst arg was, # reset and use parbounds to build parcov if not self.parcov_arg: if self.pst_arg: self.parcov_arg = self.pst_arg else: raise Exception("linear_analysis.__load_parcov(): " + "parcov_arg is None") if isinstance(self.parcov_arg, Matrix): self.__parcov = self.parcov_arg return if isinstance(self.parcov_arg, np.ndarray): # if the passed array is a vector, # then assume it is the diagonal of the parcov matrix if len(self.parcov_arg.shape) == 1: assert self.parcov_arg.shape[0] == self.jco.shape[1] isdiagonal = True else: assert self.parcov_arg.shape[0] == self.jco.shape[1] assert self.parcov_arg.shape[1] == self.jco.shape[1] isdiagonal = False self.logger.warn("linear_analysis.__load_parcov(): " + "instantiating parcov from ndarray, can't " + "verify parameters alignment with jco") self.__parcov = Matrix(x=self.parcov_arg, isdiagonal=isdiagonal, row_names=self.jco.col_names, col_names=self.jco.col_names) self.log("loading parcov") if isinstance(self.parcov_arg, str): # if the arg is a string ending with "pst" # then load parcov from parbounds if self.parcov_arg.lower().endswith(".pst"): self.__parcov = Cov.from_parbounds( self.parcov_arg, sigma_range=self.sigma_range, scale_offset=self.scale_offset) else: self.__parcov = self.__fromfile(self.parcov_arg, astype=Cov) # if the arg is a pst object elif isinstance(self.parcov_arg, Pst): self.__parcov = Cov.from_parameter_data( self.parcov_arg, sigma_range=self.sigma_range, scale_offset=self.scale_offset) else: raise Exception("linear_analysis.__load_parcov(): " + "parcov_arg must be a " + "matrix object or a file name: " + str(self.parcov_arg)) self.log("loading parcov")
def __load_obscov(self): """private method to set the obscov attribute from: a pest control file (observation weights) a pst object a matrix object an uncert file an ascii matrix file """ # if the obscov arg is None, but the pst arg is not None, # reset and load from obs weights if not self.obscov_arg: if self.pst_arg: self.obscov_arg = self.pst_arg else: raise Exception("linear_analysis.__load_obscov(): " + "obscov_arg is None") if isinstance(self.obscov_arg, Matrix): self.__obscov = self.obscov_arg return if isinstance(self.obscov_arg, np.ndarray): # if the ndarray arg is a vector, # assume it is the diagonal of the obscov matrix if len(self.obscov_arg.shape) == 1: assert self.obscov_arg.shape[0] == self.jco.shape[1] isdiagonal = True else: assert self.obscov_arg.shape[0] == self.jco.shape[0] assert self.obscov_arg.shape[1] == self.jco.shape[0] isdiagonal = False self.logger.warn("linear_analysis.__load_obscov(): " + "instantiating obscov from ndarray, " + "can't verify observation alignment with jco") self.__obscov = Matrix( x=self.obscov_arg, isdiagonal=isdiagonal, row_names=self.jco.row_names, col_names=self.jco.row_names, ) self.log("loading obscov") if isinstance(self.obscov_arg, str): if self.obscov_arg.lower().endswith(".pst"): self.__obscov = Cov.from_obsweights(self.obscov_arg) else: self.__obscov = self.__fromfile(self.obscov_arg, astype=Cov) elif isinstance(self.obscov_arg, Pst): self.__obscov = Cov.from_observation_data(self.obscov_arg) else: raise Exception("linear_analysis.__load_obscov(): " + "obscov_arg must be a " + "matrix object or a file name: " + str(self.obscov_arg)) self.log("loading obscov")
def G(self, singular_value): """get the parameter solution Matrix at a singular value V_1 * S_1^(_1) * U_1^T Parameters ---------- singular_value : int singular value to calc R at Returns ------- G : pyemu.Matrix parameter solution matrix at singular value """ if self.__G is not None and singular_value == self.__G_sv: return self.__G if singular_value == 0: self.__G_sv = 0 self.__G = Matrix( x=np.zeros((self.jco.ncol,self.jco.nrow)), row_names=self.jco.col_names, col_names=self.jco.row_names) return self.__G mn = min(self.jco.shape) try: mn = min(self.pst.npar_adj, self.pst.nnz_obs) except: pass if singular_value > mn: self.logger.warn( "ErrVar.G(): singular_value > min(npar,nobs):" + "resetting to min(npar,nobs): " + str(min(self.pst.npar_adj, self.pst.nnz_obs))) singular_value = min(self.pst.npar_adj, self.pst.nnz_obs) self.log("calc G @" + str(singular_value)) #v1 = self.qhalfx.v[:, :singular_value] v1 = self.xtqx.v[:, :singular_value] #s1 = ((self.qhalfx.s[:singular_value]) ** 2).inv s1 = (self.xtqx.s[:singular_value]).inv self.__G = v1 * s1 * v1.T * self.jco.T * self.obscov.inv self.__G_sv = singular_value self.__G.row_names = self.jco.col_names self.__G.col_names = self.jco.row_names self.__G.autoalign = True self.log("calc G @" + str(singular_value)) return self.__G
def as_pyemu_matrix(self): x = self.copy().as_matrix() return Matrix(x=x, row_names=list(self.index), col_names=list(self.columns))
def __load_predictions(self): """private method set the predictions attribute from: mixed list of row names, matrix files and ndarrays a single row name an ascii file can be none if only interested in parameters. """ if self.prediction_arg is None: self.__predictions = None return self.log("loading forecasts") if not isinstance(self.prediction_arg, list): self.prediction_arg = [self.prediction_arg] row_names = [] vecs = [] mat = None for arg in self.prediction_arg: if isinstance(arg, Matrix): # a vector if arg.shape[1] == 1: vecs.append(arg) else: assert arg.shape[0] == self.jco.shape[1],\ "linear_analysis.__load_predictions(): " +\ "multi-prediction matrix(npar,npred) not aligned " +\ "with jco(nobs,npar): " + str(arg.shape) +\ ' ' + str(self.jco.shape) #for pred_name in arg.row_names: # vecs.append(arg.extract(row_names=pred_name).T) mat = arg elif isinstance(arg, str): if arg.lower() in self.jco.row_names: row_names.append(arg.lower()) else: try: pred_mat = self.__fromfile(arg, astype=Matrix) except Exception as e: raise Exception("forecast argument: "+arg+" not found in " +\ "jco row names and could not be " +\ "loaded from a file.") # vector if pred_mat.shape[1] == 1: vecs.append(pred_mat) else: #for pred_name in pred_mat.row_names: # vecs.append(pred_mat.get(row_names=pred_name)) if mat is None: mat = pred_mat else: mat = mat.extend((pred_mat)) elif isinstance(arg, np.ndarray): self.logger.warn("linear_analysis.__load_predictions(): " + "instantiating prediction matrix from " + "ndarray, can't verify alignment") self.logger.warn( "linear_analysis.__load_predictions(): " + "instantiating prediction matrix from " + "ndarray, generating generic prediction names") pred_names = [ "pred_{0}".format(i + 1) for i in range(arg.shape[0]) ] if self.jco: names = self.jco.col_names elif self.parcov: names = self.parcov.col_names else: raise Exception("linear_analysis.__load_predictions(): " + "ndarray passed for predicitons " + "requires jco or parcov to get " + "parameter names") if mat is None: mat = Matrix(x=arg, row_names=pred_names, col_names=names).T else: mat = mat.extend( Matrix(x=arg, row_names=pred_names, col_names=names).T) #for pred_name in pred_names: # vecs.append(pred_matrix.get(row_names=pred_name).T) else: raise Exception("unrecognized predictions argument: " + str(arg)) # turn vecs into a pyemu.Matrix if len(vecs) > 0: xs = vecs[0].x for vec in vecs[1:]: xs = xs.extend(vec.x) names = [vec.col_names[0] for vec in vecs] if mat is None: mat = Matrix(x=xs, row_names=vecs[0].row_names, col_names=names) else: mat = mat.extend( Matrix(x=np.array(xs), row_names=vecs[0].row_names, col_names=names)) if len(row_names) > 0: extract = self.jco.extract(row_names=row_names).T if mat is None: mat = extract else: mat = mat.extend(extract) #for row_name in row_names: # vecs.append(extract.get(row_names=row_name).T) # call obscov to load __obscov so that __obscov # (priavte) can be manipulated self.obscov self.__obscov.drop(row_names, axis=0) self.__predictions = mat try: fnames = [ fname for fname in self.forecast_names if fname in self.pst.nnz_obs_names ] except: fnames = [] if len(fnames) > 0: raise Exception( "forecasts with non-zero weight in pst: {0}".format( ','.join(fnames))) self.log("loading forecasts") self.logger.statement("forecast names: {0}".format(','.join( mat.col_names))) return self.__predictions
def __load_predictions(self): """private: set the predictions attribute from: mixed list of row names, matrix files and ndarrays a single row name an ascii file can be none if only interested in parameters. linear_analysis.__predictions is stored as a list of column vectors """ if self.prediction_arg is None: self.__predictions = None return self.log("loading forecasts") if not isinstance(self.prediction_arg, list): self.prediction_arg = [self.prediction_arg] row_names = [] vecs = [] for arg in self.prediction_arg: if isinstance(arg, Matrix): # a vector if arg.shape[1] == 1: vecs.append(arg) else: assert arg.shape[1] == self.jco.shape[1],\ "linear_analysis.__load_predictions(): " +\ "multi-prediction matrix(npred,npar) not aligned " +\ "with jco(nobs,npar): " + str(arg.shape) +\ ' ' + str(self.jco.shape) for pred_name in arg.row_names: vecs.append(arg.extract(row_names=pred_name).T) elif isinstance(arg, str): if arg.lower() in self.jco.row_names: row_names.append(arg.lower()) else: pred_mat = self.__fromfile(arg) # vector if pred_mat.shape[1] == 1: vecs.append(pred_mat) else: for pred_name in pred_mat.row_names: vecs.append(pred_mat.get(row_names=pred_name)) elif isinstance(arg, np.ndarray): self.logger.warn("linear_analysis.__load_predictions(): " + "instantiating prediction matrix from " + "ndarray, can't verify alignment") self.logger.warn( "linear_analysis.__load_predictions(): " + "instantiating prediction matrix from " + "ndarray, generating generic prediction names") pred_names = [ "pred_{0}".format(i + 1) for i in range(arg.shape[0]) ] if self.jco: names = self.jco.col_names elif self.parcov: names = self.parcov.col_names else: raise Exception("linear_analysis.__load_predictions(): " + "ndarray passed for predicitons " + "requires jco or parcov to get " + "parameter names") pred_matrix = Matrix(x=arg, row_names=pred_names, col_names=names) for pred_name in pred_names: vecs.append(pred_matrix.get(row_names=pred_name).T) else: raise Exception("unrecognized predictions argument: " + str(arg)) if len(row_names) > 0: extract = self.jco.extract(row_names=row_names) for row_name in row_names: vecs.append(extract.get(row_names=row_name).T) # call obscov to load __obscov so that __obscov # (priavte) can be manipulated self.obscov self.__obscov.drop(row_names, axis=0) self.__predictions = vecs self.log("loading forecasts") return self.__predictions