def __init__(self,P,A,B,scale=100.0,amp=100.0*np.eye(2)): """ Create instance of astrometric map from a background mapping (Bgmap object P) and objects in each frame (Bivarg arrays A and B). """ from pyBA.distortion import astrometry_cov, d2 self.P = P self.A = A self.B = B # Default GP hyperparameters self.scale = scale self.amp = amp self.hyperparams = {'scale': self.scale, 'amp': self.amp} # Gather locations of inputs and build distance matrix self.xyarr = np.array([o.mu for o in self.A]) self.d2 = d2(self.xyarr,self.xyarr) # Use measurement uncertainties of displacement as 'nugget' self.V = np.array([a.sigma for a in A]) + np.array([b.sigma for b in B]) # Build covariance matrix for data points self.C = astrometry_cov(self.d2, self.scale, self.amp, var = self.V) # Don't compute cholesky decomposition of C until needed self.chol = None return
def __init__(self, P, A, B, scale=100.0, amp=100.0 * np.eye(2)): """ Create instance of astrometric map from a background mapping (Bgmap object P) and objects in each frame (Bivarg arrays A and B). """ from pyBA.distortion import astrometry_cov, d2 self.P = P self.A = A self.B = B # Default GP hyperparameters self.scale = scale self.amp = amp self.hyperparams = {'scale': self.scale, 'amp': self.amp} # Gather locations of inputs and build distance matrix self.xyarr = np.array([o.mu for o in self.A]) self.d2 = d2(self.xyarr, self.xyarr) # Use measurement uncertainties of displacement as 'nugget' self.V = np.array([a.sigma for a in A]) + np.array([b.sigma for b in B]) # Build covariance matrix for data points self.C = astrometry_cov(self.d2, self.scale, self.amp, var=self.V) # Don't compute cholesky decomposition of C until needed self.chol = None return
def regression(self, xy): """Performs regression on a mapping object at some locations, which can be points or distributions.""" from scipy.linalg import cho_solve from pyBA.distortion import d2, astrometry_cov, compute_residual # Convert list of inputs to array if needed if type(xy) == list: xy = np.array(xy) # Parse input if type(xy)==np.ndarray: # Single point if xy.size == 2 and type(xy)==np.ndarray: XY = np.array([ Bivarg(mu=xy,sigma=0) ]) # Array of points elif xy.ndim == 2 and type(xy[0])==np.ndarray: XY = np.array([ Bivarg(mu=xy[i],sigma=0) for i in range(len(xy)) ]) # Array of query distributions elif type(xy[0].__class__.__name__=='Bivarg'): XY = xy else: raise TypeError('Regression input should be an nx2 array of coordinates, or an array of Bivarg distributions') # Single query distribution elif xy.__class__.__name__ == 'Bivarg': XY = np.array([ xy ]) else: raise TypeError('Regression input should be an nx2 array of coordinates, or an array of Bivarg distributions') ## Gaussian process regression # Old grid coordinates xyobs = np.array([o.mu for o in self.A]) # New grid coordinates xynew = np.array([o.mu for o in XY]) # Get regression data (resdiual to background) dx, dy = compute_residual(self.A, self.B, self.P) dxy = np.array([dx, dy]).T.flatten() # Build cross covariance between old and new locations d2_grid = d2(xynew,xyobs) Cs = astrometry_cov(d2_grid, self.scale, self.amp) # Build covariance for new locations d2_grid = d2(xynew, xynew) Vnew = np.array([o.sigma for o in XY]) # Don't need to add variances for input points here, they will be propagated # through the background transformation. #Css = astrometry_cov(d2_grid, self.scale, self.amp, var=Vnew) Css = astrometry_cov(d2_grid, self.scale, self.amp) # Regression: mean function evaluated at new locations vxy = Cs.dot(cho_solve(self.chol, dxy)).reshape( (len(XY),2) ) # Regression: uncertainties at new locations S = Css - Cs.dot(cho_solve(self.chol, Cs.T)) ## Package output # Background (mean function) mapping R = np.array([o.transform(self.P) for o in XY]) # Add regression residuals to mean function munew = np.array([o.mu for o in R]) + vxy # Get regression uncertainty from background mapping S_P = self.P.uncertainty(XY) # Get regression uncertainty from gaussian process S_gp = np.array([S[i:i+2,i:i+2] for i in range(0,len(S),2)]) # Combine uncertainties into single covariance matrix sigmanew = np.array([o.sigma for o in R]) + S_gp + S_P # Construct output array of Bivargs O = np.array([ Bivarg(mu=munew[i], sigma=sigmanew[i]) for i in range(len(R)) ]) return O, S_gp, S_P
def regression(self, xy): """Performs regression on a mapping object at some locations, which can be points or distributions.""" from scipy.linalg import cho_solve from pyBA.distortion import d2, astrometry_cov, compute_residual # Convert list of inputs to array if needed if type(xy) == list: xy = np.array(xy) # Parse input if type(xy) == np.ndarray: # Single point if xy.size == 2 and type(xy) == np.ndarray: XY = np.array([Bivarg(mu=xy, sigma=0)]) # Array of points elif xy.ndim == 2 and type(xy[0]) == np.ndarray: XY = np.array( [Bivarg(mu=xy[i], sigma=0) for i in range(len(xy))]) # Array of query distributions elif type(xy[0].__class__.__name__ == 'Bivarg'): XY = xy else: raise TypeError( 'Regression input should be an nx2 array of coordinates, or an array of Bivarg distributions' ) # Single query distribution elif xy.__class__.__name__ == 'Bivarg': XY = np.array([xy]) else: raise TypeError( 'Regression input should be an nx2 array of coordinates, or an array of Bivarg distributions' ) ## Gaussian process regression # Old grid coordinates xyobs = np.array([o.mu for o in self.A]) # New grid coordinates xynew = np.array([o.mu for o in XY]) # Get regression data (resdiual to background) dx, dy = compute_residual(self.A, self.B, self.P) dxy = np.array([dx, dy]).T.flatten() # Build cross covariance between old and new locations d2_grid = d2(xynew, xyobs) Cs = astrometry_cov(d2_grid, self.scale, self.amp) # Build covariance for new locations d2_grid = d2(xynew, xynew) Vnew = np.array([o.sigma for o in XY]) # Don't need to add variances for input points here, they will be propagated # through the background transformation. #Css = astrometry_cov(d2_grid, self.scale, self.amp, var=Vnew) Css = astrometry_cov(d2_grid, self.scale, self.amp) # Regression: mean function evaluated at new locations vxy = Cs.dot(cho_solve(self.chol, dxy)).reshape((len(XY), 2)) # Regression: uncertainties at new locations S = Css - Cs.dot(cho_solve(self.chol, Cs.T)) ## Package output # Background (mean function) mapping R = np.array([o.transform(self.P) for o in XY]) # Add regression residuals to mean function munew = np.array([o.mu for o in R]) + vxy # Get regression uncertainty from background mapping S_P = self.P.uncertainty(XY) # Get regression uncertainty from gaussian process S_gp = np.array([S[i:i + 2, i:i + 2] for i in range(0, len(S), 2)]) # Combine uncertainties into single covariance matrix sigmanew = np.array([o.sigma for o in R]) + S_gp + S_P # Construct output array of Bivargs O = np.array( [Bivarg(mu=munew[i], sigma=sigmanew[i]) for i in range(len(R))]) return O, S_gp, S_P