Пример #1
0
def add_obsairmass_df_comp_obs(df_comp_obs, site_dict, df_comps, df_images):
    observer = Observer(longitude=site_dict['longitude'] * u.deg,
                        latitude=site_dict['latitude'] * u.deg,
                        elevation=site_dict['elevation'] * u.m)
    df_comp_obs['ObsAirmass'] = None
    skycoord_dict = {
        comp_id: SkyCoord(ra=ra_deg * u.deg, dec=dec_deg * u.deg)
        for (comp_id, ra_deg, dec_deg
             ) in zip(df_comps.index, df_comps['RA_deg'], df_comps['Dec_deg'])
    }
    altaz_frame_dict = {
        filename: observer.altaz(Time(jd_mid, format='jd'))
        for (filename,
             jd_mid) in zip(df_images['FITSfile'], df_images['JD_mid'])
    }
    print('ObsAirmasses: ', end='', flush=True)
    done_count = 0
    for obs, filename, comp_id in zip(df_comp_obs.index,
                                      df_comp_obs['FITSfile'],
                                      df_comp_obs['CompID']):
        alt = skycoord_dict[comp_id].transform_to(
            altaz_frame_dict[filename]).alt.value
        df_comp_obs.loc[obs,
                        'ObsAirmass'] = 1.0 / sin(alt / DEGREES_PER_RADIAN)
        done_count += 1
        if done_count % 100 == 0:
            print('.', end='', flush=True)
    print('\nObsAirmasses written to df_comp_obs:', str(len(df_comp_obs)))
Пример #2
0
def add_obsairmass_df_mp_obs(df_mp_obs, site_dict, df_images):
    observer = Observer(longitude=site_dict['longitude'] * u.deg,
                        latitude=site_dict['latitude'] * u.deg,
                        elevation=site_dict['elevation'] * u.m)
    df_mp_obs['ObsAirmass'] = None
    skycoord_dict = {
        filename: SkyCoord(ra=ra_deg * u.deg, dec=dec_deg * u.deg)
        for (filename, ra_deg,
             dec_deg) in zip(df_mp_obs['FITSfile'], df_mp_obs['RA_deg_mid'],
                             df_mp_obs['Dec_deg_mid'])
    }
    altaz_frame_dict = {
        filename: observer.altaz(Time(jd_mid, format='jd'))
        for (filename,
             jd_mid) in zip(df_images['FITSfile'], df_images['JD_mid'])
    }
    for obs, filename in zip(df_mp_obs.index, df_mp_obs['FITSfile']):
        alt = skycoord_dict[filename].transform_to(
            altaz_frame_dict[filename]).alt.value
        df_mp_obs.loc[obs, 'ObsAirmass'] = 1.0 / sin(alt / DEGREES_PER_RADIAN)
    print('ObsAirmasses written to df_mp_obs:', str(len(df_mp_obs)))
Пример #3
0
class Station(object):
    """Defines an astronomical station (antenna).
    A station is defined by some names and codenames, coordinates, and its sensitivity for the
    radio bands (wavelengths) it can observe.
    Apart of the metadata related to the station, it allows to compute the altitude/azimuth, elevation,
    or simply when a source is visible from the station for a given time range.
    """
    def __init__(self,
                 name: str,
                 codename: str,
                 network: str,
                 location: coord.EarthLocation,
                 freqs_sefds: dict,
                 min_elevation=20 * u.deg,
                 fullname: str = None,
                 all_networks: str = None,
                 country: str = '',
                 diameter: str = '',
                 real_time: bool = False):
        """Initializes a station.

        Inputs
        - name : str
            Name of the observer (the station that is going to observe).
            If it contains undercores (_), they will be converted to blank spaces.
        - codename : str
            A short code (accronym) for the name of the station. It is meant to follow the standard approach
            from the EVN: an (often) two-letter code unique for each station.
        - network : str
            Name of the network to which the station belongs (e.g. EVN).
        - location : astropy.coordinates.EarthLocation
            Position of the station on Earth in (x,y,z) gecentric coordinates.
        - freqs_sefds : dict
            Dictionary with all frequencies the station can observe as keys of the dictionary, and the
            values representing the system equivalent flux density (SEFD; in Jansky units)
            at each frequency.
            Although the key format is in principle free, we recommend to use the syntax 'XXcm' (str type).
            This will be then consistent with the default station catalog.
        - min_elevation : Quantity [OPTIONAL]
            Minimum elevation that the station can reach to observe a source. If no units (astropy.units)
            provided, degrees are assumed. By default it 20 degrees. It does not support an azimuth-dependent
            elevation limits. It must be >= 0.
        - fullname : str [OPTIONAL]
            Full name of the station. If not given, same as `name` is assumed.
            It can be used to expand the full name if an abbreviation is typically used for the name.
            For example, name: VLA, fullname: Karl G. Jansky Very Large Array.
        - all_networks : str [OPTIONAL]
            Networks where the station can participate (free style string).
        - country : str [OPTIONAL]
            Country where the station is located.
        - diameter : str [OPTIONAL]
            Diameter of the station (free format string). We recommend a syntax of e.g. '30 m' for normal
            single-dish antennas, and in case of interferometers it can have a form like '25 x 20 m',
            meaning that the station is composed of 25 antennas of 20 m each.
        - real_time : bool [OPTIONAL]
            If the station can participate in real-time observations (e.g. e-EVN), False by default.
        """
        # Some sanity checks
        for a_var, a_var_name in zip((name, codename, network, country, diameter), \
                                     ('name', 'codename', 'network', 'country', 'diameter')):
            assert isinstance(a_var, str), f"'{a_var_name}' must be a str."

        assert min_elevation >= 0.0, "'min_elevation' must be >= 0."
        assert isinstance(fullname, str) or fullname is None
        assert isinstance(all_networks, str) or fullname is None
        assert type(real_time) is bool, "'real_time' must be a bool."
        self.observer = Observer(name=name.replace('_', ' '),
                                 location=location)
        self._codename = codename
        self._network = network
        self._freqs_sefds = freqs_sefds
        assert isinstance(min_elevation, float) or isinstance(min_elevation, int) \
               or isinstance(min_elevation, u.Quantity), \
               "'min_elevation' must be either a float, int, or an astropy.units.Quantity object."
        if isinstance(min_elevation, float) or isinstance(min_elevation, int):
            self._min_elev = min_elevation * u.deg
        else:  # isinstance(min_elevation, u.Quantity):
            assert min_elevation.unit.is_equivalent(u.deg), \
                   "'min_elevation' must have angular units (e.g. degrees)"
            self._min_elev = min_elevation

        self._fullname = name if fullname is None else fullname
        self._all_networks = network if all_networks is None else all_networks
        self._country = country
        self._diameter = diameter
        self._real_time = real_time

    @property
    def name(self) -> str:
        """Name of the station.
        """
        return self.observer.name

    @property
    def codename(self) -> str:
        """Codename of the station (typically a two-letter accronym).
        """
        return self._codename

    @property
    def fullname(self) -> str:
        """Full name of the station. If not specified, it can be the same as 'name'.
        """
        return self._fullname

    @property
    def network(self) -> str:
        """Name of the network to which the station belongs.
        """
        return self._network

    @property
    def all_networks(self) -> str:
        """Name of all networks to which the station belongs.
        If not specified it can be the same as 'network'.
        """
        return self._all_networks

    @property
    def country(self) -> str:
        """Country where this station is located.
        It can be an empty string if not specified.
        """
        return self._country

    @property
    def diameter(self) -> str:
        """String representing the diameter of the station, and/or how many antennas compose
        the station in case of connected-interferometers.
        """
        return self._diameter

    @property
    def real_time(self) -> bool:
        """If the station can participate in real-time observations (e.g. e-EVN).
        """
        return self._real_time

    @property
    def location(self) -> coord.EarthLocation:
        """Location of the station as an astropy.coordinates.EarthLocation object.
        """
        return self.observer.location

    @property
    def bands(self):
        """Observing bands the station can observe.
        Returns a dict_keys object with all bands in a string format as introduced in the freqs_sefd
        attribute when the Station was created.
        """
        return self._freqs_sefds.keys()

    @property
    def sefds(self) -> dict:
        """Returns a dictionary with the system equivalent flux density (SEFDs) for each
        of the frequencies the station can observe (given as keys).
        """
        return self._freqs_sefds

    @property
    def min_elevation(self) -> u.Quantity:
        """Minimum elevation the station can observe a source.
        Returns an astropy.units.Quantity (i.e. number with units).
        """
        return self._min_elev

    def elevation(self, obs_times: Time,
                  target: FixedTarget) -> coord.angles.Latitude:
        """Returns the elevation of the target source as seen by the Station during obs_times.

        Inputs
        - obs_times : astropy.time.Time
            Time to compute the elevation of the source
            (either a single timestamp or an array of times).
        - target : astroplan.FixedTarget
             Target to observe.

        Output
        - elevations : astropy.coordinates.angles.Latitute
            Elevation of the source at the given obs_times.
        """
        return self.observer.altaz(obs_times, target).alt

    def altaz(self, obs_times: Time,
              target: FixedTarget) -> coord.sky_coordinate.SkyCoord:
        """Returns the altaz coordinates of the target source for the given observing times.

        Inputs
        - obs_times : astropy.time.Time
            Time to compute the elevation of the source
            (either a single timestamp or an array of times).
        - target : astroplan.FixedTarget
             Target coordinates to observe.

        Output
        - altaz : astropy.coordinates.sky_coordinate.SkyCoord
            Altitude and azimuth of the source for each given time.
        """
        return self.observer.altaz(obs_times, target)

    def is_visible(self, obs_times: Time, target: FixedTarget) -> tuple:
        """Returns when the target source is visible for this station at the given times.

        Inputs
        - obs_times : astropy.time.Time
            Time to compute the elevation of the source
            (either a single timestamp or an array of times).
        - target : astroplan.FixedTarget
             Target coordinates to observe. If None, the target would be assumed to be visible at all times.

        Output
        - visible : tuple
            Tuple containing the indexes of obs_times when the target source is visible
            from the station. Therefore obs_times[visible] would return only those times.
        """
        if target is None:
            return (np.arange(2), )

        elevations = self.elevation(obs_times, target)
        return np.where(elevations >= self.min_elevation)

    def has_band(self, band: str) -> bool:
        """Returns if the Station can observed the given band `the_band`.

        Inputs
        - band : str
            A string representing an observing band, following the same syntax as used
            when the station was initialized and the bands where defined in the keys of
            the freqs_sefds attribute.

        Output
        - bool whenever the station has the given observing band.
        """
        return band in self.bands

    def sefd(self, band: str) -> float:
        """Returns the system equivalent flux density (SEFD) of the Station at the given band,
        in Jansky (Jy) units.

        Input
        - band : str
            A string representing an observing band, following the same syntax as used
            when the station was initialized and the bands where defined in the keys of
            the freqs_sefds attribute.

        Output
        - SEFD : float
            The SEFD at the given band, in Jy units.

        Exception
        - It may raise KeyError if the given band is not available for this station.

        """
        return self._freqs_sefds[band]

    def __str__(self):
        return f"<{self.codename}>"

    def __repr__(self):
        return f"<Station: {self.codename}>"
class ATCA_obs:
    '''
    ATCA_obs(targets, tzinfo='Australia/Sydney', portal_htmls=[])
    
    Help with schedule the observation
    
    params:
    --------
    targets (FixTarget or list): a single FixTarget or a list of FixTarget Objects
    tzinfo (str): The timezone of the observer (check `pytz.all_timezones` for all acceptable timezones)
    portal_htmls (list): If provided, load the ATCA schedule from the webpages. an empty list by default
    
    example:
    --------
    import astropy.units as u
    from astroplan import FixedTarget
    from astropy.coordinates import SkyCoord
    from datetime import datetime, timedelta
    
    portal_htmls = ['./test/Week1.html', './test/Week2.html']
    target = [FixedTarget(name='src1', coord=SkyCoord(233.3333,-66.6666,unit=u.deg)),
              FixedTarget(name='src2', coord=SkyCoord(66.6666,-23.3333,unit=u.deg))]
    t = datetime.fromisoformat('2020-10-28')
    obs = ATCA_obs(target, tzinfo='Australia/Sydney', portal_htmls=portal_htmls)
    
    fig, ax = obs.plot_target_altitude_with_schedule(t, duration=timedelta(days=10), dateformat='%D-%H:%M')
    fig, ax = obs.plot_single_observability_heatmap(t, days=7, target_index=0)

    
    attributes:
    --------
    targets: a list of FixedTarget objects need to be observed
    calibrator: a list of FixedTarget objects
    observer: an Observer object for ATCA
    utcoffset: a timedelta object shows the offset between the timezone of the observer and UTC
    tzinfo: timezone for the observer
    portal_sched: the formatted schedule from portal_htmls - created from ATCA_sched.schedules
    portal_utcoffset: a timedelta object shows the offset between the timezone of the ATCA schedule and UTC
    portal_tz: ATCA portal timezone
    
    functions:
    --------
    plot_target_altitude: plot targets altitude vs time
    plot_target_altitude_with_schedule: plot targets altitude vs time, with green time shaded in green
    plot_single_observability_heatmap: plot observability for a single source in a heatmap
    
    '''
    def __init__(self, targets, tzinfo='Australia/Sydney', portal_htmls=[]):
        ### target and calibrators
        if not isinstance(targets, Sequence):
            targets = [targets]
            
        self.targets = targets
        self.calibrator = [FixedTarget(name='1934-638', coord=SkyCoord('19h39m25.026s -63d42m45.63s')),
                           FixedTarget(name='0823-500', coord=SkyCoord('08h25m26.869s -50d10m38.49s'))]
        ### observer
        ATCA_loc = (149.5501388*u.deg,-30.3128846*u.deg,237*u.m)
        location = EarthLocation.from_geodetic(*ATCA_loc)

        self.observer = Observer(name='ATCA',
                                 location=location,
                                 timezone=timezone('Australia/Sydney'))
        time_now = datetime.now(timezone(tzinfo))
        self.utcoffset = time_now.utcoffset()
        self.tzinfo = tzinfo
        
        if len(portal_htmls) == 0:
            self.portal_tz = None
            self.portal_sched = None
        else:
            atca_scheds = ATCA_sched(portal_htmls)
            self.portal_tz = atca_scheds.timezone
            self.portal_sched = atca_scheds.schedules
            
            ### portal utcoffset
            portal_now = datetime.now(timezone(self.portal_tz))
            self.portal_utcoffset = portal_now.utcoffset()
        
    def plot_target_altitude(self, start_time, duration=timedelta(days=1), horizon=12, dateformat='%H:%M', **style_kwargs):
        '''
        plot_target_altitude(start_time, duration=timedelta(days=1), horizon=12, dateformat='%H:%M', **style_kwargs)
        
        plot targets altitude vs time
        
        params:
        --------
        start_time (datetime.datetime): the time to start the plot
        duration (datetime.timedelta): the length of the plot, 1 day by default
        horizon (int or float): telescope horizon in degree, 12 by default
        dateformat (str): time label formatting, "%H:%M" by default
        style_kwargs: arguments passed to matplotlib.pyplot.plot_date()
        
        returns:
        --------
        fig, ax
        '''
        ### plot style
        if style_kwargs is None:
            style_kwargs = {}
        style_kwargs = dict(style_kwargs)
        style_kwargs.setdefault('linestyle', '-')
        style_kwargs.setdefault('linewidth', 2)
        style_kwargs.setdefault('fmt', '-')
        ### convert time to series of time
        time_num = (duration.days + 1)*1000 + 1
        time_series = start_time + np.linspace(0,1,time_num)*duration
        ### covert times to UTC to calculate the alt/az
        time_utcs = time_series - self.utcoffset
        
        fig = plt.figure(figsize=(8*duration.total_seconds()/(24*3600), 6))
        ax = fig.add_subplot(111)
        
        for target in self.targets:
            alts = self.observer.altaz(time_utcs, target).alt.value
            if target.name:
                ax.plot_date(time_series, alts, label=target.name, **style_kwargs)
            else:
                ax.plot_date(time_series, alts, **style_kwargs)
                
        for calibrator in self.calibrator:
            alts = self.observer.altaz(time_utcs, calibrator).alt.value
            if calibrator.name == '1934-638':
                ax.plot_date(time_series, alts, label=calibrator.name, fmt='black', lw=3, ls=':')
            else:
                ax.plot_date(time_series, alts, label=calibrator.name, fmt='black', lw=1, ls=':')
                
        ax.axhline(y=horizon, color='red', ls=':', lw=2)
                
        date_formatter = dates.DateFormatter(dateformat)
        ax.xaxis.set_major_formatter(date_formatter)
        plt.setp(ax.get_xticklabels(), rotation=30, ha='right')
        
        ax.set_xlim(dates.date2num(time_series[0]), dates.date2num(time_series[-1]))
        
        ax.set_ylim(0,90)
        ax.legend()
        
        ax.set_xlabel(f'TIME FROM {start_time.year}-{start_time.month}-{start_time.day} [{self.tzinfo}]')
                
        return fig, ax
    
    def plot_target_altitude_with_schedule(self, start_time, duration=timedelta(days=1), horizon=12, dateformat='%H:%M', **style_kwargs):
        '''
        plot_target_altitude_with_schedule(start_time, duration=timedelta(days=1), horizon=12, dateformat='%H:%M', **style_kwargs)
        
        plot targets altitude vs time, with green time shaded in green
        
        params:
        --------
        start_time (datetime.datetime): the time to start the plot
        duration (datetime.timedelta): the length of the plot, 1 day by default
        horizon (int or float): telescope horizon in degree, 12 by default
        dateformat (str): time label formatting, "%H:%M" by default
        style_kwargs: arguments passed to matplotlib.pyplot.plot_date()
        
        returns:
        --------
        fig, ax
        '''
        if not self.portal_sched:
            return self.plot_target_altitude(start_time, duration, horizon, dateformat, **style_kwargs)
        
        fig, ax = self.plot_target_altitude(start_time, duration, horizon, dateformat, **style_kwargs)
        
        ### convert time to series of time
        time_num = (duration.days + 1)*1000 + 1
        time_series = start_time + np.linspace(0,1,time_num)*duration
        
        ### read schedules
        for obs_day in self.portal_sched:
            for project_row in self.portal_sched[obs_day]:
                if project_row[-1]:
                    block_start = datetime.fromisoformat(obs_day) + timedelta(hours=float(project_row[0][0].split(':')[0]),
                                                                              minutes=float(project_row[0][0].split(':')[1]))
                    block_start = block_start + self.utcoffset - self.portal_utcoffset
                    
                    block_end = datetime.fromisoformat(obs_day) + timedelta(hours=float(project_row[0][1].split(':')[0]),
                                                                            minutes=float(project_row[0][1].split(':')[1]))
                    block_end = block_end + self.utcoffset - self.portal_utcoffset
                    
                    ax.axvspan(xmin=dates.date2num(block_start), xmax=dates.date2num(block_end),
                               color='green', alpha=0.1)
                    
        ax.set_xlim(dates.date2num(time_series[0]), dates.date2num(time_series[-1]))
                    
        return fig, ax
    
    def _greentime_bool(self, time):
        '''
        _greentime_bool(time)
        
        check if time is in during the green time slot
        
        params:
        --------
        time (datetime.datetime): the time to be checked
        
        returns:
        --------
        None if there is no schedule file for that day; True if it is in the green time slot; False if not
        '''
        if not self.portal_sched:
            return None
        
        ### transfer time to portal timezone
        time = time - self.utcoffset + self.portal_utcoffset
        
        time_date = f'{time.year}-{time.month:0>2}-{time.day:0>2}'
        if time_date not in self.portal_sched:
            return None
        
        for project in self.portal_sched[time_date]:
            project_start = datetime.fromisoformat(time_date) + timedelta(hours=float(project[0][0].split(':')[0]),
                                                                          minutes=float(project[0][0].split(':')[1]))
            project_end = datetime.fromisoformat(time_date) + timedelta(hours=float(project[0][1].split(':')[0]),
                                                                        minutes=float(project[0][1].split(':')[1]))
            if time >= project_start and time < project_end:
                if project[-1]:
                    return True
                return False
            
        return None
    
    def plot_single_observability_heatmap(self, start_time, days=7, target_index=0, horizon=12):
        '''
        plot_single_observability_heatmap(start_time, days=7, target_index=0, horizon=12)
        
        plot observability for a single source in a heatmap - we consider two factors: one is green time constrain, the other is altitude constrain
        
        params:
        --------
        start_time (datetime.datetime): time to start the plot. MAKE SURE start at 00:00 or there will be a bug
        days (int): number of days to plot, 7 by default
        target_index (int): index of the target of interest - specify which target to plot 
        horizon (int or float): telescope horizon in degree, 12 by default
        
        returns:
        --------
        fig, ax
        
        '''
        fig = plt.figure(figsize=(16,2*int(days)))
        
        for day in range(days):
            observability = np.zeros((2,48))
            
            ax = fig.add_subplot(int(days),1,day+1)
            day_time_start = start_time + timedelta(days=day)
            for i in range(48):
                block_time = day_time_start + timedelta(minutes=30) * i
                block_time_utc = block_time - self.utcoffset
                
                target_alt = self.observer.altaz(block_time_utc, self.targets[target_index]).alt.value
                if target_alt < horizon:
                    observability[0][i] = 0
                else:
                    observability[0][i] = 1
                    
                is_green_time = self._greentime_bool(block_time)
                if is_green_time == None:
                    observability[1][i] = np.nan
                else:
                    observability[1][i] = float(is_green_time)
                    
            extent = [-0.5, 47.5, -0.5, 1.5]
            ax.imshow(observability, extent=extent, origin='lower')
            ax.set_yticks(range(0, 2))
            ax.set_xticks(range(0, 48,2))
            ax.set_yticklabels(['Altitude Constrain','Greentime Constrain'])
            ax.set_xticklabels([f"{i:0>2}:00" for i in range(24)])
            
            ax.set_xticks(np.arange(extent[0], extent[1]), minor=True)
            ax.set_yticks(np.arange(extent[2], extent[3]), minor=True)
            ax.grid(which='minor', color='w', linestyle='-', linewidth=2)
            
            ax.set_xlabel(f'Observability in {day_time_start.year}-{day_time_start.month}-{day_time_start.day} [{self.tzinfo}]')
            
#         fig.suptitle(self.targets[target_index].name)
#         plt.tight_layout()
            
        return fig, ax
Пример #5
0
from astropy.time import Time
from astroplan import Observer
#from astroplan import FixedTarget
#Mars = FixedTarget.from_name("mars")

#observer-specific coordinates
mitlat=42.3601*u.degree
mitlong=-71.0942*u.degree
radome_elevation=100*u.m #roughly 100m above sea level
time = Time.now()
#print time
#time =Time('2018-08-22 15:31:06')

#define an observer and an altaz frame
radome_observer=Observer(latitude=mitlat,longitude=mitlong, elevation=radome_elevation, name='radome', timezone='US/Eastern')
altaz_frame=radome_observer.altaz(time)
icrs_frame=ICRS()
galactic_frame=Galactic()

#print radome_observer.sun_altaz(time)



def update_altaz():
    time=Time.now()
    altaz_frame=radome_observer.altaz(time)
    return altaz_frame

def get_time():
    time=Time.now()
    return time
Пример #6
0
def get_altaz(obj_name, ipt_lon, ipt_lat, t=None):

    # for html scrapping
    # from lxml import html
    # from bs4 import BeautifulSoup
    # to place requests
    import requests
    import json

    import astropy.units as u
    from astropy.time import Time
    from astropy.coordinates import SkyCoord, EarthLocation, Angle, Latitude, Longitude

    from astroplan import FixedTarget, Observer
    from astroquery.simbad import Simbad as simbad

    import ephem

    if t == None:
        t = Time.now()

    ## Set up the observer
    obs_el = 100 * u.m
    loc = EarthLocation.from_geodetic(ipt_lon, ipt_lat, obs_el)
    my_site = Observer(name="My_Site", location=loc)

    obs_lat = my_site.location.latitude
    obs_lon = my_site.location.longitude

    # observer for pyephem
    ephem_site = ephem.Observer()
    ephem_site.lon, ephem_site.lat = str(obs_lon.deg), str(obs_lat.deg)
    ephem_site.date = ephem.Date(str(t.decimalyear))

    ##Get the object
    # Check for planet-hood.
    # if planet: resolve the individual planet with pyephem.
    # else if satellite or ISS (or TIANGONG) scrap the appropriate websites and return info
    # else query simbad

    ############
    # Put in an auto-correct for kids
    ############
    # just make it lower case for now

    obj_name = obj_name.lower()

    if obj_name in ["sun", "mercury", "venus", "moon", "mars", "jupiter", "saturn", "uranus", "neptune", "pluto"]:

        if obj_name == "sun":
            my_planet = ephem.Sun()
        elif obj_name == "mercury":
            my_planet = ephem.Mercury()
        elif obj_name == "venus":
            my_planet = ephem.Venus()
        elif obj_name == "moon":
            my_planet = ephem.Moon()
        elif obj_name == "mars":
            my_planet = ephem.Mars()
        elif obj_name == "jupiter":
            my_planet = ephem.Jupiter()
        elif obj_name == "saturn":
            my_planet = ephem.Saturn()
        elif obj_name == "uranus":
            my_planet = ephem.Uranus()
        elif obj_name == "neptune":
            my_planet = ephem.Neptune()
        elif obj_name == "pluto":
            my_planet = ephem.Pluto()

        my_planet.compute(ephem_site)
        az = my_planet.az * 180 / 3.1415926535
        alt = my_planet.alt * 180 / 3.1415926535
        # here coded for just ISS but for all satellites we should have similar setups, probably poll site
    elif obj_name == "iss":
        # try a request for the iss from the open notify site. Gives current json data
        page = requests.get("http://api.open-notify.org/iss-now.json")
        issdata = page.json()
        tstamp = issdata["timestamp"]
        isslat = issdata["iss_position"]["latitude"]
        isslon = issdata["iss_position"]["longitude"]
        # there are issues with just this amount of data as you do not know the altitude of the object
        # here we fix it to 350 km
        issheight = 350 * u.km
        isslat = Latitude(isslat, unit=u.deg)
        isslon = Longitude(isslon, unit=u.deg)

        # there are issues however as this data does NOT contain the altitude so lets try scrapping the html
        # the issue with fullissdata is that it contains information in NASA style units (M50 Cartesian & M50 Keplerian)
        page = requests.get(
            "http://spaceflight.nasa.gov/realdata/sightings/SSapplications/Post/JavaSSOP/orbit/ISS/SVPOST.html"
        )
        # fullissdata=html.fromstring(page.text)

        # there are also other satellites liseted in, issue is parsing the information as I do not know what each field contains
        # the issue here is that all sat data contains unknown units and uncertain which entries contain useful information
        page = requests.get("http://www.celestrak.com/NORAD/elements/stations.txt")
        allsatdata = page.text

        c = SkyCoord(isslon, isslat, issheight)
        my_target = FixedTarget(name="ISS", coord=c)
        az = my_site.altaz(t, my_target).az.deg
        alt = my_site.altaz(t, my_target).alt.deg
    else:
        try:
            q = simbad.query_object(obj_name)
            c = SkyCoord(q["RA"][0], q["DEC"][0], unit=(u.hourangle, u.deg))
            my_star = FixedTarget(name="my_star", coord=c)

            az = my_site.altaz(t, my_star).az.deg
            alt = my_site.altaz(t, my_star).alt.deg
        except:
            print("Couldn't find Object in Database")
            alt, az = 0, 0

    return alt, az
Пример #7
0
# Define a target
tgt = FixedTarget(name='S5', ra='14:20:00.00', dec='48:00:00.00')

# Combine a list of constraints to run on Observer, FixedTarget, and time to 
# determine the observability of target
constraints = is_observable(constraint_list, obs, tgt, time_obs)

# Test only a single constraint:
constraints = is_observable(AboveAirmass(1.2), obs, tgt, time_obs)

# `constraints` will be a boolean where True=observable. For a list of 
# targets, observatories, or times, `constraints` may be a booleans array

# We will eventually need a more complicated method that minimizes a cost 
# function when optimizing an observing schedule given the results of 
# `is_observable`.

# ======================================================
# Other useful calculations wrt an observer and a target
#=======================================================

# calculate the distance in alt and az degrees between two targets at
# the given time (e.g. to calculate slew time)
sf = FixedTarget(name='Sf', ra='09:40:00.00', dec='43:00:00.00')
sm = FixedTarget(name='Sm', ra='10:30:00.00', dec='36:00:00.00')

# Coordinate arithmetic gives separations in RA, Dec, alt, az
dra, ddec = sf.ra - sm.ra, sf.dec - sm.dec
dalt = obs.altaz(sf, time_obs).alt - obs.altaz(sm, time_obs).alt
dazt = obs.altaz(sf, time_obs).az - obs.altaz(sm, time_obs).az
Пример #8
0
def createPicture(name, times):
    rcParams['font.size'] = 13
    rcParams['lines.linewidth'] = 3
    rcParams['lines.markersize'] = 0
    rcParams['grid.linestyle'] = '--'
    rcParams['axes.titlepad'] = 13
    rcParams['xtick.direction'] = 'in'
    rcParams['ytick.direction'] = 'in'
    rcParams['xtick.top'] = True
    rcParams['ytick.right'] = True
    rcParams['font.family'] = 'serif'
    rcParams['mathtext.fontset'] = 'dejavuserif'
    rc('legend', fontsize=13)
    rc('xtick.major', size=5, width=1.5)
    rc('ytick.major', size=5, width=1.5)
    rc('xtick.minor', size=3, width=1)
    rc('ytick.minor', size=3, width=1)

    star_name = name
    star_style = {'linestyle': '--', 'linewidth': 4, 'color': 'tomato'}
    star = FixedTarget.from_name(star_name)

    longitude_kgo = 42.6675 * u.deg
    latitude_kgo = 43.73611 * u.deg
    elevation_kgo = 2112 * u.m

    kgo = Observer(longitude=longitude_kgo,
                   latitude=latitude_kgo,
                   elevation=elevation_kgo,
                   name="KGO",
                   timezone="Europe/Moscow")

    # start_time = Time('2020-01-01 '+ times)
    # end_time = Time('2020-02-01 '+ times)
    # delta_t = end_time - start_time
    # observe_time = start_time + delta_t*np.linspace(0, 1, 32)
    observe_time = Time(times)

    # sunset_tonight = kgo.sun_set_time(observe_time, which="nearest")
    # sunrise_tonight = kgo.sun_rise_time(observe_time, which="nearest")

    # star_rise = list(map(lambda observe_time : kgo.target_rise_time(observe_time, star) + 5*u.minute, observe_time))
    # star_set = list(map(lambda observe_time: kgo.target_set_time(observe_time, star) + 5*u.minute, observe_time))

    # sunset_tonight = list(map(lambda observe_time:  kgo.sun_set_time(observe_time, which="nearest"), observe_time))
    # sunrise_tonight = list(map(lambda observe_time:  kgo.sun_rise_time(observe_time, which="nearest"), observe_time))

    visible_time = observe_time + np.linspace(-10, +10, 25) * u.hour
    #visible_time = start + (end - start)*np.linspace(0, 1, 25)
    stars_alts = kgo.altaz(visible_time, star).alt
    sun_alts = kgo.sun_altaz(visible_time).alt

    moon_coord = kgo.moon_altaz(visible_time)
    star_coord = kgo.altaz(visible_time, star)
    angle = moon_coord.separation(star_coord)
    moon_star = angle.deg

    #print(stars_alts)
    #t = Time(visible_time, format='iso', scale='utc')
    # start = Time(list(map(lambda x,y: np.max([x, y]), sunset_tonight, star_rise)))
    # end = Time(list(map(lambda x,y: np.min([x,y]), sunrise_tonight, star_set)))

    #visible_time = (end-start)

    #time_final = abs(visible_time.value*24)

    locator = mdates.MonthLocator()
    fmt = mdates.DateFormatter('%b')

    canvas = FigureCanvasAgg(plt.figure(1))
    plt.figure(figsize=(8, 7))
    plt.subplot(211)
    plt.plot_date(visible_time.plot_date,
                  stars_alts,
                  linestyle='-.',
                  color='mediumslateblue',
                  label=star_name)
    plt.plot_date(visible_time.plot_date,
                  sun_alts,
                  linestyle='-.',
                  color='gold',
                  label='Sun')
    plt.ylim(0, np.max([stars_alts, sun_alts]) + 5)
    plt.ylabel('Altitude, degrees')
    plt.legend(shadow=True, loc="best")
    plt.gcf().autofmt_xdate()
    plt.grid()

    plt.subplot(212)
    plt.plot_date(visible_time.plot_date,
                  moon_star,
                  linestyle='-',
                  color='slategrey',
                  label='star_name' + '\n' + times)
    plt.ylabel('Moon-Star angle, degrees')
    plt.gcf().autofmt_xdate()
    plt.grid()
    data = BytesIO()

    plt.savefig(data, format='png')
    return data.getvalue()
Пример #9
0
# Combine a list of constraints to run on Observer, FixedTarget, and time to
# determine the observability of target
constraints = is_observable(constraint_list, obs, t1, time_obs)

# Test only a single constraint:
constraints = is_observable(AirmassRange(1.2), obs, t1, time_obs)

# AirmassRange can accept two bounding airmasses, assumes single argument is
# an upper limit, lower limit = 1.

# `constraints` will be a boolean where True=observable. For a list of
# targets, observatories, or times, `constraints` may be a booleans array

# We will eventually need a more complicated method that minimizes a cost
# function when optimizing an observing schedule given the results of
# `is_observable`.

# ======================================================
# Other useful calculations wrt an observer and a target
#=======================================================

# calculate the distance in alt and az degrees between two targets at
# the given time (e.g. to calculate slew time)
sf = FixedTarget(SkyCoord('09d40m00.00s', '43d00m00.00s'), name='Sf')
sm = FixedTarget(SkyCoord('10d30m00.00s', '36d00m00.00s'), name='Sm')

# Coordinate arithmetic gives separations in RA, Dec, alt, az
dra, ddec = sf.ra - sm.ra, sf.dec - sm.dec
dalt = obs.altaz(time_obs, sf).alt - obs.altaz(time_obs, sm).alt
dazt = obs.altaz(time_obs, sf).az - obs.altaz(time_obs, sm).az
Пример #10
0
g = GoogleV3()

t_start = datetime(2017, 12, 10, 21, 38) #in UTC
t_end = datetime(2017, 12, 10, 22, 8)
cities = pd.read_csv('simplemaps-worldcities-basic.csv')
cities = cities[cities['pop'] > 1000000].reset_index()
cities['name'] = cities['city_ascii'] + ', ' + cities['iso3']
alts = []
azs = []
messages = []

print('Calculating')
for row in tqdm(cities.itertuples(), total=len(cities)):
    lat, lon = row.lat, row.lng
    obs = Observer(location=EarthLocation.from_geodetic(lon*u.deg, lat*u.deg))
    altaz = obs.altaz(t_start, Kepler)
    alt = altaz.alt.deg
    az = altaz.az.deg
    direc = az_to_coord(az)
    tz = g.timezone((lat, lon))
    t0 = tz.fromutc(t_start)
    t1 = tz.fromutc(t_end)
    alts.append(alt)
    azs.append(az)
    if alt < 0.:
        message = 'Kepler will be to the %s,'%(direc) + '<p>' +'%.0f degrees below the horizon'%(-alt)
    else:
        message = 'Kepler will be to the %s,'%(direc) + '<p>' + '%.0f degrees above the horizon'%(alt)
    message += '<br>The image will be taken between %02d:%02d and %02d:%02d local time on December %dth'%(t0.hour, t0.minute, t1.hour, t1.minute, t1.day)
    message += '<br>We hope you\'ll join us in waving to Kepler!'
    messages.append([message])
Пример #11
0
class Station(object):
    def __init__(self,
                 name,
                 codename,
                 network,
                 location,
                 freqs_sefds,
                 min_elevation=20 * u.deg,
                 fullname=None,
                 all_networks=None,
                 country='',
                 diameter=''):
        """Initializes a station. The given name must be the name of the station that
        observes, with the typical 2-letter format used in the EVN (with exceptions).

        Inputs
        - name : str
            Name of the observer (the station that is going to observe).
        - codename : str
            A code for the name of the station. It can be the same as name.
        - network : str
            Name of the network to which the station belongs.
        - location : EarthLocation
            Position of the observer on Earth.
        - freqs_sefds : dict
            Dictionary with all frequencies the station can observe, and as values
            the SEFD at each frequency.
        - min_elevation : Quantity
            Minimum elevation that the station can observe a source. If no units
            provided, degrees are assumed. By default it 20 degrees.
        - fullname : str [OPTIONAL]
            Full name of the station. If not given, `name` is assumed.
        - all_networks : str [OPTIONAL]
            Networks where the station can participate (free style).
        - country : str [OPTIONAL]
            Country where the station is placed.
        """
        self.observer = Observer(name=name.replace('_', ' '),
                                 location=location)
        self._codename = codename
        self._network = network
        self._freqs_sefds = freqs_sefds
        if (type(min_elevation) is float) or (type(min_elevation) is int):
            self._min_elev = min_elevation * u.deg
        else:
            self._min_elev = min_elevation

        if fullname is None:
            self._fullname = name
        else:
            self._fullname = fullname

        if all_networks is None:
            self._all_networks = network
        else:
            self._all_networks = all_networks

        self._country = country
        self._diameter = diameter

    @property
    def name(self):
        """Name of the station.
        """
        return self.observer.name

    @property
    def codename(self):
        """Codename of the station (typically a two-letter accronym).
        """
        return self._codename

    @property
    def fullname(self):
        return self._fullname

    @property
    def network(self):
        """Name of the network to which the station belongs.
        """
        return self._network

    @property
    def all_networks(self):
        """Name of all networks to which the station belongs.
        """
        return self._all_networks

    @property
    def country(self):
        return self._country

    @property
    def diameter(self):
        return self._diameter

    @property
    def location(self):
        """Location of the station in EarthLocation type.
        """
        return self.observer.location

    @property
    def bands(self):
        """Observing bands the station can observe.
        """
        return self._freqs_sefds.keys()

    @property
    def sefds(self):
        """Returns a dictionary with the SEFDs for each of the frequencies
        the station can observe (given as keys).
        """
        return self._freqs_sefds

    @property
    def min_elevation(self):
        """Minimum elevation the station can observe a source.
        """
        return self._min_elev

    def elevation(self, obs_times, target):
        """Returns the elevation of the source as seen by the Station during obs_times.

        Inputs
        - obs_times : astropy.time.Time
            Time to compute the elevation of the source (either single time or a list of times).
        - target : astroplan.FixedTarget
             Target to observe.

        Output
        - elevations : ndarray
            Elevation of the source at the given obs_times
        """
        # source_altaz = source_coord.transform_to(coord.AltAz(obstime=obs_times,
        #                                                 location=self.location))
        # return source_altaz.alt
        return self.observer.altaz(obs_times, target).alt

    def altaz(self, obs_times, target):
        """Returns the altaz coordinates of the target for the given observing times.
        """
        return self.observer.altaz(obs_times, target)

    def is_visible(self, obs_times, target):
        """Return if the source is visible for this station at the given times.
        """
        elevations = self.elevation(obs_times, target)
        return np.where(elevations >= self.min_elevation)

    def has_band(self, band):
        """Returns if the Station can observed the given band `the_band`.
        """
        return band in self.bands

    def sefd(self, band):
        """Returns the SEFD of the Station at the given band.
        """
        return self._freqs_sefds[band]

    def __str__(self):
        return f"<{self.codename}>"

    def __repr__(self):
        return f"<stations.Station: {self.codename}>"
Пример #12
0
for i in (l):
    moon_locs.append(SkyCoord(radec2[i][0], radec2[i][1], frame='icrs'))

#Get seperations in degrees
sep = []
for i in moon_locs:
    sep.append(target_coord.separation(i).deg)
#making them numpy arrays
sep = np.array(sep)
#sep

##################################################################################################

#Airmasses at observatory 1

airmass_obs1 = obs1.altaz(dt, target).secz
masked_airmass_obs1 = np.ma.array(airmass_obs1, mask=airmass_obs1 < 1)

#Airmasses at observatory 2

airmass_obs2 = obs2.altaz(dt, target).secz
masked_airmass_obs2 = np.ma.array(airmass_obs2, mask=airmass_obs2 < 1)

#Creating a dictionary for the dataframe
dk = {
    'datetimes': dt,
    'obs1_airmass': masked_airmass_obs1,
    'obs2_airmass': masked_airmass_obs2
}
#dk
Пример #13
0
class Simulation(object):
    """A class to encapsulate an SDSS-5 simulation
    """
    def __init__(self,
                 plan,
                 observatory,
                 idx=1,
                 schedule="normal",
                 redo_exp=True):
        if (observatory == 'apo'):
            timezone = "US/Mountain"
            fclear = 0.5
            elev = 2788
            self.telescope = {
                "alt": 30,
                "az": 90,
                "par_angle": 0,
                "alt_slew": 1.5,
                "az_slew": 2.0,
                "rot_slew": 2.0
            }
            self.obsCheck = apoCheck
            self.moveTelescope = self.moveSloanTelescope
        if (observatory == 'lco'):
            timezone = "US/Eastern"
            fclear = 0.7
            elev = 2134
            self.telescope = {"ra": 0, "dec": -30}
            self.obsCheck = lcoCheck
            self.moveTelescope = self.moveDuPontTelescope

        self.redo_exp = redo_exp

        self.obsHist = {
            "lst": list(),
            "ra": list(),
            "bright": list(),
            "field_pk": list(),
            "weather": list(),
            "mjd": list()
        }

        self.scheduler = roboscheduler.scheduler.Scheduler(
            observatory=observatory, schedule=schedule)
        self.weather = observesim.weather.Weather(
            mjd_start=self.scheduler.start,
            mjd_end=self.scheduler.end,
            seed=idx,
            fclear=fclear)
        self.observatory = Observer(longitude=self.scheduler.longitude * u.deg,
                                    latitude=self.scheduler.latitude * u.deg,
                                    elevation=elev * u.m,
                                    name=observatory,
                                    timezone=timezone)
        self.scheduler.initdb(designbase=plan)
        self.field_ra = self.scheduler.fields.racen
        self.field_dec = self.scheduler.fields.deccen
        self.field_pk = self.scheduler.fields.pk

        cadencelist = self.scheduler.fields.cadencelist.cadences
        cadences = self.scheduler.fields.cadence

        self.nom_duration = np.float32(15. / 60. / 24.)
        self.cals = np.float32(3. / 60. / 24.)
        self.observe = observesim.observe.Observe(defaultExp=self.nom_duration,
                                                  cadencelist=cadencelist,
                                                  cadences=cadences)
        self.bossReadout = np.float32(70. / 60. / 60. / 24.)

        self.curr_mjd = np.float32(1e9)

        self.coord = SkyCoord(self.field_ra * u.deg, self.field_dec * u.deg)

        self.slews = list()
        self.slew_mjds = list()
        self.slew_alt = list()
        self.slew_az = list()
        self.slew_rot = list()
        self.slew_ra = list()
        self.slew_dec = list()

        self.hit_lims = 0

        self.redo_apg = 0
        self.redo_r = 0
        self.redo_b = 0

    def moveDuPontTelescope(self, mjd, fieldidx):
        next_ra, next_dec = self.field_ra[fieldidx], self.field_dec[fieldidx]

        ra_slew = np.abs(next_ra - self.telescope["ra"])
        dec_slew = np.abs(next_dec - self.telescope["dec"])

        if ra_slew > 180:
            ra_slew = 360 - ra_slew
            assert ra_slew > 0, "forgot circular math? ra"

        dec_time = decTime(dec_slew)
        ra_time = raTime(ra_slew)

        self.telescope["ra"] = self.field_ra[fieldidx]
        self.telescope["dec"] = self.field_dec[fieldidx]

        return max([dec_time, ra_time]), ra_slew, dec_slew

    def moveSloanTelescope(self, mjd, fieldidx):
        altaz = self.observatory.altaz(Time(mjd, format="mjd"),
                                       self.coord[fieldidx])
        alt = altaz.alt.deg
        az = altaz.az.deg
        angle = self.observatory.parallactic_angle(Time(mjd, format="mjd"),
                                                   self.coord[fieldidx]).deg

        alt_slew = np.abs(alt - self.telescope["alt"])
        az_slew = np.abs(az - self.telescope["az"])
        if az_slew > 180:
            az_slew = 360 - az_slew
            assert az_slew > 0, "forgot circular math?  az"
        rot_slew = np.abs(angle - self.telescope["par_angle"])
        if rot_slew > 180:
            rot_slew = 360 - rot_slew
            assert rot_slew > 0, "forgot circular math? rot"

        alt_time = alt_slew / self.telescope["alt_slew"]
        az_time = az_slew / self.telescope["az_slew"]
        rot_time = rot_slew / self.telescope["rot_slew"]

        self.telescope["alt"] = alt
        self.telescope["az"] = az
        self.telescope["par_angle"] = angle

        return max([alt_time, az_time, rot_time]), alt_slew, az_slew, rot_slew

    def siteObs(self, fieldidx, mjd):
        """Check observability issues at site, e.g. zenith at APO
           or enclosure, etc
           for any number of mjds, e.g. for a whole observing window
        """

        try:
            len(mjd)
        except TypeError:
            mjd = np.array([mjd])

        try:
            len(fieldidx)
        except TypeError:
            fieldidx = np.array([fieldidx])

        altaz = self.observatory.altaz(Time(mjd, format="mjd"),
                                       self.coord[fieldidx],
                                       grid_times_targets=True)
        # altaz shape = (fields x mjds)
        alt = altaz.alt.deg.flatten()
        az = altaz.az.deg.flatten()
        res = self.obsCheck(alt, az)
        good = res.reshape((len(fieldidx), len(mjd)))

        # axis 1 is along fields, I guess...
        return np.all(good, axis=1)

    def bright(self, mjd=None):
        if mjd is None:
            mjd = self.curr_mjd
        skybrightness = self.scheduler.skybrightness(mjd)
        return skybrightness > 0.35

    def nextField(self):
        # dark time or brighttime? to guess at how long we need for obs
        if not self.bright():
            airmass_weight = 1.05
        else:
            airmass_weight = 0.05
        # integer division floors; no partial exposures
        maxExp = int((self.nextchange - self.curr_mjd) //
                     (self.nom_duration * 1.3**airmass_weight))
        if maxExp == 0:
            # self.curr_mjd = self.curr_mjd + self.nom_duration
            return -1, 1, True
        field_pk, nexposures = self.scheduler.nextfield(mjd=self.curr_mjd,
                                                        maxExp=maxExp)
        # assert fieldid is not None, f"can't schedule {self.curr_mjd}, {self.bright()}"
        if (field_pk is not None):
            fieldidx = np.where(self.field_pk == field_pk)[0]
            site_check = self.siteObs(fieldidx, [
                self.curr_mjd + n * (self.nom_duration)
                for n in range(nexposures)
            ])
            # maxTime = self.nextchange - self.curr_mjd
            maxTime = maxExp * self.nom_duration

            if not site_check:
                field_idxs, nexps = self.scheduler.nextfield(mjd=self.curr_mjd,
                                                             maxExp=maxExp,
                                                             returnAll=True)

                obs_fields = self.siteObs(field_idxs, [
                    self.curr_mjd + n * (self.nom_duration)
                    for n in range(nexposures)
                ])
                field_idxs = field_idxs[obs_fields]
                nexps = nexps[obs_fields]
                if len(field_idxs) == 0:
                    # print("all fields collide with something :( ")
                    # print(obs_fields)
                    self.hit_lims += 1. / 20
                    return -1, 1. / 20, False

                fieldidx, nexposures = sortFields(field_idxs,
                                                  nexps,
                                                  self.nom_duration,
                                                  maxTime=maxTime)
                if fieldidx == -1:
                    # print("baawaaaaaahhhahahaa :( ")
                    # self.curr_mjd = self.curr_mjd + self.nom_duration/20
                    return -1, 1. / 20, False
            field_pk = int(self.field_pk[fieldidx])

            return field_pk, nexposures, False
        else:
            # if not self.bright():
            #     assert False, f"{self.curr_mjd} ugh"
            return -1, 1, False

    def bookKeeping(self, fieldidx, i=-1):
        """figure out SN and keep track, etc
        """
        alt, az = self.scheduler.radec2altaz(mjd=self.curr_mjd,
                                             ra=self.field_ra[fieldidx],
                                             dec=self.field_dec[fieldidx])
        airmass = 1 / np.cos(np.pi * (90 - alt) / 180.)
        if alt < 20:
            print(i, alt, az, self.curr_mjd, fieldidx, "TOO LOW!!")
            if alt < 0:
                print("booooooooo")
                # assert False, "ugh"

        result = self.observe.result(
            mjd=self.curr_mjd,
            field_pk=self.field_pk[fieldidx],
            airmass=airmass,
            epochidx=self.scheduler.fields.icadence[fieldidx])
        duration = result["duration"]
        if duration < 0 or np.isnan(duration):
            print("HOOOWWWOWOWOWOWW")
            print(i, alt, az, self.curr_mjd, field_pk)

        self.curr_mjd = self.curr_mjd + duration + self.bossReadout

        # move telescope for tracking
        self.moveTelescope(self.curr_mjd, fieldidx)

        self.obsHist["lst"].append(self.scheduler.lst(self.curr_mjd)[0])
        self.obsHist["ra"].append(self.field_ra[fieldidx])
        self.obsHist["bright"].append(self.bright())
        self.obsHist["field_pk"].append(self.field_pk[fieldidx])
        self.obsHist["weather"].append(False)
        self.obsHist["mjd"].append(self.curr_mjd)

        return result

    def observeField(self, field_pk, nexposures):
        fieldidx = int(np.where(self.field_pk == field_pk)[0])

        slewtime, *axes = self.moveTelescope(self.curr_mjd, fieldidx)

        self.slews.append(int(slewtime))
        self.slew_mjds.append(int(self.curr_mjd))

        if len(axes) == 3:
            self.slew_alt.append(float(axes[0]))
            self.slew_az.append(float(axes[1]))
            self.slew_rot.append(float(axes[2]))

            self.slew_ra.append(np.nan)
            self.slew_dec.append(np.nan)
        else:
            self.slew_ra.append(float(axes[0]))
            self.slew_dec.append(float(axes[1]))

            self.slew_alt.append(np.nan)
            self.slew_az.append(np.nan)
            self.slew_rot.append(np.nan)

        # slewtime is in seconds...
        self.curr_mjd = self.curr_mjd + self.cals + np.float32(
            slewtime / 60. / 60. / 24.)

        field_exp_count = nexposures
        for i in range(nexposures):
            # each "exposure" is a design

            if (self.curr_mjd > self.nextchange):
                oops = (self.curr_mjd - self.nextchange) * 24 * 60
                if oops > 5:
                    print("NOOOO! BAD!", oops)
                    # print(i, nexposures, self.telescope)
                continue

            res = self.bookKeeping(fieldidx, i=i)

            if self.bright():
                if res["apgSN2"] < 100 and self.redo_exp:
                    field_exp_count += 1
                    self.redo_apg += 1
                    self.scheduler.update(field_pk=self.field_pk[fieldidx],
                                          result=res,
                                          finish=False)
                    res = self.bookKeeping(fieldidx, i=i)
                    self.scheduler.update(field_pk=self.field_pk[fieldidx],
                                          result=res,
                                          finish=True)
                else:
                    self.scheduler.update(field_pk=self.field_pk[fieldidx],
                                          result=res,
                                          finish=True)
            else:
                if (res["rSN2"] < 0.2 or res["bSN2"] < 0.2) and self.redo_exp:
                    field_exp_count += 1
                    if res["rSN2"] < 0.2:
                        self.redo_r += 1
                    else:
                        self.redo_b += 1
                    self.scheduler.update(field_pk=self.field_pk[fieldidx],
                                          result=res,
                                          finish=False)
                    res = self.bookKeeping(fieldidx, i=i)
                    self.scheduler.update(field_pk=self.field_pk[fieldidx],
                                          result=res,
                                          finish=True)
                else:
                    self.scheduler.update(field_pk=self.field_pk[fieldidx],
                                          result=res,
                                          finish=True)
        if self.bright():
            ap_tot = np.sum(
                self.scheduler.observations.apgSN2[-1 * field_exp_count:])
            # print(f"{nexposures} {field_exp_count} {len(self.scheduler.observations.apgSN2[-1*field_exp_count:])}")
            # print(f"AP SN {ap_tot:7.1f} VS {300 * nexposures}")
            if ap_tot < 650 * nexposures and self.redo_exp:
                self.redo_apg += 1
                self.scheduler.update(field_pk=self.field_pk[fieldidx],
                                      result=res,
                                      finish=False)
                res = self.bookKeeping(fieldidx, i=i)
                self.scheduler.update(field_pk=self.field_pk[fieldidx],
                                      result=res,
                                      finish=True)
        else:
            r_tot = np.sum(self.scheduler.observations.rSN2[-1 *
                                                            field_exp_count:])
            b_tot = np.sum(self.scheduler.observations.bSN2[-1 *
                                                            field_exp_count:])
            # print(f"{nexposures} {field_exp_count} {len(self.scheduler.observations.bSN2[-1*field_exp_count:])}")
            # print(f"B  SN {b_tot:7.1f} VS {2.5 * nexposures} \nR  SN {r_tot:7.1f} VS {5 * nexposures}")
            if (b_tot < 1.4 * nexposures
                    or r_tot < 3.4 * nexposures) and self.redo_exp:
                if r_tot < 3.4 * nexposures:
                    self.redo_r += 1
                else:
                    self.redo_b += 1
                self.scheduler.update(field_pk=self.field_pk[fieldidx],
                                      result=res,
                                      finish=False)
                res = self.bookKeeping(fieldidx, i=i)
                self.scheduler.update(field_pk=self.field_pk[fieldidx],
                                      result=res,
                                      finish=True)

    def observeMJD(self, mjd):
        mjd_evening_twilight = self.scheduler.evening_twilight(mjd)
        mjd_morning_twilight = self.scheduler.morning_twilight(mjd)
        self.curr_mjd = mjd_evening_twilight
        # int_mjd = int(self.curr_mjd)
        if mjd % 100 == 0:
            print("!!!!", mjd)

        # guesses = np.arange(0, 1, 0.05)

        self.nextchange = mjd_morning_twilight

        while (self.curr_mjd < mjd_morning_twilight
               and self.curr_mjd < self.scheduler.end_mjd()):
            # should we do this now?
            isclear, nextchange_weather = self.weather.clear(mjd=self.curr_mjd)
            onoff, nextchange_on = self.scheduler.on(mjd=self.curr_mjd)

            nextchange = np.min(
                np.array(
                    [nextchange_weather, nextchange_on, mjd_morning_twilight]))

            if not isclear:
                # count = 0
                # dur = float(nextchange - self.curr_mjd)
                while self.curr_mjd < nextchange:
                    if nextchange - self.curr_mjd < self.nom_duration:
                        self.curr_mjd = nextchange
                        continue
                    self.obsHist["lst"].append(
                        self.scheduler.lst(self.curr_mjd)[0])
                    self.obsHist["ra"].append(-1)
                    self.obsHist["bright"].append(self.bright())
                    self.obsHist["field_pk"].append(-1)
                    self.obsHist["weather"].append(True)
                    self.obsHist["mjd"].append(self.curr_mjd)
                    self.curr_mjd += self.nom_duration + self.bossReadout + self.cals
                    # count += 1
                # print("WEATHER ", self.curr_mjd, f"night {night_len*24:.1f}, weather {dur*24:.1f}", count)
            elif (onoff != 'on'):
                self.curr_mjd = nextchange

            if self.nextchange - self.curr_mjd < self.nom_duration:
                self.curr_mjd = self.nextchange
                continue

            field_pk, nexposures, noTime = self.nextField()
            if field_pk == -1:
                if noTime:
                    self.curr_mjd = self.curr_mjd + self.nom_duration
                    continue
                # raise Exception()
                # print("skipped ", self.curr_mjd)
                self.obsHist["lst"].append(
                    self.scheduler.lst(self.curr_mjd)[0])
                self.obsHist["ra"].append(np.nan)
                self.obsHist["bright"].append(self.bright())
                self.obsHist["field_pk"].append(-1)
                self.obsHist["weather"].append(False)
                self.obsHist["mjd"].append(self.curr_mjd)
                self.curr_mjd = self.curr_mjd + self.nom_duration
                continue
            self.observeField(field_pk, nexposures)

        # if mjd % 10 == 0:
        #     self.scheduler.priorityLogger.write(name=str(mjd) + "-" + self.observatory.name)

    def lstToArray(self):
        assert len(self.obsHist["weather"]) == len(
            self.obsHist["lst"]), "lst tracking bad!"
        dtype = [('lst', np.float64), ('ra', np.float64), ('bright', np.bool_),
                 ('field_pk', np.int32), ('weather', np.bool_),
                 ('mjd', np.float64)]
        lstOut = np.zeros(len(self.obsHist["lst"]), dtype=dtype)
        lstOut["lst"] = np.array(self.obsHist["lst"])
        lstOut["ra"] = np.array(self.obsHist["ra"])
        lstOut["bright"] = np.array(self.obsHist["bright"])
        lstOut["field_pk"] = np.array(self.obsHist["field_pk"])
        lstOut["weather"] = np.array(self.obsHist["weather"])
        lstOut["mjd"] = np.array(self.obsHist["mjd"])
        return (lstOut)

    def slewsToArray(self):
        dtype = [('time', np.int32), ('mjd', np.int32), ('alt', np.float64),
                 ('az', np.float64), ('rot', np.float64), ('ra', np.float64),
                 ('dec', np.float64)]
        arrayOut = np.zeros(len(self.slews), dtype=dtype)
        arrayOut["time"] = np.array(self.slews)
        arrayOut["mjd"] = np.array(self.slew_mjds)
        arrayOut["alt"] = np.array(self.slew_alt)
        arrayOut["az"] = np.array(self.slew_az)
        arrayOut["rot"] = np.array(self.slew_rot)
        arrayOut["ra"] = np.array(self.slew_ra)
        arrayOut["dec"] = np.array(self.slew_dec)

        return (arrayOut)
Пример #14
0
def get_24hr_airmass(target, interval, airmass_limit):

    plot_data = []
    
    start = Time(datetime.datetime.utcnow())
    end = Time(start.datetime + datetime.timedelta(days=1))
    time_range = time_grid_from_range(
        time_range = [start, end],
        time_resolution = interval*u.minute)
    time_plot = time_range.datetime
    
    fixed_target = FixedTarget(name = target.name, 
        coord = SkyCoord(
            target.ra,
            target.dec,
            unit = 'deg'
        )
    )

    #Hack to speed calculation up by factor of ~3
    sun_coords = get_sun(time_range[int(len(time_range)/2)])
    fixed_sun = FixedTarget(name = 'sun',
        coord = SkyCoord(
            sun_coords.ra,
            sun_coords.dec,
            unit = 'deg'
        )
    )

    #Colors to match SNEx1
    colors = {
        'Siding Spring': '#3366cc',
        'Sutherland': '#dc3912',
        'Teide': '#8c6239',
        'Cerro Tololo': '#ff9900',
        'McDonald': '#109618',
        'Haleakala': '#990099'
    }

    for observing_facility in facility.get_service_classes():

        observing_facility_class = facility.get_service_class(observing_facility)
        sites = observing_facility_class().get_observing_sites()

        for site, site_details in sites.items():

            observer = Observer(
                longitude = site_details.get('longitude')*u.deg,
                latitude = site_details.get('latitude')*u.deg,
                elevation = site_details.get('elevation')*u.m
            )
            
            sun_alt = observer.altaz(time_range, fixed_sun).alt
            obj_airmass = observer.altaz(time_range, fixed_target).secz

            bad_indices = np.argwhere(
                (obj_airmass >= airmass_limit) |
                (obj_airmass <= 1) |
                (sun_alt > -18*u.deg)  #between astro twilights
            )

            obj_airmass = [np.nan if i in bad_indices else float(x)
                for i, x in enumerate(obj_airmass)]

            label = '({facility}) {site}'.format(
                facility = observing_facility, site = site
            )

            plot_data.append(
                go.Scatter(x=time_plot, y=obj_airmass, mode='lines', name=label, marker=dict(color=colors.get(site)))
            )

    return plot_data
def main(args=None):
    p = parser()
    opts = p.parse_args(args)

    # Late imports
    import operator
    import sys

    from astroplan import Observer
    from astroplan.plots import plot_airmass
    from astropy.coordinates import EarthLocation, SkyCoord
    from astropy.table import Table
    from astropy.time import Time
    from astropy import units as u
    from matplotlib import dates
    from matplotlib.cm import ScalarMappable
    from matplotlib.colors import Normalize
    from matplotlib.patches import Patch
    from matplotlib import pyplot as plt
    from tqdm import tqdm
    import pytz

    from ..io import fits
    from .. import moc
    from .. import plot  # noqa
    from ..extern.quantile import percentile

    if opts.site is None:
        if opts.site_longitude is None or opts.site_latitude is None:
            p.error('must specify either --site or both '
                    '--site-longitude and --site-latitude')
        location = EarthLocation(lon=opts.site_longitude * u.deg,
                                 lat=opts.site_latitude * u.deg,
                                 height=(opts.site_height or 0) * u.m)
        if opts.site_timezone is not None:
            location.info.meta = {'timezone': opts.site_timezone}
        observer = Observer(location)
    else:
        if not ((opts.site_longitude is None) and
                (opts.site_latitude is None) and (opts.site_height is None) and
                (opts.site_timezone is None)):
            p.error('argument --site not allowed with arguments '
                    '--site-longitude, --site-latitude, '
                    '--site-height, or --site-timezone')
        observer = Observer.at_site(opts.site)

    m = fits.read_sky_map(opts.input.name, moc=True)

    # Make an empty airmass chart.
    t0 = Time(opts.time) if opts.time is not None else Time.now()
    t0 = observer.midnight(t0)
    ax = plot_airmass([], observer, t0, altitude_yaxis=True)

    # Remove the fake source and determine times that were used for the plot.
    del ax.lines[:]
    times = Time(np.linspace(*ax.get_xlim()), format='plot_date')

    theta, phi = moc.uniq2ang(m['UNIQ'])
    coords = SkyCoord(phi, 0.5 * np.pi - theta, unit='rad')
    prob = moc.uniq2pixarea(m['UNIQ']) * m['PROBDENSITY']

    levels = np.arange(90, 0, -10)
    nlevels = len(levels)
    percentiles = np.concatenate((50 - 0.5 * levels, 50 + 0.5 * levels))

    airmass = np.column_stack([
        percentile(condition_secz(coords.transform_to(observer.altaz(t)).secz),
                   percentiles,
                   weights=prob) for t in tqdm(times)
    ])

    cmap = ScalarMappable(Normalize(0, 100), plt.get_cmap())
    for level, lo, hi in zip(levels, airmass[:nlevels], airmass[nlevels:]):
        ax.fill_between(
            times.plot_date,
            clip_verylarge(lo),  # Clip infinities to large but finite values
            clip_verylarge(hi),  # because fill_between cannot handle inf
            color=cmap.to_rgba(level),
            zorder=2)

    ax.legend([Patch(facecolor=cmap.to_rgba(level)) for level in levels],
              ['{}%'.format(level) for level in levels])
    # ax.set_title('{} from {}'.format(m.meta['objid'], observer.name))

    # Adapted from astroplan
    start = times[0]
    twilights = [
        (times[0].datetime, 0.0),
        (observer.sun_set_time(Time(start), which='next').datetime, 0.0),
        (observer.twilight_evening_civil(Time(start),
                                         which='next').datetime, 0.1),
        (observer.twilight_evening_nautical(Time(start),
                                            which='next').datetime, 0.2),
        (observer.twilight_evening_astronomical(Time(start),
                                                which='next').datetime, 0.3),
        (observer.twilight_morning_astronomical(Time(start),
                                                which='next').datetime, 0.4),
        (observer.twilight_morning_nautical(Time(start),
                                            which='next').datetime, 0.3),
        (observer.twilight_morning_civil(Time(start),
                                         which='next').datetime, 0.2),
        (observer.sun_rise_time(Time(start), which='next').datetime, 0.1),
        (times[-1].datetime, 0.0),
    ]

    twilights.sort(key=operator.itemgetter(0))
    for i, twi in enumerate(twilights[1:], 1):
        if twi[1] != 0:
            ax.axvspan(twilights[i - 1][0],
                       twilights[i][0],
                       ymin=0,
                       ymax=1,
                       color='grey',
                       alpha=twi[1],
                       linewidth=0)
        if twi[1] != 0.4:
            ax.axvspan(twilights[i - 1][0],
                       twilights[i][0],
                       ymin=0,
                       ymax=1,
                       color='white',
                       alpha=0.8 - 2 * twi[1],
                       zorder=3,
                       linewidth=0)

    # Add local time axis
    timezone = (observer.location.info.meta or {}).get('timezone')
    if timezone:
        tzinfo = pytz.timezone(timezone)
        ax2 = ax.twiny()
        ax2.set_xlim(ax.get_xlim())
        ax2.set_xticks(ax.get_xticks())
        ax2.xaxis.set_major_formatter(dates.DateFormatter('%H:%M', tz=tzinfo))
        plt.setp(ax2.get_xticklabels(), rotation=-30, ha='right')
        ax2.set_xlabel("Time from {} [{}]".format(
            min(times).to_datetime(tzinfo).date(), timezone))

    if opts.verbose:
        # Write airmass table to stdout.
        times.format = 'isot'
        table = Table(masked=True)
        table['time'] = times
        table['sun_alt'] = np.ma.masked_greater_equal(
            observer.sun_altaz(times).alt, 0)
        table['sun_alt'].format = lambda x: '{}'.format(int(np.round(x)))
        for p, data in sorted(zip(percentiles, airmass)):
            table[str(p)] = np.ma.masked_invalid(data)
            table[str(p)].format = lambda x: '{:.01f}'.format(np.around(x, 1))
        table.write(sys.stdout, format='ascii.fixed_width')

    # Show or save output.
    opts.output()
Пример #16
0
def get_sidereal_visibility(target, start_time, end_time, interval,
                            airmass_limit):
    """
    Uses astroplan to calculate the airmass for a sidereal target
    for each given interval between the start and end times.

    The resulting data omits any airmass above the provided limit (or
    default, if one is not provided), as well as any airmass calculated
    during the day (defined as between astronomical twilights).

    Important note: only works for sidereal targets! For non-sidereal visibility, see here:
    https://github.com/TOMToolkit/tom_nonsidereal_airmass

    :param start_time: start of the window for which to calculate the airmass
    :type start_time: datetime

    :param end_time: end of the window for which to calculate the airmass
    :type end_time: datetime

    :param interval: time interval, in minutes, at which to calculate airmass within the given window
    :type interval: int

    :param airmass_limit: maximum acceptable airmass for the resulting calculations
    :type airmass_limit: int

    :returns: A dictionary containing the airmass data for each site. The dict keys consist of the site name prepended
        with the observing facility. The values are the airmass data, structured as an array containing two arrays. The
        first array contains the set of datetimes used in the airmass calculations. The second array contains the
        corresponding set of airmasses calculated.
    :rtype: dict
    """

    if target.type != 'SIDEREAL':
        msg = '\033[1m\033[91mAirmass plotting is only supported for sidereal targets\033[0m'
        logger.info(msg)
        empty_visibility = {}
        return empty_visibility

    if end_time < start_time:
        raise Exception('Start must be before end')

    if airmass_limit is None:
        airmass_limit = 10

    body = FixedTarget(name=target.name,
                       coord=SkyCoord(target.ra, target.dec, unit='deg'))

    visibility = {}
    sun, time_range = get_astroplan_sun_and_time(start_time, end_time,
                                                 interval)
    for observing_facility in facility.get_service_classes():
        observing_facility_class = facility.get_service_class(
            observing_facility)
        sites = observing_facility_class().get_observing_sites()
        for site, site_details in sites.items():
            observer = Observer(
                longitude=site_details.get('longitude') * units.deg,
                latitude=site_details.get('latitude') * units.deg,
                elevation=site_details.get('elevation') * units.m)

            sun_alt = observer.altaz(time_range, sun).alt
            obj_airmass = observer.altaz(time_range, body).secz

            bad_indices = np.argwhere(
                (obj_airmass >= airmass_limit) | (obj_airmass <= 1)
                | (sun_alt > -18 *
                   units.deg)  # between astronomical twilights, i.e. sun is up
            )

            obj_airmass = [
                None if i in bad_indices else float(airmass)
                for i, airmass in enumerate(obj_airmass)
            ]

            visibility[f'({observing_facility}) {site}'] = (
                time_range.datetime, obj_airmass)
    return visibility
Пример #17
0
def is_object_visible(celestial_obj: object, secz_max: float) -> tuple:
    """
    Check if the object is visible in the set start and end times.

    :param celestial_obj: object to view (FixedTarget())
    :param secz_max: Maximum viewing angle.
    :return: starting altitude, azimuth and ending altitude, azimuth.
    """
    location = Observer(
        location=EarthLocation.from_geodetic(
            lon=(Const.LONGITUDE * u.deg), lat=(Const.LATITUDE * u.deg), height=(Const.ELEVATION * u.m)
        ),
        name="location",
        timezone="UTC",
    )
    start_time = Time(
        f"{Const.START_YEAR}-"
        + f"{Const.START_MONTH}-"
        + f"{Const.START_DAY} "
        + f"{Const.START_TIME}",
        format="iso",
    )
    end_time = Time(
        f"{Const.END_YEAR}-"
        + f"{Const.END_MONTH}-"
        + f"{Const.END_DAY} "
        + f"{Const.END_TIME}",
        format="iso",
    )
    Logger.log(f"Checking sec(z) for {celestial_obj.name}.")
    start_secz = location.altaz(start_time, celestial_obj).secz
    end_secz = location.altaz(end_time, celestial_obj).secz
    start_altaz = location.altaz(start_time, celestial_obj)
    end_altaz = location.altaz(end_time, celestial_obj)

    try:
        if 0 < start_secz < secz_max:
            Logger.log(
                f"Found starting sec(z) = {start_secz} for {celestial_obj.name}."
            )
            Logger.log(
                f"Zenith={start_altaz.zen} "
                + f"Altitiude={start_altaz.alt}"
                + f"Azimuth={start_altaz.az}"
            )
            start_alt = start_altaz.alt
            start_az = start_altaz.az
        else:
            start_alt = "-"
            start_az = "-"
        if 0 < end_secz < secz_max:
            Logger.log(f"Found ending sec(z) = {end_secz} for {celestial_obj.name}.")
            Logger.log(
                f"Zenith={start_altaz.zen} "
                + f"Altitiude={start_altaz.alt}"
                + f"Azimuth={start_altaz.az}"
            )
            end_alt = end_altaz.alt
            end_az = end_altaz.az
        else:
            end_alt = "-"
            end_az = "-"
        return start_alt, start_az, end_alt, end_az
    except ValueError as e:
        Logger.log(f"Could not find sec(z) for {celestial_obj.name}.", 40)
        Logger.log(str(e), 40)
        Logger.log(start_secz, 40)
        return "-", "-", "-", "-"
    return "-", "-", "-", "-"
Пример #18
0
def get_altaz(obj_name, ipt_lon, ipt_lat, t=None):

    #for html scrapping
    #from lxml import html
    #from bs4 import BeautifulSoup
    #to place requests
    import requests
    import json

    import astropy.units as u
    from astropy.time import Time
    from astropy.coordinates import SkyCoord, EarthLocation, Angle, Latitude, Longitude

    from astroplan import FixedTarget, Observer
    from astroquery.simbad import Simbad as simbad

    import ephem

    if t == None: t = Time.now()

    ## Set up the observer
    obs_el = 100 * u.m
    loc = EarthLocation.from_geodetic(ipt_lon, ipt_lat, obs_el)
    my_site = Observer(name='My_Site', location=loc)

    obs_lat = my_site.location.lat
    obs_lon = my_site.location.lon

    #observer for pyephem
    ephem_site = ephem.Observer()
    ephem_site.lon, ephem_site.lat = str(obs_lon.deg), str(obs_lat.deg)
    ephem_site.date = ephem.Date(str(t.decimalyear))

    ##Get the object
    #Check for planet-hood.
    #if planet: resolve the individual planet with pyephem.
    #else if satellite or ISS (or TIANGONG) scrap the appropriate websites and return info
    #else query simbad

    ############
    # Put in an auto-correct for kids
    ############
    #just make it lower case for now

    obj_name = obj_name.lower()

    if obj_name in [
            "sun", "mercury", "venus", "moon", "mars", "jupiter", "saturn",
            "uranus", "neptune", "pluto"
    ]:

        if obj_name == "sun": my_planet = ephem.Sun()
        elif obj_name == "mercury": my_planet = ephem.Mercury()
        elif obj_name == "venus": my_planet = ephem.Venus()
        elif obj_name == "moon": my_planet = ephem.Moon()
        elif obj_name == "mars": my_planet = ephem.Mars()
        elif obj_name == "jupiter": my_planet = ephem.Jupiter()
        elif obj_name == "saturn": my_planet = ephem.Saturn()
        elif obj_name == "uranus": my_planet = ephem.Uranus()
        elif obj_name == "neptune": my_planet = ephem.Neptune()
        elif obj_name == "pluto": my_planet = ephem.Pluto()

        my_planet.compute(ephem_site)
        az = my_planet.az * 180 / 3.1415926535
        alt = my_planet.alt * 180 / 3.1415926535
#here coded for just ISS but for all satellites we should have similar setups, probably poll site
    elif (obj_name == "iss"):
        #try a request for the iss from the open notify site. Gives current json data
        page = requests.get("http://api.open-notify.org/iss-now.json")
        issdata = page.json()
        tstamp = issdata['timestamp']
        isslat = issdata['iss_position']['latitude']
        isslon = issdata['iss_position']['longitude']
        #there are issues with just this amount of data as you do not know the altitude of the object
        #here we fix it to 350 km
        issheight = 350 * u.km
        isslat = Latitude(isslat, unit=u.deg)
        isslon = Longitude(isslon, unit=u.deg)

        #there are issues however as this data does NOT contain the altitude so lets try scrapping the html
        #the issue with fullissdata is that it contains information in NASA style units (M50 Cartesian & M50 Keplerian)
        page = requests.get(
            "http://spaceflight.nasa.gov/realdata/sightings/SSapplications/Post/JavaSSOP/orbit/ISS/SVPOST.html"
        )
        #fullissdata=html.fromstring(page.text)

        #there are also other satellites liseted in, issue is parsing the information as I do not know what each field contains
        #the issue here is that all sat data contains unknown units and uncertain which entries contain useful information
        page = requests.get(
            "http://www.celestrak.com/NORAD/elements/stations.txt")
        allsatdata = page.text

        c = SkyCoord(isslon, isslat, issheight)
        my_target = FixedTarget(name='ISS', coord=c)
        az = my_site.altaz(t, my_target).az.deg
        alt = my_site.altaz(t, my_target).alt.deg
    else:
        try:
            q = simbad.query_object(obj_name)
            c = SkyCoord(q["RA"][0], q["DEC"][0], unit=(u.hourangle, u.deg))
            my_star = FixedTarget(name='my_star', coord=c)

            az = my_site.altaz(t, my_star).az.deg
            alt = my_site.altaz(t, my_star).alt.deg
        except:
            print("Couldn't find Object in Database")
            alt, az = 0, 0

    return alt, az
Пример #19
0
def get_24hr_airmass(target, interval, airmass_limit):

    plot_data = []

    start = Time(datetime.datetime.utcnow())
    end = Time(start.datetime + datetime.timedelta(days=1))
    time_range = time_grid_from_range(time_range=[start, end],
                                      time_resolution=interval * u.minute)
    time_plot = time_range.datetime

    fixed_target = FixedTarget(name=target.name,
                               coord=SkyCoord(target.ra,
                                              target.dec,
                                              unit='deg'))

    #Hack to speed calculation up by factor of ~3
    sun_coords = get_sun(time_range[int(len(time_range) / 2)])
    fixed_sun = FixedTarget(name='sun',
                            coord=SkyCoord(sun_coords.ra,
                                           sun_coords.dec,
                                           unit='deg'))

    for observing_facility in facility.get_service_classes():

        if observing_facility != 'LCO':
            continue

        observing_facility_class = facility.get_service_class(
            observing_facility)
        sites = observing_facility_class().get_observing_sites()

        for site, site_details in sites.items():

            observer = Observer(longitude=site_details.get('longitude') *
                                u.deg,
                                latitude=site_details.get('latitude') * u.deg,
                                elevation=site_details.get('elevation') * u.m)

            sun_alt = observer.altaz(time_range, fixed_sun).alt
            obj_airmass = observer.altaz(time_range, fixed_target).secz

            bad_indices = np.argwhere(
                (obj_airmass >= airmass_limit) | (obj_airmass <= 1)
                | (sun_alt > -18 * u.deg)  #between astro twilights
            )

            obj_airmass = [
                np.nan if i in bad_indices else float(x)
                for i, x in enumerate(obj_airmass)
            ]

            label = '({facility}) {site}'.format(facility=observing_facility,
                                                 site=site)

            plot_data.append(
                go.Scatter(
                    x=time_plot,
                    y=obj_airmass,
                    mode='lines',
                    name=label,
                ))

    return plot_data
Пример #20
0
print(total_mins)                     #Total minutes for observation 


############################################################################################################
#Loop through all ra and dec

for ii,r in enumerate(ra):
    for jj,d in enumerate(dec):
                
        target_coord = SkyCoord(ra=r*u.deg, dec=d*u.deg)
        target = FixedTarget(coord=target_coord, name="source")
        
        
        #Airmasses at observatory 1
        
        airmass_obs1=obs1.altaz(times, target).secz          #calculate airmass for observatory 1
        masked_airmass_obs1 = np.ma.array(airmass_obs1, mask=airmass_obs1 < 1)#mask airmasses for observatory 1

        
        #Airmasses at observatory2
        
        airmass_obs2=obs2.altaz(times,target).secz   #calculate airmass for observatory 2
        masked_airmass_obs2 = np.ma.array(airmass_obs2, mask=airmass_obs2 < 1)#mask airmasses for observatory 2
        
        xc=obs1.is_night(times,horizon= -12*u.deg)  #Times that it is night time at observatory 1 from time list 
        cc=obs2.is_night(times,horizon= -12*u.deg)  #Times that it is night time at observatory 2 from time list 
        
        
        
        
        # For the case night only observation for observatory 1 and 2 
Пример #21
0
def test_compare_azimuth_constraint_and_observer():
    time = Time('2001-02-03 04:05:06')
    time_ranges = [
        Time([time, time + 1 * u.hour]) + offset
        for offset in np.arange(0, 400, 100) * u.day
    ]
    for time_range in time_ranges:
        mmt = Observer(longitude=249.115*u.deg, latitude=31.6883*u.deg,  \
                                 elevation=2608*u.m, name="mmt", timezone="US/Arizona")
        targets = [vega, rigel, polaris]

        # Testing for easterly targets, from northeast (45) to southeast (135).
        min_az = Angle(45 * u.deg)
        max_az = Angle(135 * u.deg)

        # Same checks on azimuth inputs as in AzimuthConstraint.
        # Constrain the minimum and maximum azimuth angles to 0-360 range.
        min_az.wrap_at('360d', inplace=True)
        max_az.wrap_at('360d', inplace=True)
        # Handle the case of minimum azimuth having a larger value than the maximum azimuth.
        # This can occur when the azimuth range includes north (azimuth == 0).
        if min_az > max_az:
            max_az += 360 * u.deg

        # Check if each target meets azimth constraints using Observer
        always_from_observer = [
            all([
                min_az < mmt.altaz(time, target).az < max_az
                for time in time_grid_from_range(time_range)
            ]) for target in targets
        ]
        # Check if each target meets azimuth constraints using
        # is_always_observable and AzimuthConstraint
        always_from_constraint = is_always_observable(AzimuthConstraint(
            min_az, max_az),
                                                      mmt,
                                                      targets,
                                                      time_range=time_range)
        assert all(always_from_observer == always_from_constraint)

        # Testing for northerly targets, from northwest (315) to northeast (45).
        min_az = Angle(315 * u.deg)
        max_az = Angle(45 * u.deg)

        # Same checks on azimuth inputs as in AzimuthConstraint.
        # Constrain the minimum and maximum azimuth angles to 0-360 range.
        min_az.wrap_at('360d', inplace=True)
        max_az.wrap_at('360d', inplace=True)
        # Handle the case of minimum azimuth having a larger value than the maximum azimuth.
        # This can occur when the azimuth range includes north (azimuth == 0).
        if min_az > max_az:
            max_az += 360 * u.deg

        # Check if each target meets azimth constraints using Observer
        always_from_observer = [
            all([
                min_az < mmt.altaz(time, target).az < max_az
                for time in time_grid_from_range(time_range)
            ]) for target in targets
        ]
        # Check if each target meets azimuth constraints using
        # is_always_observable and AzimuthConstraint
        always_from_constraint = is_always_observable(AzimuthConstraint(
            min_az, max_az),
                                                      mmt,
                                                      targets,
                                                      time_range=time_range)
        assert all(always_from_observer == always_from_constraint)