Exemplo n.º 1
0
    def validate(self, data):
        # Target special validation
        if configdb.is_spectrograph(data['molecules'][0]['instrument_name']
                                    ) and 'rot_mode' not in data['target']:
            data['target']['rot_mode'] = 'VFLOAT'

        # check if the instrument specified is allowed
        valid_instruments = configdb.get_active_instrument_types(
            data['location'])
        for molecule in data['molecules']:
            if molecule['instrument_name'] not in valid_instruments:
                msg = _(
                    "Invalid instrument name '{}' at site={}, obs={}, tel={}. \n"
                ).format(molecule['instrument_name'],
                         data['location'].get('site', 'Any'),
                         data['location'].get('observatory', 'Any'),
                         data['location'].get('telescope', 'Any'))
                msg += _("Valid instruments include: ")
                for inst_name in valid_instruments:
                    msg += inst_name + ', '
                raise serializers.ValidationError(msg)

        # check that the requests window has enough rise_set visible time to accomodate the requests duration
        if data.get('windows'):
            duration = get_request_duration(data)
            rise_set_intervals = get_rise_set_intervals(data)
            largest_interval = timedelta(seconds=0)
            for interval in rise_set_intervals:
                largest_interval = max((interval[1] - interval[0]),
                                       largest_interval)

            for molecule in data['molecules']:
                if molecule.get('fill_window'):
                    molecule_duration = get_molecule_duration(
                        molecule_dict=molecule)
                    num_exposures = get_num_exposures(
                        molecule, largest_interval -
                        timedelta(seconds=duration - molecule_duration))
                    molecule['exposure_count'] = num_exposures
                    duration = get_request_duration(data)
                # delete the fill window attribute, it is only used for this validation
                try:
                    del molecule['fill_window']
                except KeyError:
                    pass
            if largest_interval.total_seconds() <= 0:
                raise serializers.ValidationError(
                    _('According to the constraints of the request, the target is never visible within the time '
                      'window. Check that the target is in the nighttime sky. Consider modifying the time '
                      'window or loosening the airmass or lunar separation constraints. If the target is '
                      'non sidereal, double check that the provided elements are correct.'
                      ))
            if largest_interval.total_seconds() <= duration:
                raise serializers.ValidationError((
                    'According to the constraints of the request, the target is visible for a maximum of {0:.2f} '
                    'hours within the time window. This is less than the duration of your request {1:.2f} hours. Consider '
                    'expanding the time window or loosening the airmass or lunar separation constraints.'
                ).format(largest_interval.total_seconds() / 3600.0,
                         duration / 3600.0))
        return data
Exemplo n.º 2
0
def get_telescope_states_for_request(request):
    instrument_type = request.molecules.first().instrument_name
    site_intervals = {}
    # Build up the list of telescopes and their rise set intervals for the target on this request
    site_data = configdb.get_sites_with_instrument_type_and_location(
        instrument_type=instrument_type,
        site_code=request.location.site,
        observatory_code=request.location.observatory,
        telescope_code=request.location.telescope)
    for site, details in site_data.items():
        if site not in site_intervals:
            site_intervals[site] = get_rise_set_intervals(
                request.as_dict, site)
    # If you have no sites, return the empty dict here
    if not site_intervals:
        return {}

    # Retrieve the telescope states for that set of sites
    telescope_states = TelescopeStates(start=request.min_window_time,
                                       end=request.max_window_time,
                                       sites=list(site_intervals.keys()),
                                       instrument_types=[instrument_type
                                                         ]).get()
    # Remove the empty intervals from the dictionary
    site_intervals = {
        site: intervals
        for site, intervals in site_intervals.items() if intervals
    }

    # Filter the telescope states list with the site intervals
    filtered_telescope_states = filter_telescope_states_by_intervals(
        telescope_states, site_intervals, request.min_window_time,
        request.max_window_time)

    return filtered_telescope_states
Exemplo n.º 3
0
def expand_cadence_request(request_dict):
    '''
    Takes in a valid cadence request (valid request with cadence block), and expands the request into a list of requests
    with their windows determined by the cadence parameters. Only valid requests that pass rise-set are returned, with
    failing requests silently left out of the returned list.
    :param request_dict: a valid request dictionary with cadence information.
    :return: Expanded list of requests with valid windows within the cadence.
    '''
    cadence = request_dict['cadence']
    # now expand the request into a list of requests with the proper windows from the cadence block
    cadence_requests = []
    half_jitter = timedelta(hours=cadence['jitter'] / 2.0)
    request_duration = get_request_duration(request_dict)
    request_window_start = cadence['start']

    while request_window_start < cadence['end']:
        window_start = max(request_window_start - half_jitter,
                           cadence['start'])
        window_end = min(request_window_start + half_jitter, cadence['end'])

        # test the rise_set of this window
        request_dict['windows'] = [{'start': window_start, 'end': window_end}]
        intervals = get_rise_set_intervals(request_dict)
        largest_interval = get_largest_interval(intervals)
        if largest_interval.total_seconds(
        ) >= request_duration and window_end > timezone.now():
            # this cadence window passes rise_set and is in the future so add it to the list
            request_copy = request_dict.copy()
            del request_copy['cadence']
            cadence_requests.append(request_copy)

        request_window_start += timedelta(hours=cadence['period'])
    return cadence_requests
Exemplo n.º 4
0
def get_request_duration_dict(request_dict):
    req_durations = {'requests': []}
    for req in request_dict:
        req_info = {'duration': get_request_duration(req)}
        mol_durations = [{'duration': get_molecule_duration_per_exposure(mol)} for mol in req['molecules']]
        req_info['molecules'] = mol_durations
        req_info['largest_interval'] = get_largest_interval(get_rise_set_intervals(req)).total_seconds()
        req_info['largest_interval'] -= (PER_MOLECULE_STARTUP_TIME + PER_MOLECULE_GAP)
        req_durations['requests'].append(req_info)
    req_durations['duration'] = sum([req['duration'] for req in req_durations['requests']])

    return req_durations
Exemplo n.º 5
0
 def _visible_intervals(self, request):
     visible_intervals = {}
     for site in self.sites:
         if not request.location.site or request.location.site == site[
                 'code']:
             intervals = get_rise_set_intervals(request.as_dict,
                                                site['code'])
             for r, s in intervals:
                 effective_rise = max(r, self.now)
                 if s > self.now and (
                         s - effective_rise).seconds >= request.duration:
                     if site['code'] in visible_intervals:
                         visible_intervals[site['code']].append(
                             (effective_rise, s))
                     else:
                         visible_intervals[site['code']] = [(effective_rise,
                                                             s)]
     return visible_intervals
Exemplo n.º 6
0
def get_airmasses_for_request_at_sites(request_dict):
    instrument_type = request_dict['molecules'][0]['instrument_name']
    constraints = request_dict['constraints']

    site_data = configdb.get_sites_with_instrument_type_and_location(
        instrument_type=instrument_type,
        site_code=request_dict['location'].get('site'),
        observatory_code=request_dict['location'].get('observatory'),
        telescope_code=request_dict['location'].get('telescope'))

    rs_target = get_rise_set_target(request_dict['target'])

    data = {'airmass_data': {}}
    if request_dict['target']['type'].upper() != 'SATELLITE':
        for site_id, site_details in site_data.items():
            night_times = []
            site_lat = Angle(degrees=site_details['latitude'])
            site_lon = Angle(degrees=site_details['longitude'])
            site_alt = site_details['altitude']
            intervals = get_rise_set_intervals(request_dict, site_id)
            for interval in intervals:
                night_times.extend([
                    time for time in date_range_from_interval(
                        interval[0], interval[1], dt=timedelta(minutes=10))
                ])

            if len(night_times) > 0:
                if site_id not in data:
                    data['airmass_data'][site_id] = {}
                data['airmass_data'][site_id]['times'] = [
                    time.strftime('%Y-%m-%dT%H:%M') for time in night_times
                ]
                data['airmass_data'][site_id][
                    'airmasses'] = calculate_airmass_at_times(
                        night_times, rs_target, site_lat, site_lon, site_alt)
                data['airmass_limit'] = constraints['max_airmass']

    return data