示例#1
0
def create_random_pointings(
    center, npointings, dtheta, date_obs=None, sampling_period=None, latitude=None, longitude=None
):
    """
    Return pointings randomly and uniformly distributed in a spherical cap.

    Parameters
    ----------
    center : 2-tuple
        The R.A. and declination of the center of the FOV, in degrees.
    npointings : int
        The number of requested pointings
    dtheta : float
        The maximum angular distance to the center.
    date_obs : str or astropy.time.Time, optional
        The starting date of the observation (UTC).
    sampling_period : float, optional
        The sampling period of the pointings, in seconds.
    latitude : float, optional
        The observer's latitude [degrees]. Default is DOMEC's.
    longitude : float, optional
        The observer's longitude [degrees]. Default is DOMEC's.

    """
    cosdtheta = np.cos(np.radians(dtheta))
    theta = np.degrees(np.arccos(cosdtheta + (1 - cosdtheta) * randomu(npointings)))
    phi = randomu(npointings) * 360
    pitch = randomu(npointings) * 360
    p = QubicPointing.zeros(
        npointings, date_obs=date_obs, sampling_period=sampling_period, latitude=latitude, longitude=longitude
    )
    time = p.date_obs + TimeDelta(p.time, format="sec")
    rotation = (
        Cartesian2SphericalOperator("azimuth,elevation", degrees=True)
        * CartesianEquatorial2HorizontalOperator("NE", time, p.latitude, p.longitude)
        * Rotation3dOperator("ZY'", center[0], 90 - center[1], degrees=True)
        * Spherical2CartesianOperator("zenith,azimuth", degrees=True)
    )
    coords = rotation(np.asarray([theta.T, phi.T]).T)
    p.azimuth = coords[..., 0]
    p.elevation = coords[..., 1]
    p.pitch = pitch
    return p
示例#2
0
def create_sweeping_pointings(
    center,
    duration,
    sampling_period,
    angspeed,
    delta_az,
    nsweeps_per_elevation,
    angspeed_psi,
    maxpsi,
    date_obs=None,
    latitude=None,
    longitude=None,
    return_hor=True,
    decrange=0.0,
    decspeed=2.0,
    recenter=False,
):
    """
    Return pointings according to the sweeping strategy:
    Sweep around the tracked FOV center azimuth at a fixed elevation, an
    update elevation towards the FOV center at discrete times.

    Parameters
    ----------
    center : array-like of size 2
        The R.A. and Declination of the center of the FOV.
    duration : float
        The duration of the observation, in hours.
    sampling_period : float
        The sampling period of the pointings, in seconds.
    angspeed : float
        The pointing angular speed, in deg / s.
    delta_az : float
        The sweeping extent in degrees.
    nsweeps_per_elevation : int
        The number of sweeps during a phase of constant elevation.
    angspeed_psi : float
        The pitch angular speed, in deg / s.
    maxpsi : float
        The maximum pitch angle, in degrees.
    latitude : float, optional
        The observer's latitude [degrees]. Default is DOMEC's.
    longitude : float, optional
        The observer's longitude [degrees]. Default is DOMEC's.
    date_obs : str or astropy.time.Time, optional
        The starting date of the observation (UTC).
    return_hor : bool, optional
        Obsolete keyword.

    Returns
    -------
    pointings : QubicPointing
        Structured array containing the azimuth, elevation and pitch angles,
        in degrees.

    """
    nsamples = int(np.ceil(duration * 3600 / sampling_period))
    out = QubicPointing.zeros(
        nsamples, date_obs=date_obs, sampling_period=sampling_period, latitude=latitude, longitude=longitude
    )
    racenter = center[0]
    deccenter = center[1] + decrange * np.cos(decspeed * 2 * np.pi * out.time / (np.max(out.time) - np.min(out.time)))
    backforthdt = delta_az / angspeed * 2

    jd = (out.date_obs + TimeDelta(out.time, format="sec")).jd
    tsamples = _gst2lst(_jd2gst(jd), out.longitude)

    # compute the sweep number
    isweeps = np.floor(out.time / backforthdt).astype(int)

    # azimuth/elevation of the center of the field as a function of time
    azcenter, elcenter = _equ2hor(racenter, deccenter, out.latitude, tsamples)

    # compute azimuth offset for all time samples
    daz = out.time * angspeed
    daz = daz % (delta_az * 2)
    mask = daz > delta_az
    daz[mask] = -daz[mask] + 2 * delta_az
    daz -= delta_az / 2

    # elevation is kept constant during nsweeps_per_elevation
    elcst = np.zeros(nsamples)
    azcst = np.zeros(nsamples)
    ielevations = isweeps // nsweeps_per_elevation
    nelevations = ielevations[-1] + 1
    for i in xrange(nelevations):
        mask = ielevations == i
        elcst[mask] = np.mean(elcenter[mask])
        azcst[mask] = ((np.mean((azcenter[mask] - azcenter[mask][-1]) % 360)) + azcenter[mask][-1]) % 360

    # azimuth and elevations to use for pointing
    if recenter:
        azptg = azcenter + daz
    else:
        azptg = azcst + daz
    elptg = elcst

    ### scan psi as well
    pitch = out.time * angspeed_psi
    pitch = pitch % (4 * maxpsi)
    mask = pitch > (2 * maxpsi)
    pitch[mask] = -pitch[mask] + 4 * maxpsi
    pitch -= maxpsi

    if not return_hor:
        # convert them to RA, Dec
        raptg, decptg = _hor2equ(azptg, elptg, out.latitude, tsamples)
        theta = 90 - decptg
        phi = raptg
        pointings = np.array([theta, phi, pitch]).T
        return pointings

    out.azimuth = azptg
    out.elevation = elptg
    out.pitch = pitch
    return out