def _components(data, p=1, phi=0.0, axis=None, weights=None): # Utility function for computing the generalized rectangular components # of the circular data. if weights is None: weights = np.ones((1,)) try: weights = broadcast_to(weights, data.shape) except ValueError: raise ValueError("Weights and data have inconsistent shape.") C = np.sum(weights * np.cos(p * (data - phi)), axis) / np.sum(weights, axis) S = np.sum(weights * np.sin(p * (data - phi)), axis) / np.sum(weights, axis) return C, S
def _components(data, p=1, phi=0.0, axis=None, weights=None): # Utility function for computing the generalized rectangular components # of the circular data. if weights is None: weights = np.ones((1,)) try: weights = broadcast_to(weights, data.shape) except ValueError: raise ValueError('Weights and data have inconsistent shape.') C = np.sum(weights * np.cos(p * (data - phi)), axis)/np.sum(weights, axis) S = np.sum(weights * np.sin(p * (data - phi)), axis)/np.sum(weights, axis) return C, S
def vtest(data, mu=0.0, axis=None, weights=None): """ Performs the Rayleigh test of uniformity where the alternative hypothesis H1 is assumed to have a known mean angle ``mu``. Parameters ---------- data : numpy.ndarray or Quantity Array of circular (directional) data, which is assumed to be in radians whenever ``data`` is ``numpy.ndarray``. mu : float or Quantity, optional Mean angle. Assumed to be known. axis : int, optional Axis along which the V test will be performed. weights : numpy.ndarray, optional In case of grouped data, the i-th element of ``weights`` represents a weighting factor for each group such that ``sum(weights, axis)`` equals the number of observations. See [1], remark 1.4, page 22, for detailed explanation. Returns ------- p-value : float or dimensionless Quantity p-value. Examples -------- >>> import numpy as np >>> from astropy.stats import vtest >>> from astropy import units as u >>> data = np.array([130, 90, 0, 145])*u.deg >>> vtest(data) # doctest: +FLOAT_CMP <Quantity 0.6223678199713766> References ---------- .. [1] S. R. Jammalamadaka, A. SenGupta. "Topics in Circular Statistics". Series on Multivariate Analysis, Vol. 5, 2001. .. [2] C. Agostinelli, U. Lund. "Circular Statistics from 'Topics in Circular Statistics (2001)'". 2015. <https://cran.r-project.org/web/packages/CircStats/CircStats.pdf> .. [3] M. Chirstman., C. Miller. "Testing a Sample of Directions for Uniformity." Lecture Notes, STA 6934/5805. University of Florida, 2007. """ from scipy.stats import norm if weights is None: weights = np.ones((1, )) try: weights = broadcast_to(weights, data.shape) except ValueError: raise ValueError('Weights and data have inconsistent shape.') n = np.size(data, axis=axis) R0bar = np.sum(weights * np.cos(data - mu), axis) / np.sum(weights, axis) z = np.sqrt(2.0 * n) * R0bar pz = norm.cdf(z) fz = norm.pdf(z) # see reference [3] p_value = 1 - pz + fz * ((3 * z - z**3) / (16.0 * n) + (15 * z + 305 * z**3 - 125 * z**5 + 9 * z**7) / (4608.0 * n * n)) return p_value
def vtest(data, mu=0.0, axis=None, weights=None): """ Performs the Rayleigh test of uniformity where the alternative hypothesis H1 is assumed to have a known mean angle ``mu``. Parameters ---------- data : numpy.ndarray or Quantity Array of circular (directional) data, which is assumed to be in radians whenever ``data`` is ``numpy.ndarray``. mu : float or Quantity, optional Mean angle. Assumed to be known. axis : int, optional Axis along which the V test will be performed. weights : numpy.ndarray, optional In case of grouped data, the i-th element of ``weights`` represents a weighting factor for each group such that ``sum(weights, axis)`` equals the number of observations. See [1], remark 1.4, page 22, for detailed explanation. Returns ------- p-value : float or dimensionless Quantity p-value. Examples -------- >>> import numpy as np >>> from astropy.stats import vtest >>> from astropy import units as u >>> data = np.array([130, 90, 0, 145])*u.deg >>> vtest(data) # doctest: +FLOAT_CMP <Quantity 0.6223678199713766> References ---------- .. [1] S. R. Jammalamadaka, A. SenGupta. "Topics in Circular Statistics". Series on Multivariate Analysis, Vol. 5, 2001. .. [2] C. Agostinelli, U. Lund. "Circular Statistics from 'Topics in Circular Statistics (2001)'". 2015. <https://cran.r-project.org/web/packages/CircStats/CircStats.pdf> .. [3] M. Chirstman., C. Miller. "Testing a Sample of Directions for Uniformity." Lecture Notes, STA 6934/5805. University of Florida, 2007. """ from scipy.stats import norm if weights is None: weights = np.ones((1,)) try: weights = broadcast_to(weights, data.shape) except ValueError: raise ValueError("Weights and data have inconsistent shape.") n = np.size(data, axis=axis) R0bar = np.sum(weights * np.cos(data - mu), axis) / np.sum(weights, axis) z = np.sqrt(2.0 * n) * R0bar pz = norm.cdf(z) fz = norm.pdf(z) # see reference [3] p_value = ( 1 - pz + fz * ((3 * z - z ** 3) / (16.0 * n) + (15 * z + 305 * z ** 3 - 125 * z ** 5 + 9 * z ** 7) / (4608.0 * n * n)) ) return p_value
def __call__(self, observer, targets, times=None, time_range=None, time_grid_resolution=0.5*u.hour, grid_times_targets=False): """ Compute the constraint for this class Parameters ---------- observer : `~astroplan.Observer` the observation location from which to apply the constraints targets : sequence of `~astroplan.Target` The targets on which to apply the constraints. times : `~astropy.time.Time` The times to compute the constraint. WHAT HAPPENS WHEN BOTH TIMES AND TIME_RANGE ARE SET? time_range : `~astropy.time.Time` (length = 2) Lower and upper bounds on time sequence. time_grid_resolution : `~astropy.units.quantity` Time-grid spacing grid_times_targets : bool if True, grids the constraint result with targets along the first index and times along the second. Otherwise, we rely on broadcasting the shapes together using standard numpy rules. Returns ------- constraint_result : 1D or 2D array of float or bool The constraints. If 2D with targets along the first index and times along the second. """ if times is None and time_range is not None: times = time_grid_from_range(time_range, time_resolution=time_grid_resolution) if grid_times_targets: targets = get_skycoord(targets) # TODO: these broadcasting operations are relatively slow # but there is potential for huge speedup if the end user # disables gridding and re-shapes the coords themselves # prior to evaluating multiple constraints. if targets.isscalar: # ensure we have a (1, 1) shape coord targets = SkyCoord(np.tile(targets, 1))[:, np.newaxis] else: targets = targets[..., np.newaxis] times, targets = observer._preprocess_inputs(times, targets, grid_times_targets=False) result = self.compute_constraint(times, observer, targets) # make sure the output has the same shape as would result from # broadcasting times and targets against each other if targets is not None: # broadcasting times v targets is slow due to # complex nature of these objects. We make # to simple numpy arrays of the same shape and # broadcast these to find the correct shape shp1, shp2 = times.shape, targets.shape x = np.array([1]) a = as_strided(x, shape=shp1, strides=[0] * len(shp1)) b = as_strided(x, shape=shp2, strides=[0] * len(shp2)) output_shape = np.broadcast(a, b).shape if output_shape != result.shape: result = broadcast_to(result, output_shape) return result
def __call__(self, observer, targets, times=None, time_range=None, time_grid_resolution=0.5 * u.hour, grid_times_targets=False): """ Compute the constraint for this class Parameters ---------- observer : `~astroplan.Observer` the observation location from which to apply the constraints targets : sequence of `~astroplan.Target` The targets on which to apply the constraints. times : `~astropy.time.Time` The times to compute the constraint. WHAT HAPPENS WHEN BOTH TIMES AND TIME_RANGE ARE SET? time_range : `~astropy.time.Time` (length = 2) Lower and upper bounds on time sequence. time_grid_resolution : `~astropy.units.quantity` Time-grid spacing grid_times_targets : bool if True, grids the constraint result with targets along the first index and times along the second. Otherwise, we rely on broadcasting the shapes together using standard numpy rules. Returns ------- constraint_result : 1D or 2D array of float or bool The constraints. If 2D with targets along the first index and times along the second. """ if times is None and time_range is not None: times = time_grid_from_range(time_range, time_resolution=time_grid_resolution) if grid_times_targets: targets = get_skycoord(targets) # TODO: these broadcasting operations are relatively slow # but there is potential for huge speedup if the end user # disables gridding and re-shapes the coords themselves # prior to evaluating multiple constraints. if targets.isscalar: # ensure we have a (1, 1) shape coord targets = SkyCoord(np.tile(targets, 1))[:, np.newaxis] else: targets = targets[..., np.newaxis] times, targets = observer._preprocess_inputs(times, targets, grid_times_targets=False) result = self.compute_constraint(times, observer, targets) # make sure the output has the same shape as would result from # broadcasting times and targets against each other if targets is not None: # broadcasting times v targets is slow due to # complex nature of these objects. We make # to simple numpy arrays of the same shape and # broadcast these to find the correct shape shp1, shp2 = times.shape, targets.shape x = np.array([1]) a = as_strided(x, shape=shp1, strides=[0] * len(shp1)) b = as_strided(x, shape=shp2, strides=[0] * len(shp2)) output_shape = np.broadcast(a, b).shape if output_shape != np.array(result).shape: result = broadcast_to(result, output_shape) return result