Source code for sofia_redux.scan.simulation.scan_patterns.daisy

# Licensed under a 3-clause BSD style license - see LICENSE.rst

from astropy import units
import numpy as np

from sofia_redux.scan.coordinate_systems.coordinate_2d import Coordinate2D
from sofia_redux.scan.coordinate_systems.equatorial_coordinates import (
    EquatorialCoordinates)
from sofia_redux.scan.simulation.scan_patterns.constant_speed import (
    to_constant_speed)

__all__ = ['daisy_pattern_offset', 'daisy_pattern_equatorial']


[docs] def daisy_pattern_offset(radius, radial_period, t_interval, n_oscillations=22, constant_speed=False): """ Create a daisy scan pattern in offset coordinates. The daisy pattern has the following form in two dimensions:: x = r.sin(a).cos(b) y = r.sin(a).sin(b) a = 2.pi.t/radial_period + radial_phase b = 2.t/radial_period + rotation_phase rotation_phase = 2.n_oscillations radial_phase = pi.rotation_phase The time (t) is generated in the range 0 -> n_oscillations * radial_period in increments ot t_interval. If `constant_speed` is `False`, the speed of the pattern will be minimal near the edges of the petals and maximal near the center. Due to the fact that the radial and rotational phases are auto-generated such that the pattern forms a closed shape, the samples will also occur along increasingly separated concentric rings from the origin. Therefore, for better scanning coverage, `constant_speed` may be set to `True` so that the physical distance between each sample are approximately equal. Parameters ---------- radius : units.Quantity The angular radius of the daisy pattern. radial_period : units.Quantity The time to complete a single radial oscillation. t_interval : units.Quantity The time interval between sampling points. n_oscillations : int or float, optional The number of oscillations in the pattern. The default of 22 gives a fully populated area for observation. constant_speed : bool, optional If `True`, return a pattern where the speed between each sample point is equal. Returns ------- pattern : Coordinate2D The elevation/cross-elevation scan pattern sampled at `t_interval` in the units of `radius`. """ t_length = n_oscillations * radial_period rotation_phase = 2 * n_oscillations * units.Unit('radian') radial_phase = rotation_phase * np.pi nt = int(np.ceil((t_length / t_interval).decompose().value)) t = np.arange(nt) * t_interval tr = (t / radial_period).decompose().value * units.Unit('radian') a = (2 * np.pi * tr) + radial_phase b = (2 * tr) + rotation_phase dx = radius * np.sin(a) * np.cos(b) dy = radius * np.sin(a) * np.sin(b) pattern = Coordinate2D(np.stack([dx, dy])) if constant_speed: pattern = to_constant_speed(pattern) return pattern
[docs] def daisy_pattern_equatorial(center, t_interval, **kwargs): """ Create a daisy scan pattern in equatorial coordinates. The daisy pattern will be a perfect daisy about the equatorial coordinates. Parameters ---------- center : units.Quantity or EquatorialCoordinates The center of the pattern in equatorial coordinates. t_interval : units.Quantity The sampling interval between output points. Returns ------- pattern : EquatorialCoordinates The equatorial scan pattern sampled at `t_interval`. """ if 'radius' in kwargs: radius = kwargs['radius'] else: radius = 2 * units.Unit('arcmin') if 'radial_period' in kwargs: radial_period = kwargs['radial_period'] else: radial_period = 5 * units.Unit('second') if 'n_oscillations' in kwargs: n_oscillations = kwargs['n_oscillations'] else: n_oscillations = 22 if 'constant_speed' in kwargs: constant_speed = kwargs['constant_speed'] else: constant_speed = False equatorial_offset = daisy_pattern_offset( radius, radial_period, t_interval, n_oscillations=n_oscillations, constant_speed=constant_speed) equatorial = EquatorialCoordinates(center) equatorial.add(equatorial_offset) return equatorial