Example #1
0
def azel2radec(az_deg, el_deg, lat_deg, lon_deg, dtime):
    obs = EarthLocation(lat=lat_deg * u.deg, lon=lon_deg * u.deg)
    direc = AltAz(location=obs, obstime=Time(dtime),
                  az=az_deg * u.deg, alt=el_deg * u.deg)
    sky = SkyCoord(direc.transform_to(ICRS()))

    return sky.ra.deg, sky.dec.deg
Example #2
0
def RunAstrometryCalibration(InputImage,Outputfile=None):
    """ Does Astrometry calibration of input fits image InputImage.
        Returns True if calibration succeded."""
    # Following lines are TIRSPEC specific for formating the time from fits header
    obs_timehdr = fits.getval(InputImage,'OBSTIME')
    obs_datehdr = fits.getval(InputImage,'OBSDATE')
    time_str = '{0} {1}'.format('-'.join(obs_datehdr.split('.')),obs_timehdr)

    time = Time(time_str,format='iso',scale='utc')
    hct_hanle = EarthLocation(lat=32.77944*u.deg, lon=78.9641*u.deg, height=4500*u.m)

    zenith = AltAz(location=hct_hanle, obstime=time, az=0*u.deg, alt=90*u.deg)
    ZenithRaDec = zenith.transform_to(ICRS)

    # Finally call astrometry.net software to calibrate fits image
    Z_ra = '{0.ra}'.format(ZenithRaDec).split()[0]
    Z_dec = '{0.dec}'.format(ZenithRaDec).split()[0]
    ret = subprocess.call(['solve-field','--no-plots', '--ra',Z_ra, '--dec',Z_dec, '--radius','85', 
                           '--scale-units','arcsecperpix', '--scale-low','0.28', '--scale-high','0.32',
                           InputImage])
    print(ret)
    if ret == 0:
        if Outputfile is not None:
            print('Copying {0} to {1}'.format(os.path.splitext(InputImage)[0]+'.new',Outputfile))
            shutil.copy(os.path.splitext(InputImage)[0]+'.new',Outputfile)
        return True
    else:
        return False
Example #3
0
def azel2radec(az_deg, el_deg, lat_deg, lon_deg, dtime):
    if usevallado:
        ra_deg, dec_deg = azel2radecvallado(
                             az_deg,el_deg,lat_deg,lon_deg,dtime)
    else: #use astropy v1.0 +
        obs = EarthLocation(lat=lat_deg*u.deg, lon=lon_deg*u.deg)
        direc = AltAz(location=obs, obstime=Time(dtime),
                      az=az_deg*u.deg, alt=el_deg*u.deg)
        sky = SkyCoord(direc.transform_to(ICRS()))

    return sky.ra.deg, sky.dec.deg
Example #4
0
def azel2radec(az_deg: float, el_deg: float,
               lat_deg: float, lon_deg: float,
               time: datetime, usevallado: bool = False) -> Tuple[float, float]:
    """
    viewing angle (az, el) to sky coordinates (ra, dec)

    Parameters
    ----------
    az_deg : float or numpy.ndarray of float
         azimuth [degrees clockwize from North]
    el_deg : float or numpy.ndarray of float
             elevation [degrees above horizon (neglecting aberration)]
    lat_deg : float
              observer latitude [-90, 90]
    lon_deg : float
              observer longitude [-180, 180] (degrees)
    time : datetime.datetime or str
           time of observation
    usevallado : bool, optional
                 default use astropy. If true, use Vallado algorithm

    Returns
    -------
    ra_deg : float or numpy.ndarray of float
         ecliptic right ascension (degress)
    dec_deg : float or numpy.ndarray of float
         ecliptic declination (degrees)
    """

    if usevallado or Time is None:  # non-AstroPy method, less accurate
        return vazel2radec(az_deg, el_deg, lat_deg, lon_deg, time)

    obs = EarthLocation(lat=lat_deg * u.deg, lon=lon_deg * u.deg)

    direc = AltAz(location=obs, obstime=Time(str2dt(time)),
                  az=az_deg * u.deg, alt=el_deg * u.deg)

    sky = SkyCoord(direc.transform_to(ICRS()))

    return sky.ra.deg, sky.dec.deg
Example #5
0
def altaz_to_radec(alt=35, az=90, location=None, obstime=None, *args, **kwargs):
    """ Convert alt/az degrees to RA/Dec SkyCoord

    Args:
        alt (int, optional): Altitude, defaults to 35
        az (int, optional): Azimute, defaults to 90 (east)
        location (None, required): A ~astropy.coordinates.EarthLocation
            location must be passed.
        obstime (None, optional): Time for object, defaults to `current_time`

    Returns:
        `astropy.coordinates.SkyCoord: FK5 SkyCoord
    """
    assert location is not None
    if obstime is None:
        obstime = current_time()

    verbose = kwargs.get('verbose', False)

    if verbose:
        print("Getting coordinates for Alt {} Az {}, from {} at {}".format(alt, az, location, obstime))

    altaz = AltAz(obstime=obstime, location=location, alt=alt * u.deg, az=az * u.deg)
    return SkyCoord(altaz.transform_to(ICRS))
Example #6
0
def SUN_POS():
    """ 
    Finds sun position in RA and DEC at sunrise and sunset to find
    which parts of the sky are viewable
    """
    LIST = []
    loc = coord.EarthLocation(lon=28.7134 * u.deg, lat=17.9058 * u.deg)

    start = Time(datetime.utcnow(), format='datetime',
                 scale='utc') - TimeDelta(1, format='jd')

    for i in range(0, 384):
        T = start + TimeDelta(i * 225, format='sec')
        LST = T.sidereal_time('apparent', '28.7134d')
        TMP1 = str(LST).split('h')
        TMP2 = TMP1[1].split('m')
        TMP3 = TMP2[1].split('s')
        LST = (15 * float(TMP1[0]) + 0.0166667 * float(TMP2[0]) +
               0.000277778 * float(TMP3[0]))
        altazframe = AltAz(obstime=T, location=loc)
        sunaltaz = coord.get_sun(T).transform_to(altazframe)
        if sunaltaz.alt.value <= -47 and len(LIST) == 0:
            LIST.append(str(coord.get_sun(T).ra).split('d')[0])
            print('Sunset')
            print(T)

        elif sunaltaz.alt.value >= 48 and len(LIST) == 1:
            LIST.append(str(coord.get_sun(T).ra).split('d')[0])
            print('Sunrise')
            print(T)
            break

    UP = 30 + (float(LIST[0]) + float(LIST[1])) / 2
    LOW = (float(LIST[0]) + float(LIST[1])) / 2 - 30

    return ([UP, LOW])
Example #7
0
def test_gcrs_altaz():
    """
    Check GCRS<->AltAz transforms for round-tripping.  Has multiple paths
    """
    from astropy.coordinates import EarthLocation

    ra, dec, _ = randomly_sample_sphere(1)
    gcrs = GCRS(ra=ra[0], dec=dec[0], obstime='J2000')

    # check array times sure N-d arrays work
    times = Time(np.linspace(2456293.25, 2456657.25, 51) * u.day, format='jd')

    loc = EarthLocation(lon=10 * u.deg, lat=80. * u.deg)
    aaframe = AltAz(obstime=times, location=loc)

    aa1 = gcrs.transform_to(aaframe)
    aa2 = gcrs.transform_to(ICRS()).transform_to(CIRS()).transform_to(aaframe)
    aa3 = gcrs.transform_to(ITRS()).transform_to(CIRS()).transform_to(aaframe)

    # make sure they're all consistent
    assert_allclose(aa1.alt, aa2.alt)
    assert_allclose(aa1.az, aa2.az)
    assert_allclose(aa1.alt, aa3.alt)
    assert_allclose(aa1.az, aa3.az)
Example #8
0
    def airmass(self, ra, dec, lat_input, lon_input, height_input, time_input,
                AIRMASS_MIN, AIRMASS_MAX):
        """ Airmass calculation at a given time in a particular site."""

        # Geodetic coordinates of observatory
        observatory = astropy.coordinates.EarthLocation(lat=lat_input * u.deg,
                                                        lon=lon_input * u.deg,
                                                        height=height_input *
                                                        u.m)
        max_prob_p = SkyCoord(ra=ra * u.deg, dec=dec * u.deg,
                              frame='icrs')  # ipix sky coordinates
        time = Time(time_input)  # Time object
        altaz = max_prob_p.transform_to(
            AltAz(obstime=time,
                  location=observatory))  # Altitude-Azimuth system
        #--> Horizontal coordinates
        airmass_value = altaz.secz  # 1/cos(altaz)

        if airmass_value <= AIRMASS_MIN or airmass_value >= AIRMASS_MAX:
            airmass_value = "nan"
        else:
            airmass_value = round(airmass_value, 2)

        return airmass_value
Example #9
0
def put_radec(fitsfile,skycoo):
    """Put RA,DEC coordinates into a fits file.
    
    Parameters
    ----------
    fitsfile : string
        Fits file name to update.
    skycoo : astropy.coordinates.SkyCoord Object
        Sky coordinates of the object.
    """
    comm = {'OBJCTRA':'Nominal Right Ascension of center of image',
            'OBJCTDEC':'Nominal Declination of center of image'}
    
    hdulist = fits.open(fitsfile)
    hdu = hdulist[0]
    data = hdu.data
    try:
        target_name = hdu.header['OBJECT'].strip()
    except:
        msg = '*** FATAL ERROR: target '+target_name+' not found'
        t120.log.error(msg)
        raiseValueError(msg)
    hdu.header['OBJECT'] = (target_name.upper().replace(' ',''),'Target name')
    t120.log.info('target_name='+target_name)
    time = Time(hdu.header['DATE-OBS'])
    site = EarthLocation(lat=hdu.header['SITELAT'], lon=hdu.header['SITELONG']) 
    altazframe = AltAz(obstime=time, location=site)
    altaz = skycoo.transform_to(altazframe)
    hdu.header['OBJCTRA'] = (skycoo.ra.to('deg').value,comm['OBJCTRA'])
    hdu.header['OBJCTDEC'] = (skycoo.dec.to('deg').value,comm['OBJCTDEC'])
    hdu.header['CRVAL1'] = (skycoo.ra.to('deg').value ,'Reference Right ascencion in decimal deg')
    hdu.header['CRVAL2'] = (skycoo.dec.to('deg').value,'Reference Declination in decimal deg')
    hdu.header['HISTORY'] = 'RA,DEC values inserted with py routine.'
    hdu.writeto(fitsfile,overwrite=True)
    t120.log.info('File '+fitsfile+' successfully updated with RADEC info')
    return
Example #10
0
def get_pointing_meridian_scan(time, alt, az, location, x_position, y_position,
                              altaz=False):

    '''
    estimate the pointing RA Dec accoriding obs time and init Dec
    for drift scan pointing at meridian

    time: obs time
    '''

    c0   = SkyCoord(alt=alt, az=az, frame='altaz', location=location, obstime=time)
    c0   = c0.transform_to('icrs')

    separation = np.sqrt(x_position ** 2 + y_position ** 2) * u.arcmin
    position_angle  = np.arctan2(x_position, -y_position) * u.rad

    _c = offset_by(c0[:, None], position_angle[None, :], separation[None, :])

    #return _c.ra.deg, _c.dec.deg
    if altaz:
        _altaz = _c.transform_to(AltAz(obstime=time, location=location)).altaz
        return _altaz.alt.deg, _altaz.az.deg
    else:
        return _c.ra.deg, _c.dec.deg
Example #11
0
def hx_aer_astropy(x_gcrs, time, observer_lla=None, trans_matrix=None, observer_itrs=None):
    """
    desc: measurement function - convert state into a measurement where measurements are [azimuth, elevation]
    :param x_gcrs:
    :param time:
    :param observer_lla:
    :param trans_matrix:
    :param observer_itrs:   Observer coordinates in itrs (meters)
    :return: array[azimuth, elevation, slant]
    """
    object = SkyCoord(x=x_gcrs[0] * u.m, y=x_gcrs[1] * u.m, z=x_gcrs[2] * u.m, frame='gcrs',
                   representation_type='cartesian', obstime=time)
    if observer_itrs is None:
        obs = EarthLocation.from_geodetic(lat=observer_lla[0] * u.rad, lon=observer_lla[1] * u.rad, height=observer_lla[2] * u.m)
    else:
        obs = EarthLocation.from_geocentric(x=observer_itrs[0] * u.m, y=observer_itrs[1] * u.m, z=observer_itrs[2] * u.m)
    AltAz_frame = AltAz(obstime=time, location=obs)
    results = object.transform_to(AltAz_frame)

    az = results.az.to_value(u.rad)
    alt = results.alt.to_value(u.rad)
    sr = results.distance.to_value(u.m)
    aer = np.array([az, alt, sr])
    return aer
Example #12
0
def plot2D_runs(runs, names, source, threshold, ax=None):
    for i, df in enumerate(runs):
        ax = ax or plt.gca()
        df_selected = df.query(f'gammaness > {threshold}')
    
        crab = SkyCoord.from_name(source)
        altaz = AltAz(
            location = EarthLocation.of_site('Roque de los Muchachos'),
            obstime = Time(df_selected.dragon_time, format='unix')
        )
        telescope_pointing = SkyCoord(
            alt = u.Quantity(df_selected.alt_tel.to_numpy(), u.rad, copy=False),
            az = u.Quantity(df_selected.az_tel.to_numpy(), u.rad, copy=False),
            frame = altaz
        )
        camera_frame = CameraFrame(
            focal_length = u.Quantity(df_selected.focal_length.to_numpy(), u.m, copy=False),
            telescope_pointing = telescope_pointing,
            location = EarthLocation.of_site('Roque de los Muchachos'),
            obstime = Time(df_selected.dragon_time, format='unix')
        )
        crab_cf = crab.transform_to(camera_frame)

        crab_tf = crab_cf.transform_to(TelescopeFrame())
        ax.scatter(
            crab_tf.fov_lon.to_value(u.deg), 
            crab_tf.fov_lat.to_value(u.deg), 
            color = f'C{i}',
            marker = ',',
            label = names[i]
        )
        ax.legend()
        
    ax.set_xlabel(r'fov_lon$ \,/\, \mathrm{deg}$')
    ax.set_ylabel(r'fov_lat$ \,/\, \mathrm{deg}$')
    return ax
Example #13
0
def hx2(x,
        t,
        obs_lat=observer_lat,
        obs_lon=observer_lon,
        obs_height=observer_alt):
    # measurement function - convert state into a measurement
    # where measurements are [azimuth, elevation]
    object = SkyCoord(x=x[0] * u.km,
                      y=x[1] * u.km,
                      z=x[2] * u.km,
                      frame='gcrs',
                      representation_type='cartesian',
                      obstime=t)
    obs = EarthLocation.from_geodetic(lon=obs_lon * u.rad,
                                      lat=obs_lat * u.rad,
                                      height=obs_height * u.m)
    AltAz_frame = AltAz(obstime=t, location=obs)
    results = object.transform_to(AltAz_frame)

    az = results.az.to_value(u.rad)
    alt = results.alt.to_value(u.rad)
    sr = results.distance.to_value(u.km)
    aer = np.array([az, alt, sr])
    return aer
Example #14
0
def horizontal_to_camera_cta_simtel(alt, az, alt_pointing, az_pointing,
                                    focal_length):
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', MissingFrameAttributeWarning)

        altaz = AltAz()
        source_altaz = SkyCoord(
            alt=u.Quantity(alt, u.deg, copy=False),
            az=u.Quantity(az, u.deg, copy=False),
            frame=altaz,
        )

        tel_pointing = SkyCoord(
            alt=u.Quantity(alt_pointing, u.deg, copy=False),
            az=u.Quantity(az_pointing, u.deg, copy=False),
            frame=altaz,
        )
        camera_frame = CameraFrame(
            focal_length=u.Quantity(focal_length, u.m, copy=False),
            telescope_pointing=tel_pointing,
        )

        cam_coords = source_altaz.transform_to(camera_frame)
        return cam_coords.x.to_value(u.m), cam_coords.y.to_value(u.m)
Example #15
0
def makeTableElevConstrains(year, month):
    day = 1
    
    t0 = Time("%d-%02d-%02d 00:00:00" % (year, month, day), format = 'iso',
              scale = 'utc')

    titer = t0

    while titer.datetime.month == month:
        moonpos = astropy.coordinates.get_moon(titer, location=IAR)
        moonHA  = observer.target_hour_angle(target = moonpos, time = titer)
        moonHA  = moonHA.deg
        moonAltAz = moonpos.transform_to(AltAz(obstime = titer, location = IAR))
        if 180 < moonHA < 360:
	    moonHA = moonHA - 360.

        if (-29 <= moonHA <= -27) or (27 <= moonHA <= 29):
            print "%s,%02.02f,%0.03f,%0.02f,%0.02f" % (titer.datetime,
                                                       moonHA,
                                                       moonpos.dec.deg,
                                                       moonAltAz.az.deg,
                                                       moonAltAz.alt.deg)

        titer += fiveMins
Example #16
0
def itrs2horizon(station, ts, positions, coord_type):
    """
    Convert cartesian coordinates of targets in ITRF to spherical coordinates in topocentric reference frame for a specific station.

    Usage: 
        az,alt,rho = itrs2horizon(station,ts,ts_quasi_mjd,positions,coord_type)

    Inputs:
        station -> [numercial array or list with 3 elements] coordinates of station. It can either be geocentric(x, y, z) coordinates or geodetic(lon, lat, height) coordinates.
        Unit for (x, y, z) are meter, and for (lon, lat, height) are degree and meter.
        ts -> [str array] isot-formatted UTC for interpolated prediction
        positions -> [2d float array] target positions in cartesian coordinates in meters w.r.t. ITRF for interpolated prediction.
        coord_type -> [str] coordinates type for coordinates of station; it can either be 'geocentric' or 'geodetic'.

    Outputs:
        az -> [float array] Azimuth for interpolated prediction in degrees
        alt -> [float array] Altitude for interpolated prediction in degrees
        rho -> [float array] Range for interpolated prediction in meters
    """
    if coord_type == 'geocentric':
        x, y, z = station
        site = EarthLocation.from_geocentric(x, y, z, unit='m')
    elif coord_type == 'geodetic':
        lat, lon, height = station
        site = EarthLocation.from_geodetic(lon, lat, height)

    coords = SkyCoord(positions,
                      unit='m',
                      representation_type='cartesian',
                      frame='itrs',
                      obstime=Time(ts))
    horizon = coords.transform_to(AltAz(obstime=Time(ts), location=site))

    az, alt, rho = horizon.az.deg, horizon.alt.deg, horizon.distance.m

    return az, alt, rho
    def get_altaz_in_rotated_frame(
        self,
        time: Time,
        location: EarthLocation,
        altaz: SkyCoord,
    ) -> SkyCoord:
        """Rotates the given coordinates to the frame defined by given the altitude and
        azimuth offsets for the given time and observing_location.

        Parameters
        ----------
        time : `Time`
            The Time for which the AltAz coordinates are valid
        location : `EarthLocation`
            The observing_location for which the AltAz coordinates are valid
        altaz : `SkyCoord`
            The altitude and azimuth to rotate.

        Returns
        -------
        telescope_altaz: `SkyCoord`
            The altitude and azimuth rotated to the new frame.
        """
        telescope_altaz = AltAz(alt=self.delta_alt,
                                az=self.delta_az,
                                obstime=time,
                                location=location)
        telescope_frame = altaz.transform_to(
            SkyOffsetFrame(origin=telescope_altaz))
        return SkyCoord(
            alt=Angle(telescope_frame.lon.deg * u.deg),
            az=Angle(telescope_frame.lat.deg * u.deg),
            frame="altaz",
            obstime=time,
            location=location,
        )
Example #18
0
def test_separation_is_the_same():
    from ctapipe.coordinates import TelescopeFrame

    obstime = Time('2013-11-01T03:00')
    location = EarthLocation.of_site('Roque de los Muchachos')
    horizon_frame = AltAz(location=location, obstime=obstime)

    crab = SkyCoord(ra='05h34m31.94s', dec='22d00m52.2s')
    ceta_tauri = SkyCoord(ra='5h37m38.6854231s', dec='21d08m33.158804s')

    # simulate crab "on" observations
    telescope_pointing = crab.transform_to(horizon_frame)

    telescope_frame = TelescopeFrame(
        telescope_pointing=telescope_pointing,
        location=location,
        obstime=obstime,
    )

    ceta_tauri_telescope = ceta_tauri.transform_to(telescope_frame)
    crab_telescope = crab.transform_to(telescope_frame)

    sep = ceta_tauri_telescope.separation(crab_telescope).to_value(u.deg)
    assert ceta_tauri.separation(crab).to_value(u.deg) == approx(sep, rel=1e-4)
Example #19
0
def _orientation(location, time='now'):
    """
    Return the orientation angle for the Sun from a specified Earth location and time.  The
    orientation angle is the angle between local zenith and solar north, measured eastward from
    local zenith.

    Parameters
    ----------
    location : `~astropy.coordinates.EarthLocation`
        Observer location on Earth
    time : {parse_time_types}
        Time to use in a parse_time-compatible format

    Returns
    -------
    out : `~astropy.coordinates.Angle`
        The orientation of the Sun
    """
    obstime = parse_time(time)

    # Define the frame where its Z axis is aligned with local zenith
    local_frame = AltAz(obstime=obstime, location=location)

    return _sun_north_angle_to_z(local_frame)
Example #20
0
def test_regression_5133():
    N = 1000
    np.random.seed(12345)
    lon = np.random.uniform(-10, 10, N) * u.deg
    lat = np.random.uniform(50, 52, N) * u.deg
    alt = np.random.uniform(0, 10., N) * u.km

    time = Time('2010-1-1')

    objects = EarthLocation.from_geodetic(lon, lat, height=alt)
    itrs_coo = objects.get_itrs(time)

    homes = [
        EarthLocation.from_geodetic(lon=-1 * u.deg, lat=52 * u.deg, height=h)
        for h in (0, 1000, 10000) * u.km
    ]

    altaz_frames = [AltAz(obstime=time, location=h) for h in homes]
    altaz_coos = [itrs_coo.transform_to(f) for f in altaz_frames]

    # they should all be different
    for coo in altaz_coos[1:]:
        assert not quantity_allclose(coo.az, coo.az[0])
        assert not quantity_allclose(coo.alt, coo.alt[0])
def astropy_parallactic_angles(times, antenna_positions, field_centre):
    """
    Computes parallactic angles per timestep for the given
    reference antenna position and field centre.
    """
    ap = antenna_positions
    fc = field_centre

    # Convert from MJD second to MJD
    times = Time(times / 86400.00, format='mjd', scale='utc')

    ap = EarthLocation.from_geocentric(
        ap[:, 0], ap[:, 1], ap[:, 2], unit='m')
    fc = SkyCoord(ra=fc[0], dec=fc[1], unit=units.rad, frame='fk5')
    pole = SkyCoord(ra=0, dec=90, unit=units.deg, frame='fk5')

    cirs_frame = CIRS(obstime=times)
    pole_cirs = pole.transform_to(cirs_frame)
    fc_cirs = fc.transform_to(cirs_frame)

    altaz_frame = AltAz(location=ap[None, :], obstime=times[:, None])
    pole_altaz = pole_cirs[:, None].transform_to(altaz_frame)
    fc_altaz = fc_cirs[:, None].transform_to(altaz_frame)
    return fc_altaz.position_angle(pole_altaz)
Example #22
0
    def save_png(self, figname: str, beam_contours: bool = True, show_sources: bool = True, **kwargs):
        """ """
        image_center = altaz_to_radec(
            SkyCoord(
                self.analog_pointing.az,
                self.analog_pointing.alt,
                frame=AltAz(
                    obstime=self.tv_image.time[0],
                    location=nenufar_position
                )
            )
        )

        #kwargs = {}

        if show_sources:
            src_names = []
            src_position = []

            with open(join(dirname(__file__), "nenufar_tv_sources.json")) as src_file:
                sources = json.load(src_file)

            for name in sources["FixedSources"]:
                src = FixedTarget.from_name(name, time=self.tv_image.time[0])
                if src.coordinates.separation(image_center) <= 0.8*self.fov_radius:
                    src_names.append(name)
                    src_position.append(src.coordinates)
            for name in sources["SolarSystemSources"]:
                src = SolarSystemTarget.from_name(name, time=self.tv_image.time[0])
                if src.coordinates.separation(image_center) <= 0.8*self.fov_radius:
                    src_names.append(name)
                    src_position.append(src.coordinates)

            if len(src_position) != 0:
                kwargs["text"] = (SkyCoord(src_position), src_names, "white")

        if beam_contours:
            # Simulate the array factor
            ma = MiniArray()
            af_sky = ma.array_factor(
                sky=HpxSky(
                    resolution=0.2*u.deg,
                    time=self.tv_image.time[0],
                    frequency=self.tv_image.frequency[0]
                ),
                pointing=Pointing(
                    coordinates=image_center,
                    time=self.tv_image.time[0]
                )
            )
            # Normalize the array factor
            af = af_sky[0, 0, 0].compute()
            af_normalized = af/af.max()
            kwargs["contour"] = (af_normalized, np.arange(0.5, 1, 0.2), "copper")

        # Plot
        self.tv_image[0, 0, 0].plot(
            center=image_center,
            radius=self.fov_radius - 2.5*u.deg,
            figname=figname,
            colorbar_label=f"Stokes {self.tv_image.polarization[0]}",
            **kwargs
        )
        return
Example #23
0
    def rephase_visibilities(self, phase_center, uvw):
        """ """

        # Compute the zenith original phase center
        zenith = SkyCoord(
            np.zeros(self.time.size),
            np.ones(self.time.size)*90,
            unit="deg",
            frame=AltAz(
                obstime=self.time,
                location=nenufar_position
            )
        )
        zenith_phase_center = altaz_to_radec(zenith)

        # Define the rotation matrix
        def rotation_matrix(skycoord):
            """
            """
            ra_rad = skycoord.ra.rad
            dec_rad = skycoord.dec.rad

            if np.isscalar(ra_rad):
                ra_rad = np.array([ra_rad])
                dec_rad = np.array([dec_rad])

            cos_ra = np.cos(ra_rad)
            sin_ra = np.sin(ra_rad)
            cos_dec = np.cos(dec_rad)
            sin_dec = np.sin(dec_rad)

            return np.array([
                [cos_ra, -sin_ra, np.zeros(ra_rad.size)],
                [-sin_ra*sin_dec, -cos_ra*sin_dec, cos_dec],
                [sin_ra*cos_dec, cos_ra*cos_dec, sin_dec],
            ])

        # Transformation matrices
        to_origin = rotation_matrix(zenith_phase_center) # (3, 3, ntimes)
        to_new_center = rotation_matrix(phase_center) # (3, 3, 1)
        total_transformation = np.matmul(
            np.transpose(
                to_new_center,
                (2, 0, 1)
            ),
            to_origin
        ) # (3, 3, ntimes)
        rotUVW = np.matmul(
            np.expand_dims(
                (to_origin[2, :] - to_new_center[2, :]).T,
                axis=1
            ),
            np.transpose(
                to_origin,
                (2, 1, 0)
            )
        ) # (ntimes, 1, 3)
        phase = np.matmul(
            rotUVW,
            np.transpose(uvw, (0, 2, 1))
        ) # (ntimes, 1, nvis)
        rotate_visibilities = np.exp(
            2.j*np.pi*phase/wavelength(self.frequency).to(u.m).value[None, :, None]
        ) # (ntimes, nfreqs, nvis)

        new_uvw = np.matmul(
            uvw, # (ntimes, nvis, 3)
            np.transpose(total_transformation, (2, 0, 1))
        )

        return rotate_visibilities, new_uvw
Example #24
0
    def coordinate_calc(self,
                        x_list,
                        y_list,
                        time_list,
                        coord,
                        off_az,
                        off_el,
                        hosei,
                        lamda,
                        press,
                        temp,
                        humi,
                        limit=True,
                        rotation=True):
        """
        x_list and y_list == [deg]
        """
        if coord == "planet":
            planet_flag = True
            coord = "altaz"
        else:
            planet_flag = False
            pass
        # coordinate check len(x_list)=len(y_list)=len(time_list)
        frame = self.coord_list[coord.lower()]
        az_list = []
        el_list = []
        if frame == "altaz":
            az_list = list(map(lambda k: k + off_az, x_list))
            el_list = list(map(lambda k: k + off_el, y_list))

            if planet_flag == True:
                tmp_az_list = []
                tmp_el_list = []
                for i in range(len(az_list)):
                    azel_list = self.kisa_calc2(az_list[i], el_list[i], hosei)
                    tmp_az_list.append(azel_list[0] + off_az)
                    tmp_el_list.append(azel_list[1] + off_el)
                az_list = tmp_az_list
                el_list = tmp_el_list
            else:
                pass

        else:
            on_coord = SkyCoord(
                x_list,
                y_list,
                frame=frame,
                unit='arcsec',
            )

            # convert_azel
            nanten2 = EarthLocation(lat=self.latitude * u.deg,
                                    lon=self.longitude * u.deg,
                                    height=self.height * u.m)
            on_coord.location = nanten2
            on_coord.pressure = press * u.hPa  #weather correction
            on_coord.temperature = temp * u.deg_C  #weather correction
            on_coord.relative_humidity = humi  #weather correction
            on_coord.obswl = lamda * u.um  #weather correction

            altaz_list = on_coord.transform_to(AltAz(obstime=time_list))

            for i in range(len(altaz_list)):
                azel_list = self.kisa_calc(altaz_list[i], hosei)
                az_list.append(azel_list[0] + off_az)
                el_list.append(azel_list[1] + off_el)
                #az_list.append(altaz_list[i].az.arcsec+off_az) #no_kisa
                #el_list.append(altaz_list[i].alt.arcsec+off_el) #no_kisa

            pass

        if rotation == False:
            az_list = [
                i - 360 * 3600. if i > 180 * 3600. else i for i in az_list
            ]
            az_list = [
                i + 360 * 3600. if i < -180 * 3600. else i for i in az_list
            ]
        #print("az :",az_list[0]/3600.,"el :", el_list[0]/3600.)

        return [az_list, el_list]
Example #25
0
def analyze_muon_event(event):
    """
    Generic muon event analyzer.

    Parameters
    ----------
    event : ctapipe dl1 event container


    Returns
    -------
    muonringparam, muonintensityparam : MuonRingParameter
    and MuonIntensityParameter container event

    """

    names = [
        'LST_LST_LSTCam', 'MST_MST_NectarCam', 'MST_MST_FlashCam',
        'MST_SCT_SCTCam', 'SST_1M_DigiCam', 'SST_GCT_CHEC',
        'SST_ASTRI_ASTRICam', 'SST_ASTRI_CHEC'
    ]
    tail_cuts = [(5, 7), (5, 7), (10, 12), (5, 7), (5, 7), (5, 7), (5, 7),
                 (5, 7)]  # 10, 12?
    impact = [(0.2, 0.9), (0.1, 0.95), (0.2, 0.9), (0.2, 0.9), (0.1, 0.95),
              (0.1, 0.95), (0.1, 0.95), (0.1, 0.95)] * u.m
    ringwidth = [(0.04, 0.08), (0.02, 0.1), (0.01, 0.1), (0.02, 0.1),
                 (0.01, 0.5), (0.02, 0.2), (0.02, 0.2), (0.02, 0.2)] * u.deg
    total_pix = [1855., 1855., 1764., 11328., 1296., 2048., 2368., 2048]
    # 8% (or 6%) as limit
    min_pix = [148., 148., 141., 680., 104., 164., 142., 164]
    # Need to either convert from the pixel area in m^2 or check the camera specs
    ang_pixel_width = [0.1, 0.2, 0.18, 0.067, 0.24, 0.2, 0.17, 0.2, 0.163
                       ] * u.deg
    # Found from TDRs (or the pixel area)
    hole_rad = [
        0.308 * u.m, 0.244 * u.m, 0.244 * u.m, 4.3866 * u.m, 0.160 * u.m,
        0.130 * u.m, 0.171 * u.m, 0.171 * u.m
    ]  # Assuming approximately spherical hole
    cam_rad = [2.26, 3.96, 3.87, 4., 4.45, 2.86, 5.25, 2.86] * u.deg
    # Above found from the field of view calculation
    sec_rad = [
        0. * u.m, 0. * u.m, 0. * u.m, 2.7 * u.m, 0. * u.m, 1. * u.m, 1.8 * u.m,
        1.8 * u.m
    ]
    sct = [False, False, False, True, False, True, True, True]
    # Added cleaning here. All these options should go to an input card
    cleaning = True

    muon_cuts = {
        'Name': names,
        'tail_cuts': tail_cuts,
        'Impact': impact,
        'RingWidth': ringwidth,
        'total_pix': total_pix,
        'min_pix': min_pix,
        'CamRad': cam_rad,
        'SecRad': sec_rad,
        'SCT': sct,
        'AngPixW': ang_pixel_width,
        'HoleRad': hole_rad
    }
    logger.debug(muon_cuts)

    muonringlist = []  # [None] * len(event.dl0.tels_with_data)
    muonintensitylist = []  # [None] * len(event.dl0.tels_with_data)
    tellist = []
    muon_event_param = {
        'TelIds': tellist,
        'MuonRingParams': muonringlist,
        'MuonIntensityParams': muonintensitylist
    }

    for telid in event.dl0.tels_with_data:

        logger.debug("Analysing muon event for tel %d", telid)
        image = event.dl1.tel[telid].image

        # Get geometry
        teldes = event.inst.subarray.tel[telid]
        geom = teldes.camera
        x, y = geom.pix_x, geom.pix_y

        dict_index = muon_cuts['Name'].index(str(teldes))
        logger.debug('found an index of %d for camera %d', dict_index,
                     geom.cam_id)

        tailcuts = muon_cuts['tail_cuts'][dict_index]
        logger.debug("Tailcuts are %s", tailcuts)

        clean_mask = tailcuts_clean(geom,
                                    image,
                                    picture_thresh=tailcuts[0],
                                    boundary_thresh=tailcuts[1])

        # TODO: correct this hack for values over 90
        altval = event.mcheader.run_array_direction[1]
        if altval > Angle(90, unit=u.deg):
            warnings.warn('Altitude over 90 degrees')
            altval = Angle(90, unit=u.deg)

        telescope_pointing = SkyCoord(alt=altval,
                                      az=event.mcheader.run_array_direction[0],
                                      frame=AltAz())
        camera_coord = SkyCoord(
            x=x,
            y=y,
            frame=CameraFrame(
                focal_length=teldes.optics.equivalent_focal_length,
                rotation=geom.pix_rotation,
                telescope_pointing=telescope_pointing,
            ))

        nom_coord = camera_coord.transform_to(
            NominalFrame(origin=telescope_pointing))
        x = nom_coord.delta_az.to(u.deg)
        y = nom_coord.delta_alt.to(u.deg)

        if (cleaning):
            img = image * clean_mask
        else:
            img = image

        muonring = ChaudhuriKunduRingFitter(None)

        logger.debug("img: %s mask: %s, x=%s y= %s", np.sum(image),
                     np.sum(clean_mask), x, y)

        if not sum(img):  # Nothing left after tail cuts
            continue

        muonringparam = muonring.fit(x, y, image * clean_mask)

        dist = np.sqrt(
            np.power(x - muonringparam.ring_center_x, 2) +
            np.power(y - muonringparam.ring_center_y, 2))
        ring_dist = np.abs(dist - muonringparam.ring_radius)

        muonringparam = muonring.fit(
            x, y, img * (ring_dist < muonringparam.ring_radius * 0.4))

        dist = np.sqrt(
            np.power(x - muonringparam.ring_center_x, 2) +
            np.power(y - muonringparam.ring_center_y, 2))
        ring_dist = np.abs(dist - muonringparam.ring_radius)

        muonringparam = muonring.fit(
            x, y, img * (ring_dist < muonringparam.ring_radius * 0.4))

        muonringparam.tel_id = telid
        muonringparam.obs_id = event.dl0.obs_id
        muonringparam.event_id = event.dl0.event_id
        dist_mask = np.abs(
            dist - muonringparam.ring_radius) < muonringparam.ring_radius * 0.4
        pix_im = image * dist_mask
        nom_dist = np.sqrt(
            np.power(muonringparam.ring_center_x, 2) +
            np.power(muonringparam.ring_center_y, 2))

        minpix = muon_cuts['min_pix'][dict_index]  # 0.06*numpix #or 8%

        mir_rad = np.sqrt(teldes.optics.mirror_area.to("m2") / np.pi)

        # Camera containment radius -  better than nothing - guess pixel
        # diameter of 0.11, all cameras are perfectly circular   cam_rad =
        # np.sqrt(numpix*0.11/(2.*np.pi))

        if (npix_above_threshold(pix_im, tailcuts[0]) > 0.1 * minpix
                and npix_composing_ring(pix_im) > minpix
                and nom_dist < muon_cuts['CamRad'][dict_index]
                and muonringparam.ring_radius < 1.5 * u.deg
                and muonringparam.ring_radius > 1. * u.deg):
            muonringparam.ring_containment = ring_containment(
                muonringparam.ring_radius, muon_cuts['CamRad'][dict_index],
                muonringparam.ring_center_x, muonringparam.ring_center_y)

            # Guess HESS is 0.16
            # sec_rad = 0.*u.m
            # sct = False
            # if numpix == 2048 and mir_rad > 2.*u.m and mir_rad < 2.1*u.m:
            #     sec_rad = 1.*u.m
            #     sct = True
            #
            # Store muon ring parameters (passing cuts stage 1)
            # muonringlist[idx] = muonringparam

            tellist.append(telid)
            muonringlist.append(muonringparam)
            muonintensitylist.append(None)

            ctel = MuonLineIntegrate(
                mir_rad,
                hole_radius=muon_cuts['HoleRad'][dict_index],
                pixel_width=muon_cuts['AngPixW'][dict_index],
                sct_flag=muon_cuts['SCT'][dict_index],
                secondary_radius=muon_cuts['SecRad'][dict_index])

            if image.shape[0] == muon_cuts['total_pix'][dict_index]:
                muonintensityoutput = ctel.fit_muon(
                    muonringparam.ring_center_x, muonringparam.ring_center_y,
                    muonringparam.ring_radius, x[dist_mask], y[dist_mask],
                    image[dist_mask])

                muonintensityoutput.tel_id = telid
                muonintensityoutput.obs_id = event.dl0.obs_id
                muonintensityoutput.event_id = event.dl0.event_id
                muonintensityoutput.mask = dist_mask

                idx_ring = np.nonzero(pix_im)
                muonintensityoutput.ring_completeness = ring_completeness(
                    x[idx_ring],
                    y[idx_ring],
                    pix_im[idx_ring],
                    muonringparam.ring_radius,
                    muonringparam.ring_center_x,
                    muonringparam.ring_center_y,
                    threshold=30,
                    bins=30)
                muonintensityoutput.ring_size = np.sum(pix_im)

                dist_ringwidth_mask = np.abs(
                    dist - muonringparam.ring_radius) < (
                        muonintensityoutput.ring_width)
                pix_ringwidth_im = image * dist_ringwidth_mask
                idx_ringwidth = np.nonzero(pix_ringwidth_im)

                muonintensityoutput.ring_pix_completeness = npix_above_threshold(
                    pix_ringwidth_im[idx_ringwidth], tailcuts[0]) / len(
                        pix_im[idx_ringwidth])

                logger.debug(
                    "Tel %d Impact parameter = %s mir_rad=%s "
                    "ring_width=%s", telid,
                    muonintensityoutput.impact_parameter, mir_rad,
                    muonintensityoutput.ring_width)
                conditions = [
                    muonintensityoutput.impact_parameter * u.m <
                    muon_cuts['Impact'][dict_index][1] * mir_rad,
                    muonintensityoutput.impact_parameter >
                    muon_cuts['Impact'][dict_index][0],
                    muonintensityoutput.ring_width <
                    muon_cuts['RingWidth'][dict_index][1],
                    muonintensityoutput.ring_width >
                    muon_cuts['RingWidth'][dict_index][0]
                ]

                if all(conditions):
                    muonintensityparam = muonintensityoutput
                    idx = tellist.index(telid)
                    muonintensitylist[idx] = muonintensityparam
                    logger.debug("Muon found in tel %d,  tels in event=%d",
                                 telid, len(event.dl0.tels_with_data))
                else:
                    continue

    return muon_event_param
Example #26
0
def pwv(location,
        Ra=None,
        Dec=None,
        P_min=300,
        P_max=750,
        line_of_site='zenith',
        plot=False):
    """
    Compute the precipitable water vapor at ``location`` in direction of
    ``line_of_site``.

    Parameters
    ----------
    location : `~fyodor.Location`
        Location of observatory.
    Ra : float
        Right ascension of target
    Dec : float
        Declination of target
    P_min : float
        Minimum pressure (hPa)
    P_max : float
        Maximum pressure (hPa)
    line_of_site :  str, {"target", "zenith"}
        Either compute line of sight to the target or to the zenith.
    plot : bool
        Generate a plot of the PWV at each time.

    Returns
    -------
    dates : list

    PWV : `~numpy.ndarray`
    """
    params = load_files()
    times, day, epoch, date, nc_filesT, nc_filesM, h, e, r_pol = params[:9]
    r_eq, P, H, lon_origin, g16_data_file = params[9:]

    # Pressure level boundaries
    P_min = np.abs(P - P_min).argmin()
    P_max = np.abs(P - P_max).argmin()

    # Convert from radian to degrees:
    Ra = float(Ra)
    Dec = float(Dec)
    Sky = SkyCoord(ra=Ra * u.degree, dec=Dec * u.degree)
    Aa = Sky.transform_to(
        AltAz(obstime=times, location=location.to_EarthLocation()))
    latt = Dec
    lont = Ra

    # Computes PWV along line of sight
    if line_of_site == 'target':
        INDEX = np.ravel(np.where(Aa.alt.degree < 30))
        INDEXP = np.ravel(np.where(Aa.alt.degree > 30))

        # Keep time values corresponding to Alt above 30 degrees
        EPOCH = epoch
        for index in sorted(INDEX, reverse=True):
            del EPOCH[index]
        DATE = []
        for i in range(0, len(epoch)):
            DATEt = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(EPOCH[i]))
            DATE.append(DATEt)

        Alt = Aa.alt.rad
        Az = Aa.az.rad

        # Compute distance from location to projection point
        delta_x = []
        d_lat = []
        d_lon = []

        for i in range(0, len(Alt)):
            delta_xi = []
            for j in h:
                delta_xt = j / np.tan(Alt[i])
                delta_xt = delta_xt * u.m**-1
                delta_xi.append(delta_xt)
            delta_x.append(delta_xi)
        delta_x = np.array(delta_x)

        for i in range(0, len(Az)):
            d_latt = delta_x[i, ] * np.cos(Az[i])
            d_lont = delta_x[i, ] * np.sin(Az[i])
            d_lat.append(d_latt)
            d_lon.append(d_lont)
        d_lat = np.array(d_lat)
        d_lon = np.array(d_lon)

        # Compute latitude and longitude of projection points
        lat_proj = []
        lon_proj = []
        for i in range(0, len(Alt)):
            obs_latt = (
                location.latdeg +
                np.degrees(np.arctan(d_lat[i, ] * u.m / R_earth)).value)
            obs_lont = (
                location.londeg +
                np.degrees(np.arctan(d_lon[i, ] * u.m / R_earth)).value)
            lat_proj.append(obs_latt)
            lon_proj.append(obs_lont)
        lat_proj = np.array(lat_proj)
        lon_proj = np.array(lon_proj)

        lat_proj_rad = np.radians(lat_proj)
        lon_proj_rad = np.radians(lon_proj)
        lambda_0 = np.radians(lon_origin)

        # Transform into scan angles
        lat_origin = np.arctan(r_pol**2 / r_eq**2 * np.tan(lat_proj_rad))
        r_c = r_pol / np.sqrt(1 - (e**2) * np.cos(lat_origin)**2)

        x, y = geodetic_to_cartesian(lat_origin, lon_proj_rad, lambda_0, r_c,
                                     H)

        g16_data_fileT = []
        xscanT = []
        yscanT = []
        XT = []
        YT = []
        LVT = []

        # Retrieve Temperature data
        for i in INDEXP:
            g16_data = nc_filesT[i]
            g16_data_fileT.append(g16_data)
            g16 = Dataset(nc_filesT[i], 'r')
            xtemp = g16.variables['x'][:]
            xscanT.append(xtemp)
            ytemp = g16.variables['y'][:]
            yscanT.append(ytemp)

            LVTi = []
            Xi = []
            Yi = []
            for j in range(P_min, P_max + 1):
                Xtemp = np.abs(xtemp - x[i, j]).argmin()
                Xi.append(Xtemp)
                Ytemp = np.abs(ytemp - y[i, j]).argmin()
                Yi.append(Ytemp)
                LVTtemp = g16.variables['LVT'][Ytemp, Xtemp, j]
                LVTi.append(LVTtemp)
            LVT.append(LVTi)
            XT.append(Xi)
            YT.append(Yi)
        LVT = np.array(LVT)

        # Retrieve Relative humidity data
        g16_data_fileM = []
        xscanM = []
        yscanM = []
        XM = []
        YM = []
        LVM = []

        for i in INDEXP:
            g16_dataM = nc_filesM[i]
            g16_data_fileM.append(g16_dataM)
            g16M = Dataset(nc_filesM[i], 'r')
            xtempM = g16M.variables['x'][:]
            xscanM.append(xtempM)
            ytempM = g16M.variables['y'][:]
            yscanM.append(ytempM)

            LVMi = []
            Xi = []
            Yi = []
            for j in range(P_min, P_max + 1):
                XtempM = np.abs(xtempM - x[i, j]).argmin()
                Xi.append(XtempM)
                YtempM = np.abs(ytempM - y[i, j]).argmin()
                Yi.append(YtempM)
                LVMtemp = g16M.variables['LVM'][YtempM, XtempM, j]
                LVMi.append(LVMtemp)
            LVM.append(LVMi)
            XM.append(Xi)
            YM.append(Yi)
        LVM = np.array(LVM)

        P = 100 * P
        LVT = LVT - 273.15

        Pi = P[P_min:P_max + 1]

        PWV = pwv_integral(LVT, LVM, Pi)

        if plot:
            # Plot and save data
            fig = plt.figure(figsize=(8, 5))
            ax = fig.add_subplot(111)
            ax.plot(DATE, PWV, 'bo', ms=4)
            plt.title('Precipitable Water Vapor along line of sight, {} on {}'.
                      format(location.site, day[0]),
                      fontsize=20)
            plt.xticks(rotation='vertical', fontsize=16)
            plt.yticks(fontsize=16)
            ax.set_xlabel("Date", color="C0", fontsize=18)
            ax.set_ylabel("PWV (mm)", color="C0", fontsize=18)
            RA_patch = mpatches.Patch(color='white',
                                      label='RA: {} degrees'.format(Ra))
            Dec_patch = mpatches.Patch(color='white',
                                       label='Dec: {} degrees'.format(Dec))
            every_nth = 4
            for n, label in enumerate(ax.xaxis.get_ticklabels()):
                if n % every_nth != 0:
                    label.set_visible(False)
            for n, label in enumerate(ax.xaxis.get_ticklines()):
                if n % every_nth != 0:
                    label.set_visible(False)
            plt.tight_layout()
            plt.legend(handles=[RA_patch, Dec_patch],
                       loc='lower right',
                       fontsize=18)
        out_date = DATE

    # Computes PWV at zenith
    elif line_of_site == 'zenith':

        # Transform latitude and longitude into scan angles
        lambda_0 = np.radians(lon_origin)
        obs_lat_rad = np.radians(latt)
        obs_lon_rad = np.radians(lont)

        lat_origin = np.arctan(r_pol**2 / r_eq**2 * np.tan(obs_lat_rad))

        r_c = r_pol / (np.sqrt(1 - (e**2) * (np.cos(lat_origin))**2))

        x, y = geodetic_to_cartesian(lat_origin, obs_lon_rad, lambda_0, r_c, H)

        xscanT = []
        yscanT = []

        # Retrieve Temperature data
        LVT = []
        for i in range(0, len(nc_filesT)):
            g16_data = nc_filesT[i]
            g16_data_file.append(g16_data)
            g16 = Dataset(g16_data_file[i], 'r')
            xtemp = g16.variables['x'][:]
            xscanT.append(xtemp)
            ytemp = g16.variables['y'][:]
            yscanT.append(ytemp)

            XT = []
            YT = []
            LVTi = []
            for j in range(0, len(P)):
                Xtemp = np.abs(xtemp - x).argmin()
                XT.append(Xtemp)
                Ytemp = np.abs(ytemp - y).argmin()
                YT.append(Ytemp)
                LVTtemp = g16.variables['LVT'][Ytemp, Xtemp, j]
                LVTi.append(LVTtemp)
            LVT.append(LVTi)

        LVT = np.array(LVT)

        # Retrieve Relative humidity data
        g16_data_fileM = []
        xscanM = []
        yscanM = []
        LVM = []

        for i in range(0, len(nc_filesM)):
            g16_dataM = nc_filesM[i]
            g16_data_fileM.append(g16_dataM)
            g16M = Dataset(g16_data_fileM[i], 'r')
            xtempM = g16M.variables['x'][:]
            xscanM.append(xtempM)
            ytempM = g16M.variables['y'][:]
            yscanM.append(ytempM)

            XM = []
            YM = []
            LVMi = []
            for j in range(0, len(P)):
                XtempM = np.abs(xtempM - x).argmin()
                XM.append(XtempM)
                YtempM = np.abs(ytempM - y).argmin()
                YM.append(YtempM)
                LVMtemp = g16M.variables['LVM'][YtempM, XtempM, j]
                LVMi.append(LVMtemp)
            LVM.append(LVMi)

        LVM = np.array(LVM)

        # Change pressure units to Pa and Temperature to K
        P = 100 * P
        LVT = LVT - 273.15

        PWV = pwv_integral(LVT, LVM, P)

        if plot:
            fig = plt.figure(figsize=(8, 5))
            ax = fig.add_subplot(111)
            ax.plot(date, PWV, 'bo', ms=4)
            plt.title('Precipitable Water Vapor at zenith, {} on {}'.format(
                location.site, day[0]),
                      fontsize=20)
            plt.xticks(rotation='vertical', fontsize=16)
            plt.yticks(fontsize=16)
            ax.set_xlabel("Date", color="C0", fontsize=18)
            ax.set_ylabel("PWV (mm)", color="C0", fontsize=18)
            every_nth = 4
            for n, label in enumerate(ax.xaxis.get_ticklabels()):
                if n % every_nth != 0:
                    label.set_visible(False)
            for n, label in enumerate(ax.xaxis.get_ticklines()):
                if n % every_nth != 0:
                    label.set_visible(False)
            plt.tight_layout()

        out_date = date

    return out_date, PWV
Example #27
0
def showPfsDesign(pfsDesigns,
                  date=None,
                  timerange=8,
                  showTime=None,
                  showDesignId=True):
    """Show the altitude at Subaru of the available pfsDesigns as a function of time.

    pfsDesigns: array of `pfs.datamodel.PfsDesign`
       The available designs
    date: `str` or ``None``
       The desired date; if None use today (in HST)
       If None, also show the current time unless showTime is False
    timerange: `int`
       Total number of hours to show, centred at midnight
    showTime: `bool` or `None`
       If False don't show the current time even if known
    showDesignId: `bool`
       Include the pfsDesignId in the labels
    """
    if date is None:
        now = datetime.datetime.now(pytz.timezone('US/Hawaii'))
        date = now.date()

        now += datetime.timedelta(utcoffset /
                                  24)  # all times are actually kept in UTC
    else:
        now = None

    midnight = Time(f'{date} 00:00:00')  # UTC, damn astropy
    time = midnight + np.linspace(24 - timerange / 2, 24 + timerange / 2,
                                  100) * u.hour

    global subaru
    if subaru is None:
        subaru = EarthLocation.of_site('Subaru')

    telstate = AltAz(obstime=time - utcoffset * u.hour,
                     location=subaru)  # AltAz needs UTC

    xformatter = mdates.DateFormatter('%H:%M')
    plt.gca().xaxis.set_major_formatter(xformatter)

    for pfsDesign in pfsDesigns:
        boresight = SkyCoord(ra=pfsDesign.raBoresight * u.degree,
                             dec=pfsDesign.decBoresight * u.degree,
                             frame='icrs')

        label = showDesignId
        plt.plot(time.datetime,
                 boresight.transform_to(telstate).alt,
                 label=f"0x{pfsDesign.pfsDesignId:x} {pfsDesign.designName}"
                 if showDesignId else pfsDesign.designName)

    plt.gcf().autofmt_xdate()
    plt.legend(prop={"family": "monospace"} if showDesignId else {})

    if now is not None and showTime is not False:
        plt.axvline(now, ls='-', color='black', alpha=0.5)

    plt.ylim(max([-1, plt.ylim()[0]]), None)

    plt.xlabel("Local Time")
    plt.ylabel("Altitude (deg)")
    plt.title(f"{date}")
Example #28
0
def altaz2radec(altaz, location, obstime=None, epoch_RA=2000.0, time_type=None):

    """
    ----------------------------------------------------------------------------
    Convert Alt-Az to RA-Dec with accurate ephemeris

    Inputs:

    altaz   [numpy array] Altitude and Azimuth as a Nx2 numpy array. All units 
            in degrees

    location
            [instance of class astropy.coordinates.EarthLocation] Location of
            the observer provided as an instance of class 
            astropy.coordinates.EarthLocation

    obstime [scalar, string, or instance of class astropy.time.Time] The time 
            or epoch which applies to input altaz. It can be a scalar (in JD 
            or JYear), string (JYear string prefixed with 'J' or ISO or ISOT), 
            or an instance of class astropy.time.Time. The appropriate format 
            must be specified in input time_type. If set to None (default), it 
            will be set equal to epoch_RA. 

    epoch_RA
            [scalar, string, or instance of class astropy.time.Time] The time 
            or epoch which applies to output radec. It can be a scalar (in JD 
            or JYear), string (JYear string prefixed with 'J' or ISO or ISOT), 
            or an instance of class astropy.time.Time. The appropriate format 
            must be specified in input time_type. It must be in the same format 
            as the one obstime is specified in. If set to 2000.0 (default), it 
            is assumed to be in 'jyear' format. If set to None, it will be set 
            equal to default of 2000.0 in 'jyear' format. 

    time_type
            [string] Specifies the format in which obstime and epoch_RA are
            provided. Accepted values are 'jd' (Julian Day), 'jyear' (Julian 
            year), 'iso' or 'isot'. If set to None (default) and if obstime 
            and/or epoch_RA is a scalar, the corresponding scalar entries are
            assumed to be in Julian Year. 

    Output:

    The output radec as a numpy array of shape (N,2) in units of degrees is 
    returned at the epoch specified in epoch_RA.
    ----------------------------------------------------------------------------
    """

    if isinstance(altaz, NP.ndarray):
        if altaz.size == 2:
            altaz = altaz.reshape(1,-1)
        if altaz.ndim != 2:
            raise ValueError('Input altaz must be a numpy array of shape (N,2)')
        if altaz.shape[1] != 2:
            raise ValueError('Input altaz must be a numpy array of shape (N,2)')
    elif not isinstance(altaz, AltAz):
        raise TypeError('Input altaz must be a numpy array or an instance of class astropy.coordinates.AltAz')

    if not isinstance(location, EarthLocation):
        raise TypeError('Input location must be an instance of class astropy.coordinates.EarthLocation')

    if epoch_RA is not None:
        if isinstance(epoch_RA, (int,float)):
            if (time_type is None) or (time_type.lower() == 'jyear'):
                equinox_RA = Time(epoch_RA, scale='utc', format='jyear')
            elif time_type.lower() == 'jd':
                equinox_RA = Time(epoch_RA, scale='utc', format='jd')
        elif isinstance(epoch_RA, str):
            if time_type.lower() == 'jyear':
                equinox_RA = Time('J{0:.9f}'.format(epoch_RA), scale='utc', format='jyear_str')
            elif (time_type.lower() == 'iso') or (time_type.lower() == 'isot'):
                equinox_RA = Time(epoch_RA, scale='utc', format=time_type.lower())
        elif isinstance(epoch_RA, Time):
            equinox_RA = copy.copy(epoch_RA)
        else:
            raise TypeError('Input epoch_RA is invalid or currently not accepted')
    else:
        equinox_RA = Time(2000.0, format='jyear', scale='utc')
        warnings.warn('No epoch_RA provided. Setting epoch to {0}'.format(equinox_RA.jyear_str))
        
    if obstime is not None:
        if isinstance(obstime, (int,float)):
            if (time_type is None) or (time_type.lower() == 'jyear'):
                equinox_altaz = Time(obstime, scale='utc', format='jyear')
            elif time_type.lower() == 'jd':
                equinox_altaz = Time(obstime, scale='utc', format='jd')
        elif isinstance(obstime, str):
            if time_type.lower() == 'jyear':
                equinox_altaz = Time('J{0:.9f}'.format(obstime), scale='utc', format='jyear_str')
            if (time_type.lower() == 'iso') or (time_type.lower() == 'isot'):
                equinox_altaz = Time(obstime, scale='utc', format=time_type.lower())
        elif isinstance(obstime, Time):
            equinox_altaz = copy.copy(obstime)
        else:
            raise TypeError('Input obstime is invalid or currently not accepted')
    else:
        if isinstance(altaz, AltAz):
            equinox_altaz = copy.deepcopy(altaz.obstime)
        else:
            equinox_altaz = copy.copy(equinox_RA)
        warnings.warn('No obstime provided. Setting obstime to {0}'.format(equinox_altaz.jyear_str))
        
    if isinstance(altaz, AltAz):
        elaz = copy.deepcopy(altaz)
    else:
        elaz = AltAz(alt=altaz[:,0]*U.deg, az=altaz[:,1]*U.deg, obstime=equinox_altaz, location=location)
    coords_radec = elaz.transform_to(FK5(equinox=equinox_RA))
    radec = NP.hstack((coords_radec.ra.deg.reshape(-1,1), coords_radec.dec.deg.reshape(-1,1)))
    return radec
Example #29
0
observation_time = ephem.Date('2018/3/30 03:00:00.00')

for i in xrange(len(data)):
    observer = ephem.Observer()
    observer.lon = np.radians(mandi_lon)
    observer.lat = np.radians(mandi_lat)
    observer.elevation = 1000
    observer.date = observation_time

    output_alt, output_az = [], []

    for l in xrange(5):
        names = ['Star1', 'Star2', 'Star3', 'Star4', 'Star5']
        ra, dec = observer.radec_of(np.radians(stars_az[l]),
                                    np.radians(stars_alt[l]))
        ab = data[i]
        lato, lono = ab['latitude'], ab['longitude']
        new_location = EarthLocation(lat=lato, lon=lono, height=100 * u.m)
        new_time = Time('2018-3-30 12:00:00')
        aa = AltAz(location=new_location, obstime=new_time)
        coord = SkyCoord(str(ra), str(dec), unit='deg')
        g = coord.transform_to(aa)
        az, alt = boring_function(str(g.az)), boring_function(str(g.alt))
        output_az.append(az)
        output_alt.append(alt)
        wb = load_workbook('output.xlsx')
        sheet = wb.get_sheet_by_name('N-W')
        sheet[putter_string[l] +
              str(i + 2)] = "alt=" + str(alt) + ", az=" + str(az)
        wb.save(filename='output.xlsx')
Example #30
0
def run(obs,
        method,
        h5parmFilename,
        maxdtec=0.5,
        maxvtec=50,
        alphaIon=11 / 3,
        hIon=250e3,
        vIon=20,
        seed=0,
        fitsFilename=None,
        stepname='tec',
        angRes=60,
        expfolder='',
        ncpu=0):
    """
    Simulate TEC values and store them to a h5parm.

    Parameters
    ----------
    method : str
        Method to use:
        "fits": read TEC values from the FITS cube specified by fitsFilename
        "tid": generate a traveling ionospheric disturbance (TID) wave
        "turbulence": generate a turbulent ionosphere
    h5parmFilename : str
        Filename of output h5parm file.
    maxdtec : float, optional. Default = 0.5
        Maximum screen dTEC per timestep in TECU.
    maxvtec: float, optional. Default = 50.
        Highest vTEC in daily modulation in TECU.
    alphaIon: float, optional. Default = 11/3.
        Ionosphere power spectrum exponent. Is 11/3 for Kolmogorov,
        de Gasperin and Mevius found 3.89 for LOFAR.
    hIon : float, optional. Default = 250 km
        Height of thin layer ionoshpere.
    vIono : float, optional. Default = 20 m/s
        Velocity of tecscreen. This controls the tec variation frequency.
    seed: int, optional.
        Random screen seed. Use for reproducibility.
    fitsFilename : str, optional
        Filename of input FITS cube with dTEC solutions.
    stepname _ str, optional
        Name of step to use in DPPP parset
    angRes : float, optional. Default = 60.
        Angular resolution of the screen [arcsec]. Only for turbulent model.
    expfolder : str, optional. Default = None
        Export the tecscreen data to this folder for plotting. Depending on
        system memory, this will not work for very large/highres screens.
        Only for 'turbulence' method.
    ncpu : int, optional
        Number of cores to use, by default all available.
    """
    # TODO : Test TID and polynomial method for multi-ms usage
    method = method.lower()
    if ncpu == 0:
        ncpu = mp.cpu_count()
    # Get sky model properties
    ras, decs = obs.get_patch_coords()
    source_names = obs.get_patch_names()
    ants = obs.stations
    sp = obs.stationpositions
    times = obs.get_times()

    tecvals = np.zeros((len(times), len(ants), len(ras)))
    weights = np.ones_like(tecvals)

    if method == 'turbulence':
        directions = np.array([ras, decs]).T
        tecvals = comoving_tecscreen(sp,
                                     directions,
                                     times,
                                     alpha=alphaIon,
                                     angRes=angRes,
                                     hIon=hIon,
                                     vIon=vIon,
                                     maxvtec=maxvtec,
                                     maxdtec=maxdtec,
                                     ncpu=ncpu,
                                     expfolder=expfolder,
                                     seed=seed)
    elif method == 'fits':
        # Load solutions from FITS cube
        hdu = pyfits.open(fitsFilename, memmap=False)
        data = hdu[0].data
        header = hdu[0].header
        w = wcs.WCS(header)
        ntimes, _, nstations, ny, nx = data.shape

        # Check that number of stations in input FITS cube matches MS
        if nstations != len(ants):
            logger.error('Number of stations in input FITS cube does not '
                         'match that in the input MS')
            return 1

        # Get solutions at the source coords
        for d, (ra_deg, dec_deg) in enumerate(zip(ras, decs)):
            ra_dec = np.array([[ra_deg, dec_deg, 0, 0, 0]])
            x = int(w.wcs_world2pix(ra_dec, 0)[0][0])
            y = int(w.wcs_world2pix(ra_dec, 0)[0][1])
            if x < 0 or x > nx or y < 0 or y > ny:
                tecvals[:, :, d, :] = 0.0
                weights[:, :, d, :] = 0.0
                continue
            for t in range(ntimes):
                for s in range(nstations):
                    tecvals[t, s, d] = data[t, 0, s, y, x]
        tecvals = daytime_tec_modulation(times)[:, np.newaxis, np.newaxis] * (
            tecvals + maxvtec)

    elif method == 'tid':
        # Properties of TID wave
        tidLen = 200e3
        tidVel = 500e3 / 3600,
        tid_prop = [maxdtec, tidLen, tidVel]
        # Generate solutions for TID wave
        A12 = EarthLocation(lat=52.91 * u.deg,
                            lon=6.87 * u.deg,
                            height=1 * u.m)
        mjd = Time(times / (3600.0 * 24.0), format="mjd")

        aa = AltAz(location=A12, obstime=mjd)
        altazcoord = []
        pool = mp.Pool(processes=ncpu)
        radec = [(r, d, aa) for r, d in zip(ras, decs)]
        altazcoord = pool.map(_getaltaz, radec)
        gettec_args = [(a, sp, A12, times, *tid_prop) for a in altazcoord]
        alltec = pool.map(_gettec, gettec_args)
        pool.close()
        pool.join()
        alltec = np.array(alltec)
        # Fill the axis arrays
        tecvals = alltec[:, :, 0, :].transpose([2, 1, 0])  # [:,:,:,0]
        # convert to vTEC
        tecvals = daytime_tec_modulation(times)[:, np.newaxis, np.newaxis] * (
            tecvals + maxvtec)

    else:
        logger.error('method "{}" not understood'.format(method))
        return 1

    # Write tec values to h5parm file as DPPP input
    ho = h5parm(h5parmFilename, readonly=False)

    if 'sol000' in ho.getSolsetNames():
        solset = ho.getSolset('sol000')
    else:
        solset = ho.makeSolset(solsetName='sol000')

    if 'tec000' in solset.getSoltabNames():
        logger.info('''Solution-table tec000 is already present in
                 {}. It will be overwritten.'''.format(h5parmFilename +
                                                       '/sol000'))
        solset.getSoltab('tec000').delete()

    st = solset.makeSoltab('tec',
                           'tec000',
                           axesNames=['time', 'ant', 'dir'],
                           axesVals=[times, ants, source_names],
                           vals=tecvals,
                           weights=weights)
    antennaTable = solset.obj._f_get_child('antenna')
    antennaTable.append(list(zip(*(ants, sp))))
    sourceTable = solset.obj._f_get_child('source')
    vals = [[ra, dec] for ra, dec in zip(ras, decs)]
    sourceTable.append(list(zip(*(source_names, vals))))

    # Add CREATE entry to history
    soltabs = solset.getSoltabs()
    for st in soltabs:
        st.addHistory('CREATE (by TEC operation of LoSiTo from obs {0} '
                      'and method="{{1}}")'.format(h5parmFilename, method))
    ho.close()

    # Update predict parset parameters for the obs
    obs.add_to_parset(stepname, 'tec000', h5parmFilename)

    return 0
Example #31
0
def get_observation_site_location():
    current_time = get_current_time()
    observation_site = get_current_location()
    observation_site_frame = AltAz(obstime=current_time,
                                   location=observation_site)
    return observation_site_frame
        Greenland = EarthLocation( lat=Angle(72.5796, 'deg'),
                                  lon=Angle(-38.4592, 'deg'),
                                  height=3200 * u.m),
        Tibet     = EarthLocation( lat=Angle(32.3166667, 'deg'),
                                  lon=Angle(80.0166666667, 'deg'),
                                  height=5100 * u.m),
)

location = locations[LOCATION]

start_time = Time(datetime.datetime(2015, 8, 1), scale='ut1')
sampling_interval = TimeDelta(SAMPLING, format="sec")
time = start_time + sampling_interval * np.arange(0., HOURS*3600/SAMPLING)

# zenith
altaz = AltAz(az=Angle(0., unit=u.degree), alt=ELEVATION, obstime=time, location=location)
radec = altaz.transform_to(ICRS)
ra_zenith = radec.ra.radian
dec_zenith = radec.dec.radian

# local north
altaz = AltAz(az=Angle(0., unit=u.degree), alt=Angle(0., unit=u.degree), obstime=time, location=location)
radec = altaz.transform_to(ICRS)
ra_north = radec.ra.radian
dec_north = radec.dec.radian

import pandas as pd

pd.DataFrame({"ra_zenith_rad":ra_zenith, "dec_zenith_rad":dec_zenith, 
    "ra_north_rad":ra_north, "dec_north_rad":dec_north}, index=time.datetime).to_hdf("zenith_pointing_" + LOCATION.lower() + ".h5", "data")
Example #33
0
    def execute(self, command):
        t = Time(Time.now(), location=self.location)

        altaz = SkyCoord(self.STATE['az'],
                         self.STATE['alt'],
                         unit=(u.hour, u.deg),
                         frame=AltAz(obstime=t, location=self.location))

        # Apply state changes based on the command.
        if command == 'Abort':
            self.STATE['status'].slewing = 0
            self.STATE['status'].tracking = 0
        elif command == 'Park':
            self.STATE['alt'] = 50
            self.STATE['az'] = 90
            self.STATE['status'].parked = 1
        elif command == 'UnPark':
            self.STATE['status'].parked = 0
        elif command.startswith('GoToAltAz'):
            command, az, alt = command.split(' ')

            altaz = SkyCoord(az,
                             alt,
                             unit=u.deg,
                             frame=AltAz(obstime=t, location=self.location))

            self.STATE['destination']['alt'] = altaz.alt.deg
            self.STATE['destination']['az'] = altaz.az.deg

            # Slew to the given alt/az, updating current alt and az as we go.
            # TODO: threading.Thread(target=self._slew_altaz).start()
            self.STATE['alt'] = altaz.alt.deg
            self.STATE['az'] = altaz.az.deg
        elif command.startswith('GoTo'):
            command, ra, dec, equinox = command.split(' ')

            radec = SkyCoord(ra,
                             dec,
                             unit=(u.hour, u.deg),
                             equinox='J2000',
                             obstime=t,
                             location=self.location)

            self.STATE['destination']['ra'] = radec.ra.hour
            self.STATE['destination']['dec'] = radec.dec.deg
            self.STATE['destination']['equinox'] = str(equinox)
            self.STATE['destination']['alt'] = radec.altaz.alt.deg
            self.STATE['destination']['az'] = radec.altaz.az.deg

            # Slew to the given ra/dec, updating current ra and dec as we go.
            # TODO: threading.Thread(target=self._slew_radec).start()
            self.STATE['ra'] = radec.ra.hour
            self.STATE['dec'] = radec.dec.deg

            self.STATE['status'].tracking = 1
        elif command.startswith('SetTrackMode'):
            command, tracking, track_type, ra_rate, dec_rate = command.split(
                ' ')

            self.STATE['status'].tracking = int(tracking)
            self.STATE['status'].non_sidereal_tracking = int(track_type)

            self.STATE.update({
                'tracking': {
                    'enabled': int(tracking),
                    'ra_rate': float(ra_rate),
                    'dec_rate': float(dec_rate),
                },
            })
        elif command.startswith('SyncToAltAz'):
            command, az, alt = command.split(' ')

            self.STATE['alt'] = float(alt)
            self.STATE['az'] = float(az)
        elif command.startswith('Sync'):
            command, ra, dec, type_, equinox = command.split(' ')

            self.STATE['ra'] = float(ra)
            self.STATE['dec'] = float(dec)
            self.STATE['equinox'] = equinox
        elif command.startswith('PulseGuide'):
            pass  # TODO
        elif command == 'MotorsToBlinky':
            self.STATE['status'].manual = 1
        elif command == 'MotorsToAuto':
            self.STATE['status'].manual = 0
        elif command.startswith('CookCoordinates'):
            pass  # TODO
        elif command.startswith('UnCookCoordinates'):
            pass  # TODO
        elif command.startswith('JogArcSeconds'):
            command, direction, arcsec = command.split(' ')

            arcsec = float(arcsec) * u.arcsec

            if direction == 'N':
                self.STATE['dec'] = (Angle(self.STATE['dec'] * u.deg) +
                                     arcsec).value
            elif direction == 'S':
                self.STATE['dec'] = (Angle(self.STATE['dec'] * u.deg) -
                                     arcsec).value
            elif direction == 'E':
                self.STATE['ra'] = (Angle(self.STATE['ra'] * u.hour) +
                                    arcsec).value
            elif direction == 'W':
                self.STATE['ra'] = (Angle(self.STATE['ra'] * u.hour) -
                                    arcsec).value

        # Construct a response based on the issued command.
        if command == 'ReadScopeDestination':
            response = '{};{};{};{};{};{};{};{};{};{};{};_'.format(
                self.STATE['status'].value,
                self.STATE['destination']['ra'],
                self.STATE['destination']['dec'],
                self.STATE['destination']['alt'],
                self.STATE['destination']['az'],
                self.STATE['secondary_axis_angle'],
                self.STATE['primary_axis_angle'],
                t.sidereal_time(kind='apparent').hour,
                t.jd,
                self.STATE['time'],
                altaz.secz,
            )
        elif command == 'RotatorComms':
            response = '{};{};{};{};{};{};{};{};{};{};{};_'.format(
                self.STATE['status'].value,
                self.STATE['ra'],
                self.STATE['dec'],
                self.STATE['alt'],
                self.STATE['az'],
                self.STATE['derotator'][
                    self.STATE['instrument']]['parallactic_angle'],
                self.STATE['derotator'][
                    self.STATE['instrument']]['parallactic_rate'],
                self.STATE['derotator'][
                    self.STATE['instrument']]['camera_solved_angle'],
                self.STATE['derotator'][self.STATE['instrument']]
                ['destination_position'],
                self.STATE['time'],
                altaz.secz,
            )
        elif command == 'SiteLocations':
            response = '{};{};{};_SiteLocations'.format(
                self.location.lat.value, self.location.lon.value,
                self.location.height.value)
        else:
            response = '{};{};{};{};{};{};{};{};{};{};{};_'.format(
                self.STATE['status'].value,
                self.STATE['ra'],
                self.STATE['dec'],
                self.STATE['alt'],
                self.STATE['az'],
                self.STATE['secondary_axis_angle'],
                self.STATE['primary_axis_angle'],
                t.sidereal_time(kind='apparent').hour,
                t.jd,
                self.STATE['time'],
                altaz.secz,
            )

        return response + Driver.TERMINATOR
def get_instrumental_mags(data, coords, obsname, ext):
    '''
    Takes a hipercam data object, and exctracts the instrumental magnitude of each aperture in each CCD

    If Coords and an observatory are supplied, also correct for airmass, using supplied extinction coeffiecients


    Arguments:
    ----------
    data: hipercam.Hlog
        The data to analyse. tseries will be extracted from here.

    coords: str
        Ra, Dec of the data. Must be readable by Astropy.

    obsname: str
        Observing location name of the data.

    ext: iterable
        Extinction corrections to apply, given in CCD order. i.e. [<CCD1 ext>, <CCD2 ext>, ...]


    Returns:
    --------
    all_mags: dict
        Dict, with the keys corresponding to the CCD numbers. Each entry is a numpy array of the
        instrumental magnitudes, in the order they're found in the aperture list.
    '''
    logger.printer("------- Getting instrumental magnitude -------")

    logger.printer("  I'm correcting for airmass, using the following:")
    logger.printer("     Extinction: {} mags/airmass".format(ext))
    logger.printer("        Ra, Dec: {}".format(coords))
    logger.printer("    Observatory: {}".format(obsname))

    # Where are we?
    try:
        observatory = coord.EarthLocation.of_site(obsname)
        logger.printer("Observatory successfully retrieved from site name")
    except:
        obsname = obsname.split(',')
        if len(obsname) != 2:
            logger.printer("  The (lat, lon) MUST!!! be comma separated!")
            exit()
        lat, lon = obsname
        logger.printer(
            "  Earth location from latitude, longitude: {}, {}".format(
                lat, lon))
        observatory = coord.EarthLocation.from_geodetic(lat=lat, lon=lon)

    star_loc = coord.SkyCoord(coords, unit=(u.hourangle, u.deg))

    # I want altitude converted to zenith angle.
    obs_T = data.tseries('1', '1').t
    obs_T = time.Time(obs_T, format='mjd')

    # Define the altAz frame, containing the time and location
    altAz_frame = AltAz(obstime=obs_T, location=observatory)
    star_loc_AltAz = star_loc.transform_to(altAz_frame)

    # Compute the airmass, at the time of the first frame
    zenith_angle = 90 - star_loc_AltAz.alt.deg
    zenith_angle_rad = np.deg2rad(zenith_angle)
    airmass = 1. / np.cos(zenith_angle_rad)

    logger.printer(
        "  For the observations starting at {} and ending at {}...".format(
            obs_T[0].iso, obs_T[-1].iso))
    logger.printer(
        "   -> Zenith angle starts at {:.3f}, and ends at {:.3f}".format(
            zenith_angle[0], zenith_angle[-1]))
    logger.printer("   -> Airmass starts at {:.3f}, ends at {:.3f}".format(
        airmass[0], airmass[-1]))

    # I'll use the mean for reporting.
    mean_airmass = np.mean(airmass)
    logger.printer("Mean airmass: {:.3f}".format(mean_airmass))
    if np.any(airmass) <= 0:
        logger.printer("Airmass is negative!! We have a problem there!")
        logger.printer("EarthLocation (constructed from {}):".format(obsname))
        logger.printer(str(observatory))
        logger.printer(str(observatory.lat), str(observatory.lon))
        logger.printer("Star location:")
        logger.printer(str(star_loc))
        input("Hit enter to continue... ")

    logger.printer(
        "\nGetting the INSTRUMENTAL (electron flux) magnitudes for the log file"
    )

    all_mags = {}
    aps = data.apnames
    CCDs = [str(i + 1) for i, key in enumerate(aps)]

    if ext is None:
        logger.printer("NOT applying extinction corrections!!!")
        ext = [0.0 for i in CCDs]
    ext = np.array(ext)

    # Data masking stuff
    FLAG = np.uint32(0)
    for f in FLAGS_TO_IGNORE:
        FLAG = FLAG | f
    if FLAG:
        logger.printer("  Ignoring bad data flags: {}".format(FLAGS_TO_IGNORE))
        logger.printer("List of keys:")
        logger.printer(hcam.FLAGS)

    for CCD in CCDs:
        logger.printer("\n---> Doing CCD {} <---".format(CCD))
        # information gathering
        ap = sorted(aps[CCD])
        ex = ext[int(CCD) - 1]
        exptime = data[CCD]['Exptim']

        # star magnitudes
        mags = []

        for comp in ap:
            logger.printer("")
            star = data.tseries(CCD, comp)

            ### AIRMASSES ###
            # I want altitude converted to zenith angle.
            obs_T = star.t
            obs_T = time.Time(obs_T, format='mjd')

            # Define the altAz frame, containing the time and location
            altAz_frame = AltAz(obstime=obs_T, location=observatory)
            star_loc_AltAz = star_loc.transform_to(altAz_frame)

            # Compute the airmass, at the time of the first frame
            zenith_angle = 90 - star_loc_AltAz.alt.deg
            zenith_angle_rad = np.deg2rad(zenith_angle)
            airmass = 1. / np.cos(zenith_angle_rad)

            # Mask out data that has flags
            # Filter out flags I don't care about.
            star.mask = star.mask & (~FLAG)
            mask = star.mask != 0
            # First and last data are never good
            mask[0] = True
            mask[-1] = True
            if np.any(star.mask):
                removed = np.sum(star.mask != 0)

                logger.printer("Bad data detected!")
                logger.printer(
                    "The mask will remove {}/{} data points.".format(
                        removed, len(star.y)))

            # star counts/s
            fl = star.y / exptime

            # Get magnitudes, and apply atmospheric extinction correction to each frame.
            aperture_mags = -2.5 * np.log10(fl)
            aperture_mags -= (ex * airmass)

            # Take a clipped mean
            mag, mag_median, mag_sigma = sigma_clipped_stats(aperture_mags,
                                                             mask=mask,
                                                             sigma=3.0)

            # Just for reporting
            counts_per_frame = np.mean(star.y[np.where(mask == False)])
            counts_per_frame_err = np.std(star.y[np.where(mask == False)])

            logger.printer(
                "Aperture {} had a clipped mean counts per frame of {:.2f}+/-{:.2f}"
                .format(comp, counts_per_frame, counts_per_frame_err))
            logger.printer("  and a mean exposure time of {:.3f}s".format(
                np.mean(exptime)))
            # logger.printer("  Pre-ext correct: CCD {}, Ap {}, mag: {:.3f}+/-{:.3f}".format(CCD, comp, -2.5*np.log10(fl), mag_sigma))
            mags.append(mag)
        mags = np.array(mags)

        logger.printer("  CCD {} extinction: {:.3f} mags".format(
            CCD, ex * mean_airmass))
        logger.printer("  Post-ext correct:")
        for i, mag in enumerate(mags):
            logger.printer("    Ap {}: {:.3f} mags".format(i, mag))
        logger.printer("\n\n")

        all_mags[CCD] = np.array(mags)
    return all_mags
Example #35
0
def enu_to_enu(from_coo, to_frame):
    # for now we just implement this through AltAz to make sure we get everything
    # covered
    return from_coo.transform_to(
        AltAz(obstime=from_coo.obstime)).transform_to(to_frame)
Example #36
0
 def altaz_frame(self):
     """ALT / AZ frame (`~astropy.coordinates.AltAz`)."""
     return AltAz(obstime=self.time, location=self.location)
Example #37
0
    def plot(self, date):
        """
        Produce plot of the object visability for date
        Modified from https://docs.astropy.org/en/stable/generated/examples/coordinates/plot_obs-planning.html
        """

        import matplotlib.pyplot as plt
        from astropy.visualization import astropy_mpl_style
        plt.style.use(astropy_mpl_style)

        midnight = self.observer.midnight(date, which='next')
        delta_midnight = np.linspace(-2, 10, 100) * u.hour
        frame_night = AltAz(obstime=midnight + delta_midnight,
                            location=self.location)
        targetaltazs_night = self.target.transform_to(frame_night)

        # Use  `~astropy.coordinates.get_sun` to find the location of the Sun at 1000

        from astropy.coordinates import get_sun
        delta_midnight = np.linspace(-12, 12, 1000) * u.hour
        times = midnight + delta_midnight
        frame = AltAz(obstime=times, location=self.location)
        sunaltazs = get_sun(times).transform_to(frame)

        # Do the same with `~astropy.coordinates.get_moon` to find when the moon is
        # up. Be aware that this will need to download a 10MB file from the internet
        # to get a precise location of the moon.

        from astropy.coordinates import get_moon
        moon = get_moon(times)
        moonaltazs = moon.transform_to(frame)

        ##############################################################################
        # Find the alt,az coordinates of M33 at those same times:

        targetaltazs = self.target.transform_to(frame)

        ##############################################################################
        # Make a beautiful figure illustrating nighttime and the altitudes of M33 and
        # the Sun over that time:

        plt.plot(delta_midnight, sunaltazs.alt, color='r', label='Sun')
        plt.plot(delta_midnight,
                 moonaltazs.alt,
                 color=[0.75] * 3,
                 ls='--',
                 label='Moon')
        plt.scatter(delta_midnight,
                    targetaltazs.alt,
                    c=targetaltazs.az,
                    label='Target',
                    lw=0,
                    s=8,
                    cmap='viridis')
        plt.fill_between(delta_midnight.to('hr').value,
                         0,
                         90,
                         sunaltazs.alt < -0 * u.deg,
                         color='0.5',
                         zorder=0)
        plt.fill_between(delta_midnight.to('hr').value,
                         0,
                         90,
                         sunaltazs.alt < -18 * u.deg,
                         color='k',
                         zorder=0)
        plt.hlines(self.altConstraint,
                   -12,
                   12,
                   colors='red',
                   linestyles='dotted',
                   lw=1)
        plt.colorbar().set_label('Azimuth [deg]')
        plt.legend(loc='upper left')
        plt.xlim(-12, 12)
        plt.xticks(np.arange(13) * 2 - 12)
        plt.ylim(0, 90)
        plt.xlabel('Hours from Local Midnight')
        plt.ylabel('Altitude [deg]')
        plt.show()
Example #38
0
def make_test_observation_table(observatory_name='HESS', n_obs=10,
                                datestart=None, dateend=None,
                                use_abs_time=False,
                                random_state='random-seed'):
    """Make a test observation table.

    For the moment, only random observation tables are created.
    If `datestart` and `dateend` are specified, the starting time
    of the observations will be restricted to the specified interval.
    These parameters are interpreted as date, the precise hour of the
    day is ignored, unless the end date is closer than 1 day to the
    starting date, in which case, the precise time of the day is also
    considered.

    Parameters
    ----------
    observatory_name : str
        Name of the observatory; a list of choices is given in
        `~gammapy.obs.observatory_locations`.
    n_obs : int
        Number of observations for the obs table.
    datestart : `~astropy.time.Time`, optional
        Starting date for random generation of observation start time.
    dateend : `~astropy.time.Time`, optional
        Ending date for random generation of observation start time.
    use_abs_time : bool, optional
        Use absolute UTC times instead of [MET]_ seconds after the reference.
    random_state : {int, 'random-seed', 'global-rng', `~numpy.random.RandomState`}, optional
        Defines random number generator initialisation.
        Passed to `~gammapy.utils.random.get_random_state`.

    Returns
    -------
    obs_table : `~gammapy.obs.ObservationTable`
        Observation table.
    """
    random_state = get_random_state(random_state)

    n_obs_start = 1

    obs_table = ObservationTable()

    # build a time reference as the start of 2010
    dateref = Time('2010-01-01T00:00:00', format='isot', scale='utc')
    dateref_mjd_fra, dateref_mjd_int = np.modf(dateref.mjd)

    # define table header
    obs_table.meta['OBSERVATORY_NAME'] = observatory_name
    obs_table.meta['MJDREFI'] = dateref_mjd_int
    obs_table.meta['MJDREFF'] = dateref_mjd_fra
    if use_abs_time:
        # show the observation times in UTC
        obs_table.meta['TIME_FORMAT'] = 'absolute'
    else:
        # show the observation times in seconds after the reference
        obs_table.meta['TIME_FORMAT'] = 'relative'
    header = obs_table.meta

    # obs id
    obs_id = np.arange(n_obs_start, n_obs_start + n_obs)
    obs_table['OBS_ID'] = obs_id

    # obs time: 30 min
    time_observation = Quantity(30. * np.ones_like(obs_id), 'minute').to('second')
    obs_table['TIME_OBSERVATION'] = time_observation

    # livetime: 25 min
    time_live = Quantity(25. * np.ones_like(obs_id), 'minute').to('second')
    obs_table['TIME_LIVE'] = time_live

    # start time
    #  - random points between the start of 2010 and the end of 2014 (unless
    # otherwise specified)
    #  - using the start of 2010 as a reference time for the header of the table
    #  - observations restrict to night time (only if specified time interval is
    # more than 1 day)
    #  - considering start of astronomical day at midday: implicit in setting
    # the start of the night, when generating random night hours
    if datestart == None:
        datestart = Time('2010-01-01T00:00:00', format='isot', scale='utc')
    if dateend == None:
        dateend = Time('2015-01-01T00:00:00', format='isot', scale='utc')
    time_start = random_state.uniform(datestart.mjd, dateend.mjd, len(obs_id))
    time_start = Time(time_start, format='mjd', scale='utc')

    # check if time interval selected is more than 1 day
    if (dateend - datestart).jd > 1.:
        # keep only the integer part (i.e. the day, not the fraction of the day)
        time_start_f, time_start_i = np.modf(time_start.mjd)
        time_start = Time(time_start_i, format='mjd', scale='utc')

        # random generation of night hours: 6 h (from 22 h to 4 h), leaving 1/2 h
        # time for the last run to finish
        night_start = Quantity(22., 'hour')
        night_duration = Quantity(5.5, 'hour')
        hour_start = random_state.uniform(night_start.value,
                                 night_start.value + night_duration.value,
                                 len(obs_id))
        hour_start = Quantity(hour_start, 'hour')

        # add night hour to integer part of MJD
        time_start += hour_start

    if use_abs_time:
        # show the observation times in UTC
        time_start = Time(time_start.isot)
    else:
        # show the observation times in seconds after the reference
        time_start = time_relative_to_ref(time_start, header)
        # converting to quantity (better treatment of units)
        time_start = Quantity(time_start.sec, 'second')

    obs_table['TIME_START'] = time_start

    # stop time
    # calculated as TIME_START + TIME_OBSERVATION
    if use_abs_time:
        time_stop = Time(obs_table['TIME_START'])
        time_stop += TimeDelta(obs_table['TIME_OBSERVATION'])
    else:
        time_stop = TimeDelta(obs_table['TIME_START'])
        time_stop += TimeDelta(obs_table['TIME_OBSERVATION'])
        # converting to quantity (better treatment of units)
        time_stop = Quantity(time_stop.sec, 'second')

    obs_table['TIME_STOP'] = time_stop

    # az, alt
    # random points in a sphere above 45 deg altitude
    az, alt = sample_sphere(size=len(obs_id),
                            lon_range=Angle([0, 360], 'degree'),
                            lat_range=Angle([45, 90], 'degree'),
                            random_state=random_state)
    az = Angle(az, 'degree')
    alt = Angle(alt, 'degree')
    obs_table['AZ'] = az
    obs_table['ALT'] = alt

    # RA, dec
    # derive from az, alt taking into account that alt, az represent the values
    # at the middle of the observation, i.e. at time_ref + (TIME_START + TIME_STOP)/2
    # (or better: time_ref + TIME_START + (TIME_OBSERVATION/2))
    # in use_abs_time mode, the time_ref should not be added, since it's already included
    # in TIME_START and TIME_STOP
    az = Angle(obs_table['AZ'])
    alt = Angle(obs_table['ALT'])
    if use_abs_time:
        obstime = Time(obs_table['TIME_START'])
        obstime += TimeDelta(obs_table['TIME_OBSERVATION']) / 2.
    else:
        obstime = time_ref_from_dict(obs_table.meta)
        obstime += TimeDelta(obs_table['TIME_START'])
        obstime += TimeDelta(obs_table['TIME_OBSERVATION']) / 2.
    location = observatory_locations[observatory_name]
    alt_az_coord = AltAz(az=az, alt=alt, obstime=obstime, location=location)
    sky_coord = alt_az_coord.transform_to(FK5)
    obs_table['RA'] = sky_coord.ra
    obs_table['DEC'] = sky_coord.dec

    # positions

    # number of telescopes
    # random integers between 3 and 4
    n_tels_min = 3
    n_tels_max = 4
    n_tels = random_state.randint(n_tels_min, n_tels_max + 1, len(obs_id))
    obs_table['N_TELS'] = n_tels

    # muon efficiency
    # random between 0.6 and 1.0
    muon_efficiency = random_state.uniform(low=0.6, high=1.0, size=len(obs_id))
    obs_table['MUON_EFFICIENCY'] = muon_efficiency

    return obs_table