Example #1
0
 def test_fit_eval_diagcov(self):
     """GaussianFit (shared stdev): Basic function fitting and evaluation using data from a known function."""
     interp = GaussianFit(self.init_mean, self.init_std, self.init_height)
     interp.fit(self.x, self.y)
     y = interp(self.x)
     assert_almost_equal(interp.mean, self.true_mean, decimal=7)
     assert_almost_equal(interp.std, self.true_std, decimal=7)
     assert_almost_equal(interp.height, self.true_height, decimal=7)
     assert_almost_equal(y, self.y, decimal=7)
Example #2
0
 def test_fit_eval_diagcov(self):
     """GaussianFit (shared stdev): Basic function fitting and evaluation using data from a known function."""
     interp = GaussianFit(self.init_mean, self.init_std, self.init_height)
     interp.fit(self.x, self.y)
     y = interp(self.x)
     assert_almost_equal(interp.mean, self.true_mean, decimal=7)
     assert_almost_equal(interp.std, self.true_std, decimal=7)
     assert_almost_equal(interp.height, self.true_height, decimal=7)
     assert_almost_equal(y, self.y, decimal=7)
Example #3
0
 def test_fit_eval_diagcov(self):
     """GaussianFit (independent stdevs): Basic fitting and evaluation."""
     interp = GaussianFit(self.init_mean, self.init_std, self.init_height)
     interp.fit(self.x, self.y)
     y = interp(self.x)
     assert_almost_equal(interp.mean, self.true_mean, decimal=7)
     assert_almost_equal(interp.std, self.true_std, decimal=7)
     assert_almost_equal(interp.height, self.true_height, decimal=7)
     assert_almost_equal(y, self.y, decimal=7)
Example #4
0
 def setUp(self):
     self.true_mean, self.true_std, self.true_height = [0, 0], 1., 0.
     true_gauss = GaussianFit(self.true_mean, self.true_std,
                              self.true_height)
     self.x = 7 * np.random.randn(2, 80)
     self.y = true_gauss(self.x)
     self.init_mean, self.init_std, self.init_height = [0, 0], 1, 0
Example #5
0
    def __init__(self, center, width, height):
        ScatterFit.__init__(self)
        if not np.isscalar(width):
            width = np.atleast_1d(width)
        self._interp = GaussianFit(center, fwhm_to_sigma(width), height)
        self.center = self._interp.mean
        self.width = sigma_to_fwhm(self._interp.std)
        self.height = self._interp.height

        self.expected_width = width
        # Initial guess for radius of first null
        # XXX: POTENTIAL TWEAK
        self.radius_first_null = 1.3 * np.mean(self.expected_width)
        # Beam initially unrefined and invalid
        self.refined = 0
        self.is_valid = False
        self.std_center = self.std_width = self.std_height = None
Example #6
0
 def setUp(self):
     # For a more challenging fit, move the true mean away from the origin, i.e. away from the region
     # being randomly sampled in self.x. Fitting a Gaussian to a segment that does not contain a clear peak
     # works fine if the fit is done to the log of the data, but fails in the linear domain.
     self.true_mean, self.true_std, self.true_height = [0., 0.], [3., 5.], 4.
     true_gauss = GaussianFit(self.true_mean, self.true_std, self.true_height)
     self.x = 7. * np.random.randn(2, 300)
     self.y = true_gauss(self.x)
     self.init_mean, self.init_std, self.init_height = [3., -2.], [1., 1.], 1.
Example #7
0
 def test_cov_params(self):
     """GaussianFit (independent stdevs): Obtain sample statistics of params and compare to calculated cov matrix."""
     interp = GaussianFit(self.init_mean, self.init_std, self.init_height)
     true_params = np.r_[self.true_mean, self.true_height, self.true_std]
     std_y = 0.1
     M = 200
     param_set = np.zeros((len(true_params), M))
     for n in range(M):
         interp.fit(self.x, self.y + std_y * np.random.randn(len(self.y)), std_y)
         param_set[:, n] = np.r_[interp.mean, interp.height, interp.std]
     mean_params = param_set.mean(axis=1)
     norm_params = param_set - mean_params[:, np.newaxis]
     cov_params = np.dot(norm_params, norm_params.T) / M
     estm_std_params = np.sqrt(np.diag(cov_params))
     std_params = np.r_[interp.std_mean, interp.std_height, interp.std_std]
     self.assertTrue((np.abs(mean_params - true_params) / std_params < 0.5).all(),
                     "Sample mean parameter vector differs too much from true value")
     # Only check diagonal of cov matrix - the rest is probably affected by linearisation
     self.assertTrue((np.abs(estm_std_params - std_params) / std_params < 0.2).all(),
                     "Sample parameter standard deviation differs too much from expected one")
Example #8
0
 def test_cov_params(self):
     """GaussianFit (independent stdevs): Obtain sample statistics of parameters and compare to calculated covariance matrix."""
     interp = GaussianFit(self.init_mean, self.init_std, self.init_height)
     true_params = np.r_[self.true_mean, self.true_height, self.true_std]
     std_y = 0.1
     M = 200
     param_set = np.zeros((len(true_params), M))
     for n in range(M):
         interp.fit(self.x, self.y + std_y * np.random.randn(len(self.y)), std_y)
         param_set[:, n] = np.r_[interp.mean, interp.height, interp.std]
     mean_params = param_set.mean(axis=1)
     norm_params = param_set - mean_params[:, np.newaxis]
     cov_params = np.dot(norm_params, norm_params.T) / M
     estm_std_params = np.sqrt(np.diag(cov_params))
     std_params = np.r_[interp.std_mean, interp.std_height, interp.std_std]
     self.assertTrue((np.abs(mean_params - true_params) / std_params < 0.5).all(),
                     "Sample mean parameter vector differs too much from true value")
     # Only check diagonal of cov matrix - the rest is probably affected by linearisation
     self.assertTrue((np.abs(estm_std_params - std_params) / std_params < 0.2).all(),
                     "Sample parameter standard deviation differs too much from expected one")
Example #9
0
 def setUp(self):
     self.true_mean = [0, 0]
     self.true_std = np.sqrt(10)
     self.true_height = 4
     true_gauss = GaussianFit(self.true_mean, self.true_std,
                              self.true_height)
     self.x = 7 * np.random.randn(2, 80)
     self.y = true_gauss(self.x)
     self.init_mean = [3, -2]
     self.init_std = 1
     self.init_height = 1
Example #10
0
class BeamPatternFit(ScatterFit):
    """Fit analytic beam pattern to total power data defined on 2-D plane.

    This fits a two-dimensional Gaussian curve (with diagonal covariance matrix)
    to total power data as a function of 2-D coordinates. The Gaussian bump
    represents an antenna beam pattern convolved with a point source.

    Parameters
    ----------
    center : sequence of 2 floats
        Initial guess of 2-element beam center, in target coordinate units
    width : sequence of 2 floats, or float
        Initial guess of single beamwidth for both dimensions, or 2-element
        beamwidth vector, expressed as FWHM in units of target coordinates
    height : float
        Initial guess of beam pattern amplitude or height

    Attributes
    ----------
    expected_width : real array, shape (2,), or float
        Initial guess of beamwidth, saved as expected width for checks
    radius_first_null : float
        Radius of first null in beam in target coordinate units (stored here for
        convenience, but not calculated internally)
    refined : int
        Number of scan-based baselines used to refine beam (0 means unrefined)
    is_valid : bool
        True if beam parameters are within reasonable ranges after fit
    std_center : array of float, shape (2,)
        Standard error of beam center, only set after :func:`fit`
    std_width : array of float, shape (2,), or float
        Standard error of beamwidth(s), only set after :func:`fit`
    std_height : float
        Standard error of beam height, only set after :func:`fit`

    """
    def __init__(self, center, width, height):
        ScatterFit.__init__(self)
        if not np.isscalar(width):
            width = np.atleast_1d(width)
        self._interp = GaussianFit(center, fwhm_to_sigma(width), height)
        self.center = self._interp.mean
        self.width = sigma_to_fwhm(self._interp.std)
        self.height = self._interp.height

        self.expected_width = width
        # Initial guess for radius of first null
        # XXX: POTENTIAL TWEAK
        self.radius_first_null = 1.3 * np.mean(self.expected_width)
        # Beam initially unrefined and invalid
        self.refined = 0
        self.is_valid = False
        self.std_center = self.std_width = self.std_height = None

    def fit(self, x, y, std_y=1.0):
        """Fit a beam pattern to data.

        The center, width and height of the fitted beam pattern (and their
        standard errors) can be obtained from the corresponding member variables
        after this is run.

        Parameters
        ----------
        x : array-like, shape (2, N)
            Sequence of 2-dimensional target coordinates (as column vectors)
        y : array-like, shape (N,)
            Sequence of corresponding total power values to fit
        std_y : float or array-like, shape (N,), optional
            Measurement error or uncertainty of `y` values, expressed as standard
            deviation in units of `y`

        """
        self._interp.fit(x, y, std_y)
        self.center = self._interp.mean
        self.width = sigma_to_fwhm(self._interp.std)
        self.height = self._interp.height
        self.std_center = self._interp.std_mean
        self.std_width = sigma_to_fwhm(self._interp.std_std)
        self.std_height = self._interp.std_height
        self.is_valid = not any(np.isnan(self.center)) and self.height > 0.
        # XXX: POTENTIAL TWEAK
        norm_width = self.width / self.expected_width
        self.is_valid &= all(norm_width > 0.9) and all(norm_width < 1.25)

    def __call__(self, x):
        """Evaluate fitted beam pattern function on new target coordinates.

        Parameters
        ----------
        x : array-like, shape (2, M)
            Sequence of 2-dimensional target coordinates (as column vectors)

        Returns
        -------
        y : array, shape (M,)
            Sequence of total power values representing fitted beam

        """
        return self._interp(x)