Esempio n. 1
0
def test_interpolation_broadcasting():
    from astropy.coordinates.angle_utilities import golden_spiral_grid
    from astropy.coordinates import SkyCoord, EarthLocation, AltAz
    from astropy.time import Time
    import astropy.units as u

    from astropy.coordinates.erfa_astrom import (erfa_astrom,
                                                 ErfaAstromInterpolator)

    # 1000 gridded locations on the sky
    rep = golden_spiral_grid(100)
    coord = SkyCoord(rep)

    # 30 times over the space of 1 hours
    times = Time('2020-01-01T20:00') + np.linspace(-0.5, 0.5, 30) * u.hour

    lst1 = EarthLocation(
        lon=-17.891498 * u.deg,
        lat=28.761443 * u.deg,
        height=2200 * u.m,
    )

    # note the use of broadcasting so that 300 times are broadcast against 1000 positions
    aa_frame = AltAz(obstime=times[:, np.newaxis], location=lst1)
    aa_coord = coord.transform_to(aa_frame)

    with erfa_astrom.set(ErfaAstromInterpolator(300 * u.s)):
        aa_coord_interp = coord.transform_to(aa_frame)

    assert aa_coord.shape == aa_coord_interp.shape
    assert np.all(aa_coord.separation(aa_coord_interp) < 1 * u.microarcsecond)
Esempio n. 2
0
def test_interpolation_nd():
    '''
    Test that the interpolation also works for nd-arrays
    '''

    fact = EarthLocation(
        lon=-17.891105 * u.deg,
        lat=28.761584 * u.deg,
        height=2200 * u.m,
    )

    interp_provider = ErfaAstromInterpolator(300 * u.s)
    provider = ErfaAstrom()

    for shape in [tuple(), (1, ), (10, ), (3, 2), (2, 10, 5), (4, 5, 3, 2)]:
        # create obstimes of the desired shapes
        delta_t = np.linspace(0, 12, np.prod(shape, dtype=int)) * u.hour
        obstime = (Time('2020-01-01T18:00') + delta_t).reshape(shape)

        altaz = AltAz(location=fact, obstime=obstime)
        gcrs = GCRS(obstime=obstime)
        cirs = CIRS(obstime=obstime)

        for frame, tcode in zip([altaz, cirs, gcrs], ['apio', 'apco', 'apcs']):
            without_interp = getattr(provider, tcode)(frame)
            assert without_interp.shape == shape

            with_interp = getattr(interp_provider, tcode)(frame)
            assert with_interp.shape == shape
Esempio n. 3
0
def test_erfa_astrom():
    # I was having a pretty hard time in coming
    # up with a unit test only testing the astrom provider
    # that would not just test its implementation with its implementation
    # so we test a coordinate conversion using it

    location = EarthLocation(
        lon=-17.891105 * u.deg,
        lat=28.761584 * u.deg,
        height=2200 * u.m,
    )
    obstime = Time('2020-01-01T18:00') + np.linspace(0, 1, 100) * u.hour

    altaz = AltAz(location=location, obstime=obstime)
    coord = SkyCoord(ra=83.63308333, dec=22.0145, unit=u.deg)

    # do the reference transformation, no interpolation
    ref = coord.transform_to(altaz)

    with erfa_astrom.set(ErfaAstromInterpolator(300 * u.s)):
        interp_300s = coord.transform_to(altaz)

    # make sure they are actually different
    assert np.any(ref.separation(interp_300s) > 0.005 * u.microarcsecond)

    # make sure the resolution is as good as we expect
    assert np.all(ref.separation(interp_300s) < 1 * u.microarcsecond)
Esempio n. 4
0
def test_science_state():

    assert erfa_astrom.get().__class__ is ErfaAstrom

    res = 300 * u.s
    with erfa_astrom.set(ErfaAstromInterpolator(res)):
        assert isinstance(erfa_astrom.get(), ErfaAstromInterpolator)
        erfa_astrom.get().mjd_resolution == res.to_value(u.day)

    # context manager should have switched it back
    assert erfa_astrom.get().__class__ is ErfaAstrom

    # must be a subclass of BaseErfaAstrom
    with pytest.raises(TypeError):
        erfa_astrom.set('foo')
Esempio n. 5
0
def add_icrs_position_params(data, source_pos):
    """
    Updating data with ICRS position values of reconstructed positions in
    RA DEC coordinates and add column on separation form true source position.
    """
    reco_alt = data["reco_alt"]
    reco_az = data["reco_az"]

    time_utc = Time(data["dragon_time"], format="unix", scale="utc")

    reco_altaz = SkyCoord(alt=reco_alt,
                          az=reco_az,
                          frame=AltAz(obstime=time_utc, location=location))

    with erfa_astrom.set(ErfaAstromInterpolator(300 * u.s)):
        reco_icrs = reco_altaz.transform_to(frame="icrs")

    data["RA"] = reco_icrs.ra.to(u.deg)
    data["Dec"] = reco_icrs.dec.to(u.deg)
    data["theta"] = reco_icrs.separation(source_pos).to(u.deg)

    return data
Esempio n. 6
0
def create_event_list(
    data, run_number, source_name, source_pos, effective_time, elapsed_time
):
    """
    Create the event_list BinTableHDUs from the given data

    Parameters
    ----------
        Data: DL2 data file
                'astropy.table.QTable'
        Run: Run number
                Int
        Source_name: Name of the source
                Str
        Source_pos: Ra/Dec position of the source
                'astropy.coordinates.SkyCoord'
        Effective_time: Effective time of triggered events of the run
                Float
        Elapsed_time: Total elapsed time of triggered events of the run
                Float
    Returns
    -------
        Events HDU:  `astropy.io.fits.BinTableHDU`
        GTI HDU:  `astropy.io.fits.BinTableHDU`
        Pointing HDU:  `astropy.io.fits.BinTableHDU`
    """

    tel_list = np.unique(data["tel_id"])

    # Timing parameters
    t_start = data["dragon_time"].value[0]
    t_stop = data["dragon_time"].value[-1]
    time_utc = Time(data["dragon_time"], format="unix", scale="utc")
    t_start_iso = time_utc[0].to_value("iso", "date_hms")
    t_stop_iso = time_utc[-1].to_value("iso", "date_hms")
    date_obs = t_start_iso[:10]
    time_obs = t_start_iso[11:]
    date_end = t_stop_iso[:10]
    time_end = t_stop_iso[11:]

    MJDREF = Time("1970-01-01T00:00", scale="utc")

    # Position parameters
    reco_alt = data["reco_alt"]
    reco_az = data["reco_az"]
    pointing_alt = data["pointing_alt"]
    pointing_az = data["pointing_az"]

    reco_altaz = SkyCoord(
        alt=reco_alt, az=reco_az, frame=AltAz(obstime=time_utc, location=location)
    )
    pnt_icrs = SkyCoord(
        alt=pointing_alt[0],
        az=pointing_az[0],
        frame=AltAz(obstime=time_utc[0], location=location),
    ).transform_to(frame="icrs")

    with erfa_astrom.set(ErfaAstromInterpolator(30 * u.s)):
        reco_icrs = reco_altaz.transform_to(frame="icrs")

    # Observation modes
    source_pointing_diff = source_pos.separation(pnt_icrs)
    if np.around(source_pointing_diff, 1) == wobble_offset:
        mode = "WOBBLE"
    elif np.around(source_pointing_diff, 1) > 1 * u.deg:
        mode = "OFF"
    elif np.around(source_pointing_diff, 1) == 0.0 * u.deg:
        mode = "ON"
    else:
        # Nomenclature is to be worked out or have a separate way to mark mispointings
        mode = "UNDETERMINED"

    log.info(
        "Source pointing difference with camera pointing"
        f" is {source_pointing_diff:.3f}"
    )

    event_table = QTable(
        {
            "EVENT_ID": data["event_id"],
            "TIME": data["dragon_time"],
            "RA": reco_icrs.ra.to(u.deg),
            "DEC": reco_icrs.dec.to(u.deg),
            "ENERGY": data["reco_energy"],
            # Optional columns
            "GAMMANESS": data["gh_score"],
            "MULTIP": u.Quantity(np.repeat(len(tel_list), len(data)), dtype=int),
            "GLON": reco_icrs.galactic.l.to(u.deg),
            "GLAT": reco_icrs.galactic.b.to(u.deg),
            "ALT": reco_alt.to(u.deg),
            "AZ": reco_az.to(u.deg),
        }
    )
    gti_table = QTable(
        {
            "START": u.Quantity(t_start, unit=u.s, ndmin=1),
            "STOP": u.Quantity(t_stop, unit=u.s, ndmin=1),
        }
    )
    pnt_table = QTable(
        {
            "TIME": u.Quantity(t_start, unit=u.s, ndmin=1),
            "RA_PNT": u.Quantity(pnt_icrs.ra.to(u.deg), ndmin=1),
            "DEC_PNT": u.Quantity(pnt_icrs.dec.to(u.deg), ndmin=1),
            "ALT_PNT": u.Quantity(pointing_alt[0].to(u.deg), ndmin=1),
            "AZ_PNT": u.Quantity(pointing_az[0].to(u.deg), ndmin=1),
        }
    )

    # Adding the meta data
    # Comments can be added later for relevant metadata
    # Event table metadata
    ev_header = DEFAULT_HEADER.copy()
    ev_header["CREATED"] = Time.now().utc.iso
    ev_header["HDUCLAS1"] = "EVENTS"

    ev_header["OBS_ID"] = run_number

    ev_header["DATE-OBS"] = date_obs
    ev_header["TIME-OBS"] = time_obs
    ev_header["DATE-END"] = date_end
    ev_header["TIME-END"] = time_end
    ev_header["TSTART"] = t_start
    ev_header["TSTOP"] = t_stop
    ev_header["MJDREFI"] = int(MJDREF.mjd)
    ev_header["MJDREFF"] = MJDREF.mjd - int(MJDREF.mjd)
    ev_header["TIMEUNIT"] = "s"
    ev_header["TIMESYS"] = "UTC"
    ev_header["TIMEREF"] = "TOPOCENTER"
    ev_header["ONTIME"] = elapsed_time
    ev_header["TELAPSE"] = t_stop - t_start
    ev_header["DEADC"] = effective_time / elapsed_time
    ev_header["LIVETIME"] = effective_time

    ev_header["OBJECT"] = source_name
    ev_header["OBS_MODE"] = mode

    ev_header["N_TELS"] = len(tel_list)
    ev_header["TELLIST"] = "LST-" + " ".join(map(str, tel_list))
    ev_header["INSTRUME"] = f"{ev_header['TELLIST']}"

    ev_header["RA_PNT"] = pnt_icrs.ra.to_value()
    ev_header["DEC_PNT"] = pnt_icrs.dec.to_value()
    ev_header["ALT_PNT"] = data["pointing_alt"].mean().to_value(u.deg)
    ev_header["AZ_PNT"] = data["pointing_az"].mean().to_value(u.deg)
    ev_header["RA_OBJ"] = source_pos.ra.to_value()
    ev_header["DEC_OBJ"] = source_pos.dec.to_value()
    ev_header["FOVALIGN"] = "RADEC"

    # GTI table metadata
    gti_header = DEFAULT_HEADER.copy()
    gti_header["CREATED"] = Time.now().utc.iso
    gti_header["HDUCLAS1"] = "GTI"

    gti_header["OBS_ID"] = run_number
    gti_header["MJDREFI"] = ev_header["MJDREFI"]
    gti_header["MJDREFF"] = ev_header["MJDREFF"]
    gti_header["TIMESYS"] = ev_header["TIMESYS"]
    gti_header["TIMEUNIT"] = ev_header["TIMEUNIT"]
    gti_header["TIMEREF"] = ev_header["TIMEREF"]

    # Pointing table metadata
    pnt_header = DEFAULT_HEADER.copy()
    pnt_header["CREATED"] = Time.now().utc.iso
    pnt_header["HDUCLAS1"] = "POINTING"

    pnt_header["OBS_ID"] = run_number
    pnt_header["MJDREFI"] = ev_header["MJDREFI"]
    pnt_header["MJDREFF"] = ev_header["MJDREFF"]
    pnt_header["TIMEUNIT"] = ev_header["TIMEUNIT"]
    pnt_header["TIMESYS"] = ev_header["TIMESYS"]
    pnt_header["OBSGEO-L"] = (
        location.lon.to_value(u.deg),
        "Geographic longitude of telescope (deg)",
    )
    pnt_header["OBSGEO-B"] = (
        location.lat.to_value(u.deg),
        "Geographic latitude of telescope (deg)",
    )
    pnt_header["OBSGEO-H"] = (
        round(location.height.to_value(u.m), 2),
        "Geographic latitude of telescope (m)",
    )

    pnt_header["TIMEREF"] = ev_header["TIMEREF"]

    # Create HDUs
    event = fits.BinTableHDU(event_table, header=ev_header, name="EVENTS")
    gti = fits.BinTableHDU(gti_table, header=gti_header, name="GTI")
    pointing = fits.BinTableHDU(pnt_table, header=pnt_header, name="POINTING")

    return event, gti, pointing
Esempio n. 7
0
from ..apply import predict_energy, predict_disp, predict_separator
from ..parallel import parallelize_array_computation
from ..io import (
    read_telescope_data_chunked,
    copy_group,
    set_sample_fraction,
    load_model,
)
from ..configuration import AICTConfig
from ..feature_generation import feature_generation
from ..preprocessing import calc_true_disp
from ..logging import setup_logging

# use interpolation for all coordinate transforms
# 100x speed increase with no precision lost (~uas)
erfa_astrom.set(ErfaAstromInterpolator(5 * u.min))

dl3_columns = [
    "run_id",
    "event_num",
    "gamma_energy_prediction",
    "gamma_prediction",
    "disp_prediction",
    "theta_deg",
    "theta_deg_off_1",
    "theta_deg_off_2",
    "theta_deg_off_3",
    "theta_deg_off_4",
    "theta_deg_off_5",
    "pointing_position_az",
    "pointing_position_zd",
from time import perf_counter
import numpy as np
import astropy.units as u


# array with 10000 obstimes
obstime = Time('2010-01-01T20:00') + np.linspace(0, 6, 10000) * u.hour
location = location = EarthLocation(lon=-17.89 * u.deg, lat=28.76 * u.deg, height=2200 * u.m)
frame = AltAz(obstime=obstime, location=location)
crab = SkyCoord(ra='05h34m31.94s', dec='22d00m52.2s')

# transform with default transformation and print duration
t0 = perf_counter()
crab_altaz = crab.transform_to(frame)  
print(f'Transformation took {perf_counter() - t0:.2f} s')  


# transform with interpolating astrometric values
t0 = perf_counter()
with erfa_astrom.set(ErfaAstromInterpolator(300 * u.s)):
    crab_altaz_interpolated = crab.transform_to(frame)
print(f'Transformation took {perf_counter() - t0:.2f} s')  


err = crab_altaz.separation(crab_altaz_interpolated)
print(f'Mean error of interpolation: {err.to(u.microarcsecond).mean():.4f}')  


# To set erfa_astrom for a whole session, use it without context manager:
erfa_astrom.set(ErfaAstromInterpolator(300 * u.s)) 
Esempio n. 9
0
def test_warnings():

    with pytest.warns(AstropyWarning):
        with erfa_astrom.set(ErfaAstromInterpolator(9 * u.us)):
            pass