def calc_posterior(self, x, geom, rdn_meas): """Calculate posterior distribution of state vector. This depends both on the location in the state space and the radiance (via noise).""" xa = self.fm.xa(x, geom) Sa = self.fm.Sa(x, geom) Sa_inv = svd_inv(Sa, hashtable=self.ht) K = self.fm.K(x, geom) Seps = self.fm.Seps(rdn_meas, geom, init=x) Seps_inv = svd_inv(Seps, hashtable=self.ht) # Gain matrix G reflects current state, so we use the state-dependent # Jacobian matrix K S_hat = svd_inv(K.T.dot(Seps_inv).dot(K) + Sa_inv, hashtable=self.ht) G = S_hat.dot(K.T).dot(Seps_inv) # N. Cressie [ASA 2018] suggests an alternate definition of S_hat for # more statistically-consistent posterior confidence estimation if self.state_indep_S_hat: Ka = self.fm.K(xa, geom) S_hat = svd_inv(Ka.T.dot(Seps_inv).dot(Ka) + Sa_inv, hashtable=self.ht) # Reduce the hash table, if needed while len(self.ht) > self.max_table_size: self.ht.popitem(last=False) return S_hat, K, G
def __init__(self, config): Surface.__init__(self, config) # Models are stored as dictionaries in .mat format model_dict = loadmat(config['surface_file']) self.components = list(zip(model_dict['means'], model_dict['covs'])) self.n_comp = len(self.components) self.wl = model_dict['wl'][0] self.n_wl = len(self.wl) # Set up normalization method self.normalize = model_dict['normalize'] if self.normalize == 'Euclidean': self.norm = lambda r: norm(r) elif self.normalize == 'RMS': self.norm = lambda r: s.sqrt(s.mean(pow(r, 2))) elif self.normalize == 'None': self.norm = lambda r: 1.0 else: raise ValueError('Unrecognized Normalization: %s\n' % self.normalize) try: self.selection_metric = config['selection_metric'] except KeyError: self.selection_metric = 'Mahalanobis' # Reference values are used for normalizing the reflectances. # in the VSWIR regime, reflectances are normalized so that the model # is agnostic to absolute magnitude. self.refwl = s.squeeze(model_dict['refwl']) self.idx_ref = [ s.argmin(abs(self.wl - w)) for w in s.squeeze(self.refwl) ] self.idx_ref = s.array(self.idx_ref) # Cache some important computations self.Covs, self.Cinvs, self.mus = [], [], [] for i in range(self.n_comp): Cov = self.components[i][1] self.Covs.append( s.array([Cov[j, self.idx_ref] for j in self.idx_ref])) self.Cinvs.append(svd_inv(self.Covs[-1])) self.mus.append(self.components[i][0][self.idx_ref]) # Variables retrieved: each channel maps to a reflectance model parameter rmin, rmax = 0, 10.0 self.statevec = ['RFL_%04i' % int(w) for w in self.wl] self.bounds = [[rmin, rmax] for w in self.wl] self.scale = [1.0 for w in self.wl] self.init = [0.15 * (rmax - rmin) + rmin for v in self.wl] self.idx_lamb = s.arange(self.n_wl) self.n_state = len(self.statevec)