Example #1
0
    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 
Example #2
0
    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
Example #3
0
    def build_covariance(self,scale=None,amp=None):

        from pyBA.distortion import astrometry_cov
        
        if scale != None:
            self.scale = scale
            self.hyperparams['scale'] = scale

        if amp != None:
            if np.size(amp) == 1:
                amp = np.array([[amp,0.],[0.,amp]])
            elif np.size(amp) == 2:
                amp = np.array([[amp[0],amp[1]],[amp[1],amp[0]]])

            self.amp = amp
            self.hyperparams['amp'] = amp
        
        self.C = astrometry_cov(self.d2, self.scale, self.amp, var = self.V)

        # Compute cholesky decomposition of C with optimised parameters
        from scipy.linalg import cho_factor
        self.chol = cho_factor(self.C)
Example #4
0
    def build_covariance(self, scale=None, amp=None):

        from pyBA.distortion import astrometry_cov

        if scale is not None:
            self.scale = scale
            self.hyperparams['scale'] = scale

        if amp is not None:
            if np.size(amp) == 1:
                amp = np.array([[amp, 0.], [0., amp]])
            elif np.size(amp) == 2:
                amp = np.array([[amp[0], amp[1]], [amp[1], amp[0]]])

            self.amp = amp
            self.hyperparams['amp'] = amp

        self.C = astrometry_cov(self.d2, self.scale, self.amp, var=self.V)

        # Compute cholesky decomposition of C with optimised parameters
        from scipy.linalg import cho_factor
        self.chol = cho_factor(self.C)
Example #5
0
    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
Example #6
0
    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