def _get_ra_target_intervals(self, target, up, airmass, effective_horizon): star = Star(self.site['latitude'], target, effective_horizon) if up: day_interval_func = self._find_when_target_is_up else: day_interval_func = self._find_when_target_is_down # Find rise/set/transit for each day intervals = [] current_date = self.start_date while current_date < self.end_date + ONE_DAY: one_day_intervals = day_interval_func(target, current_date, star, airmass) # Add today's intervals to the accumulating list of intervals intervals.extend(one_day_intervals) # Move on to tomorrow current_date += ONE_DAY # Collapse adjacent intervals into continuous larger intervals intervals = coalesce_adjacent_intervals(intervals) intervals = intersect_intervals(intervals, [(self.start_date, self.end_date)]) return intervals
def test_coalesce_adjacent_intervals(self): input_intervals = list(self.some_adjacent_intervals) received = coalesce_adjacent_intervals(self.some_adjacent_intervals) assert_equal(received, self.expected_coalescence) # Confirm the input list was not modified in place assert_equal(input_intervals, self.some_adjacent_intervals)
def get_ha_intervals(self, target): """Returns the hour angle intervals for the given target. Returns the hour anle intervals for the given target and given site and date range set in this visibility object. The hour angle intervals are uninterupted chunks of time that the target is within the hour angle limits of the telescope. Args: target (dict): A dictionary of target details in the rise-set library format Returns: list: A list of tuples of start/end datetime pairs that make up the intervals over which this target is within HA limits. """ SIDEREAL_SOLAR_DAY_RATIO = 1.002737909350 SIDEREAL_SOLAR_DAY = datetime.timedelta( seconds=(ONE_DAY.total_seconds() / SIDEREAL_SOLAR_DAY_RATIO)) earliest_date = self.start_date - SIDEREAL_SOLAR_DAY tdb = date_to_tdb(earliest_date) mjd = gregorian_to_ut_mjd(earliest_date) gmst = ut_mjd_to_gmst(mjd) # Need the apparent ra/dec for getting correct ha limits on high dec targets apparent_ra, apparent_dec = mean_to_apparent(target, tdb) # Flip the neg/pos ha limits if site is in the southern hemisphere ha_neg = self.ha_limit_neg ha_pos = self.ha_limit_pos if self.site['latitude'].in_degrees() < 0: ha_neg = -self.ha_limit_pos ha_pos = -self.ha_limit_neg # the rise time hour_rise = ha_neg + apparent_ra.in_hours() - \ self.site['longitude'].in_hours() - gmst.in_hours() hour_rise /= SIDEREAL_SOLAR_DAY_RATIO # the set time hour_set = ha_pos + apparent_ra.in_hours() - \ self.site['longitude'].in_hours() - gmst.in_hours() hour_set /= SIDEREAL_SOLAR_DAY_RATIO current_rise = earliest_date + datetime.timedelta(hours=hour_rise) current_set = earliest_date + datetime.timedelta(hours=hour_set) # Find hour angle limits for each day intervals = [] while current_set < (self.end_date + SIDEREAL_SOLAR_DAY): intervals.append((current_rise, current_set)) current_rise += SIDEREAL_SOLAR_DAY current_set += SIDEREAL_SOLAR_DAY # do not exceed start/end dates intervals = coalesce_adjacent_intervals(intervals) intervals = intersect_intervals(intervals, [(self.start_date, self.end_date)]) return intervals
def find_moving_object_network_up_intervals(window, elements, site_filename, chunksize): '''Network wide wrapper for find_moving_object_up_intervals.''' sites = initialise_sites(site_filename) up_intervals_at = {} for site in sites: up_intervals, altitudes = find_moving_object_up_intervals(window, elements, site, chunksize) coalesced_intervals = coalesce_adjacent_intervals(up_intervals) up_intervals_at[site['name']] = coalesced_intervals return up_intervals_at
def _get_chunked_intervals(self, target, target_intervals, compare_func, constraint, chunksize=datetime.timedelta(minutes=30)): '''Returns a set of datetime 2-tuples, each of which represents an interval of time that the target is greater than the constraint away from the thing-to-be-avoided. The supplied compare_func calculates the distance to it's specific obstacle (moon, zenith). ''' intervals = [] for start, end in target_intervals: chunkstart = start chunkend = min(chunkstart + chunksize, end) while chunkstart != chunkend and chunkend <= end: # get the tdb date of the start time of the interval tdb = date_to_tdb(chunkstart) # get the apparent ra/dec for the target, and for the moon at this timestamp if is_sidereal_target(target): target_app_ra, target_app_dec = mean_to_apparent( target, tdb) else: target_app_ra, target_app_dec = elem_to_topocentric_apparent( chunkstart, target, self.site, target_to_jform(target)) if compare_func({ 'time': chunkstart, 'tdb': tdb }, target_app_ra, target_app_dec, constraint): intervals.append((chunkstart, chunkend)) # increment the chunkstart/end up chunkstart = chunkend chunkend = min(chunkstart + chunksize, end) intervals = coalesce_adjacent_intervals(intervals) return intervals
def get_rise_set_intervals(request_dict, site=''): intervals = [] site = site if site else request_dict['location'].get('site', '') site_details = configdb.get_sites_with_instrument_type_and_location( request_dict['molecules'][0]['instrument_name'], site, request_dict['location'].get('observatory', ''), request_dict['location'].get('telescope', '') ) if not site_details: return intervals intervals_by_site = {} if request_dict.get('id'): cache_key = '{0}.rsi'.format(request_dict['id']) intervals_by_site = cache.get(cache_key, {}) for site in site_details: if intervals_by_site.get(site): intervals.extend(intervals_by_site[site]) else: intervals_by_site[site] = [] rise_set_site = get_rise_set_site(site_details[site]) rise_set_target = get_rise_set_target(request_dict['target']) for window in request_dict['windows']: visibility = get_rise_set_visibility(rise_set_site, window['start'], window['end'], site_details[site]) intervals_by_site[site].extend( visibility.get_observable_intervals( rise_set_target, airmass=request_dict['constraints']['max_airmass'], moon_distance=Angle(degrees=request_dict['constraints']['min_lunar_distance']) ) ) intervals.extend(intervals_by_site[site]) if request_dict.get('id'): cache.set(cache_key, intervals_by_site, 86400 * 30) # cache for 30 days return coalesce_adjacent_intervals(intervals)