Esempio n. 1
0
    def post(self, request, *args, **kwargs):
        """
        Method that handles POST requests for the ``DataProductSaveView``. Gets the observation facility that created
        the data and saves the selected data products as ``DataProduct`` objects. Redirects to the
        ``ObservationDetailView`` for the specific ``ObservationRecord``.

        :param request: Django POST request object
        :type request: HttpRequest
        """
        service_class = get_service_class(request.POST['facility'])
        observation_record = ObservationRecord.objects.get(pk=kwargs['pk'])
        products = request.POST.getlist('products')
        if not products:
            messages.warning(
                request,
                'No products were saved, please select at least one dataproduct'
            )
        elif products[0] == 'ALL':
            products = service_class().save_data_products(observation_record)
            messages.success(request, 'Saved all available data products')
        else:
            for product in products:
                products = service_class().save_data_products(
                    observation_record, product)
                messages.success(
                    request, 'Successfully saved: {0}'.format('\n'.join(
                        [str(p) for p in products])))
        return redirect(
            reverse('tom_observations:detail',
                    kwargs={'pk': observation_record.id}))
Esempio n. 2
0
    def get_context_data(self, *args, **kwargs):
        """
        Adds a number of items to the context object for this view, including the form for adding resulting
        ``DataProduct`` objects to a ``DataProductGroup``, the ``DataProduct`` objects associated with the
        ``ObservationRecord``, and the most recent image from this ``ObservationRecord``. It also populates the
        ``DataProductUploadForm`` hidden fields with initial data.

        :returns: context dictionary
        :rtype: dict
        """
        context = super().get_context_data(*args, **kwargs)
        context['form'] = AddProductToGroupForm()
        service_class = get_service_class(self.object.facility)
        context['editable'] = isinstance(service_class(),
                                         BaseManualObservationFacility)
        context['data_products'] = service_class().all_data_products(
            self.object)
        context['can_be_cancelled'] = self.object.status not in service_class(
        ).get_terminal_observing_states()
        newest_image = None
        for data_product in context['data_products']['saved']:
            newest_image = data_product if (not newest_image or data_product.modified > newest_image.modified) and \
                data_product.get_file_extension() == '.fits' else newest_image
        if newest_image:
            context['image'] = newest_image.get_image_data()
        data_product_upload_form = DataProductUploadForm(
            initial={
                'observation_record':
                self.get_object(),
                'referrer':
                reverse('tom_observations:detail',
                        args=(self.get_object().id, ))
            })
        context['data_product_form'] = data_product_upload_form
        return context
Esempio n. 3
0
 def get_context_data(self, *args, **kwargs):
     context = super().get_context_data(*args, **kwargs)
     context['form'] = AddProductToGroupForm()
     service_class = get_service_class(self.object.facility)
     context['data_products'] = service_class().all_data_products(
         self.object)
     newest_image = None
     for data_product in context['data_products']['saved']:
         newest_image = data_product if (not newest_image or data_product.modified > newest_image.modified) and \
             data_product.get_file_extension() == '.fits' else newest_image
     if newest_image:
         context['image'] = newest_image.get_image_data()
     data_timestamp = self.get_object().scheduled_end if self.get_object().scheduled_end \
         else self.get_object().created
     data_product_upload_form = DataProductUploadForm(
         initial={
             'observation_record':
             self.get_object(),
             'observation_timestamp':
             data_timestamp,
             'facility':
             self.get_object().facility,
             'referrer':
             reverse('tom_observations:detail',
                     args=(self.get_object().id, ))
         },
         hide_target_fields=True)
     context['data_product_form'] = data_product_upload_form
     return context
Esempio n. 4
0
    def _process_spectrum_from_fits(self, data_product, facility):
        """
        Processes the data from a spectrum from a fits file into a Spectrum1D object, which can then be serialized and
        stored as a ReducedDatum for further processing or display. File is read using specutils as specified in the
        below documentation.
        # https://specutils.readthedocs.io/en/doc-testing/specutils/read_fits.html

        Parameters
        ----------
        data_product : tom_dataproducts.models.DataProduct
            Spectroscopic DataProduct which will be processed into a Spectrum1D
        facility : str
            The name of the facility from which the data was taken, and should match the key in the FACILITY property in
            the TOM settings.

        Returns
        -------
        specutils.Spectrum1D
            Spectrum1D object containing the data from the DataProduct
        """

        flux, header = fits.getdata(data_product.data.path, header=True)

        dim = len(flux.shape)
        if dim == 3:
            flux = flux[0, 0, :]
        elif flux.shape[0] == 2:
            flux = flux[0, :]
        header['CUNIT1'] = 'Angstrom'
        wcs = WCS(header=header)
        flux = flux * get_service_class(facility)().get_flux_constant()

        spectrum = Spectrum1D(flux=flux, wcs=wcs)

        return spectrum
Esempio n. 5
0
 def is_valid(self):
     super().is_valid()
     obs_module = get_service_class(self.cleaned_data['facility'])
     errors = obs_module().validate_observation(self.observation_payload())
     if errors:
         self.add_error(None, self._flatten_error_dict(errors))
     return not errors
Esempio n. 6
0
    def run(self):
        failed_observations = [
            obsr for obsr in
            self.dynamic_cadence.observation_group.observation_records.all()
            if obsr.failed
        ]
        new_observations = []
        for obs in failed_observations:
            observation_payload = obs.parameters
            facility = get_service_class(obs.facility)()
            start_keyword, end_keyword = facility.get_start_end_keywords()
            observation_payload = self.advance_window(
                observation_payload,
                start_keyword=start_keyword,
                end_keyword=end_keyword)
            obs_type = obs.parameters.get('observation_type', None)
            form = facility.get_form(obs_type)(observation_payload)
            form.is_valid()
            observation_ids = facility.submit_observation(
                form.observation_payload())

            for observation_id in observation_ids:
                # Create Observation record
                record = ObservationRecord.objects.create(
                    target=obs.target,
                    facility=facility.name,
                    parameters=observation_payload,
                    observation_id=observation_id)
                self.dynamic_cadence.observation_group.observation_records.add(
                    record)
                self.dynamic_cadence.observation_group.save()
                new_observations.append(record)

        return new_observations
Esempio n. 7
0
    def handle(self, *args, **options):
        # Check required settings are present before proceeding
        try:
            from_addr = settings.TOM_EDUCATION_FROM_EMAIL_ADDRESS
        except AttributeError:
            self.stderr.write('TOM_EDUCATION_FROM_EMAIL_ADDRESS not set in settings.py')
            return

        # Keep track of targets and alerts with new data
        new_data_targets = set([])
        new_data_alerts = set([])

        for alert in ObservationAlert.objects.all():
            ob = alert.observation
            facility_class = get_service_class(ob.facility)
            facility = facility_class()

            if ob.status not in facility.get_terminal_observing_states():
                facility.update_observation_status(ob.observation_id)
                self.stdout.write('Checking for new data for observation {}'.format(ob.observation_id))
                if facility.save_data_products(ob):
                    new_data_targets.add(ob.target)
                    new_data_alerts.add(alert)

        for target in new_data_targets:
            # Make new timelapse
            # TODO: supress imageio output
            prods = (target.dataproduct_set.filter(data__endswith=self.IMAGE_FILE_SUFFIX)
                                           .exclude(data__endswith=RAW_FILE_EXTENSION))
            if not prods.exists():
                continue
            new_pipeline = TimelapsePipeline.create_timestamped(target, prods)
            self.stdout.write('Creating timelapse for target {}'.format(target.name))
            try:
                new_pipeline.run()
            except AsyncError as ex:
                self.stderr.write(f'Failed to create timelapse: {ex}')
                return
            new_tl = new_pipeline.group.dataproduct_set.first()

            # Delete old timelapses
            # TODO: control deletion from settings.py
            timelapses = (DataProduct.objects
                                     .filter(target=target, data_product_type=settings.DATA_PRODUCT_TYPES['timelapse'][0])
                                     .exclude(pk=new_tl.pk)
                                     .all())
            for tl in timelapses:
                tl.delete()
                tl.data.delete(save=False)

        for alert in new_data_alerts:
            target = alert.observation.target
            # Send update email
            subject = "Observation for '{}' has new data".format(target.name)
            message = ("Your observation for '{}' has completed, and a "
                       "timelapse is available".format(target.name))
            to = [alert.email]
            send_mail(subject, message, from_addr, to)
        self.stdout.write('Send {} email updates'.format(len(new_data_alerts)))
Esempio n. 8
0
    def get_form_class(self):
        facility_name = self.get_facility_name()

        if not facility_name:
            raise ValueError('Must provide a facility name')

        # TODO: modify this to work with all LCO forms
        return get_service_class(facility_name)().get_template_form(None)
Esempio n. 9
0
    def get_facility_class(self):
        """
        Gets the facility interface class

        :returns: facility class name
        :rtype: str
        """
        return get_service_class(self.get_facility())
Esempio n. 10
0
 def is_valid(self):
     super().is_valid()
     # TODO this is a bit leaky and should be done without the need of get_service_class
     obs_module = get_service_class(self.cleaned_data['facility'])
     errors = obs_module().validate_observation(self.observation_payload())
     if errors:
         self.add_error(None, self._flatten_error_dict(errors))
     return not errors
Esempio n. 11
0
def get_radec_ephemeris(eph_json_single, start_time, end_time, interval,
                        observing_facility, observing_site):
    observing_facility_class = facility.get_service_class(observing_facility)
    sites = observing_facility_class().get_observing_sites()
    observer = None
    for site_name in sites:
        obs_site = sites[site_name]
        if obs_site['sitecode'] == observing_site:

            observer = coordinates.EarthLocation(
                lat=obs_site.get('latitude') * units.deg,
                lon=obs_site.get('longitude') * units.deg,
                height=obs_site.get('elevation') * units.m)
    if observer is None:
        # this condition occurs if the facility being requested isn't in the site list provided.
        return (None, None, None, None, -1)
    ra = []
    dec = []
    mjd = []
    for i in range(len(eph_json_single)):
        ra.append(float(eph_json_single[i]['R']))
        dec.append(float(eph_json_single[i]['D']))
        mjd.append(float(eph_json_single[i]['t']))
    ra = np.array(ra)
    dec = np.array(dec)
    mjd = np.array(mjd)

    fra = interp.interp1d(mjd, ra)
    fdec = interp.interp1d(mjd, dec)

    start = Time(start_time)
    end = Time(end_time)

    time_range = time_grid_from_range(time_range=[start, end],
                                      time_resolution=interval * units.hour)
    tr_mjd = time_range.mjd

    airmasses = []
    sun_alts = []
    for i in range(len(tr_mjd)):
        c = SkyCoord(fra(time_range[i].mjd),
                     fdec(time_range[i].mjd),
                     frame="icrs",
                     unit="deg")
        t = Time(tr_mjd[i], format='mjd')
        sun = coordinates.get_sun(t)
        altaz = c.transform_to(AltAz(obstime=t, location=observer))
        sun_altaz = sun.transform_to(AltAz(obstime=t, location=observer))
        airmass = altaz.secz
        airmasses.append(airmass)
        sun_alts.append(sun_altaz.alt.value)
    airmasses = np.array(airmasses)
    sun_alts = np.array(sun_alts)

    if np.min(tr_mjd) >= np.min(mjd) and np.max(tr_mjd) <= np.max(mjd):
        return (tr_mjd, fra(tr_mjd), fdec(tr_mjd), airmasses, sun_alts)
    else:
        return (None, None, None, None, -2)
Esempio n. 12
0
def get_visibility(target, start_time, end_time, interval, airmass_limit=10):
    """
    Calculates the airmass for a 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.

    :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 not airmass_limit:
        airmass_limit = 10
    visibility = {}
    body = get_pyephem_instance_for_type(target)
    sun = ephem.Sun()
    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():
            positions = [[], []]
            observer = observer_for_site(site_details)
            rise_sets = get_rise_set(observer, sun, start_time, end_time)
            curr_interval = start_time
            while curr_interval <= end_time:
                time = curr_interval
                last_rise_set = get_last_rise_set_pair(rise_sets, time)
                sunup = time > last_rise_set[0] and time < last_rise_set[1] if last_rise_set else False
                observer.date = curr_interval
                body.compute(observer)
                alt = Angle(str(body.alt), unit=units.degree)
                az = Angle(str(body.az), unit=units.degree)
                altaz = AltAz(alt=alt.to_string(unit=units.rad), az=az.to_string(unit=units.rad))
                airmass = altaz.secz
                positions[0].append(curr_interval)
                positions[1].append(
                    airmass.value if (airmass.value > 1 and airmass.value <= airmass_limit) and not sunup else None
                )
                curr_interval += timedelta(minutes=interval)
            visibility['({0}) {1}'.format(observing_facility, site)] = positions
    return visibility
Esempio n. 13
0
 def cancel(self, request, *args, **kwargs):
     instance = self.get_object()
     facility = get_service_class(instance.facility)()
     try:
         success = facility.cancel_observation(instance.observation_id)
         if success:
             facility.update_observation_status(instance.observation_id)
             instance.refresh_from_db()
             serializer = self.get_serializer(instance)
             return Response(serializer.data, status=status.HTTP_200_OK)
     except Exception as e:
         raise ValidationError(f'Unable to cancel observation due to: {e}')
Esempio n. 14
0
def find_saved_data_products(target_id):
    '''
    target_id: unique ID of the target to look up
    '''
    obs_recs = ObservationRecord.objects.filter(target__identifier=target_id)
    frames = []
    for obs_rec in obs_recs:
        products = get_service_class(
            obs_rec.facility)().all_data_products(obs_rec)
        frames.append(products['saved'])
    logger.debug("Total frames=%s" % (len(frames)))
    return frames
Esempio n. 15
0
    def get(self, request, *args, **kwargs):
        obsr_id = self.kwargs.get('pk')
        obsr = ObservationRecord.objects.get(id=obsr_id)
        facility = get_service_class(obsr.facility)()
        errors = facility.cancel_observation(obsr.observation_id)
        if errors:
            messages.error(self.request,
                           f'Unable to cancel observation: {errors}')

        referer = self.request.GET('next', None)
        referer = urlparse(referer).path if referer else '/'
        return redirect(referer)
Esempio n. 16
0
    def is_valid(self):
        if not self.is_bound or self.errors:  # Note: accessing errors calls clean()
            return False

        # Validation below is copied from tom_base. Note that calling
        # super().is_valid() is not desirable here since the tom_base code
        # *always* validates the observation (which involves an API call) even
        # if clean() has already thrown up errors
        obs_module = get_service_class(self.cleaned_data['facility'])
        errors = obs_module().validate_observation(self.observation_payload())
        if errors:
            self.add_error(None, self._flatten_error_dict(errors))
        return not errors
Esempio n. 17
0
 def get_context_data(self, *args, **kwargs):
     context = super().get_context_data(*args, **kwargs)
     context['form'] = AddProductToGroupForm()
     service_class = get_service_class(self.object.facility)
     context['data_products'] = service_class().all_data_products(
         self.object)
     newest_image = None
     for data_product in context['data_products']['saved']:
         newest_image = data_product if (not newest_image or data_product.modified > newest_image.modified) and \
             data_product.get_file_extension() == '.fits' else newest_image
     if newest_image:
         context['image'] = newest_image.get_image_data()
     return context
Esempio n. 18
0
    def _process_spectrum_from_plaintext(self, data_product):
        """
        Processes the data from a spectrum from a plaintext file into a Spectrum1D object, which can then be serialized
        and stored as a ReducedDatum for further processing or display. File is read using astropy as specified in
        the below documentation. The file is expected to be a multi-column delimited file, with headers for wavelength
        and flux. The file also requires comments containing, at minimum, 'DATE-OBS: [value]', where value is an
        Astropy Time module-readable date. It can optionally contain 'FACILITY: [value]', where the facility is a string
        matching the name of a valid facility in the TOM.
        # http://docs.astropy.org/en/stable/io/ascii/read.html
        Parameters
        ----------
        :param data_product: Spectroscopic DataProduct which will be processed into a Spectrum1D
        :type data_product: tom_dataproducts.models.DataProduct
        :returns: Spectrum1D object containing the data from the DataProduct
        :rtype: specutils.Spectrum1D
        :returns: Datetime of observation, if it is in the comments and the file is from a supported facility, current
            datetime otherwise
        :rtype: AstroPy.Time
        """

        from django.core.files.storage import default_storage

        data_aws = default_storage.open(data_product.data.name, 'r')

        data = ascii.read(data_aws.read(), names=['wavelength', 'flux'])

        if len(data) < 1:
            raise InvalidFileFormatException(
                'Empty table or invalid file type')
        facility_name = None
        date_obs = datetime.now()
        comments = data.meta.get('comments', [])

        for comment in comments:
            if 'date-obs' in comment.lower():
                date_obs = comment.split(':')[1].strip()
            if 'facility' in comment.lower():
                facility_name = comment.split(':')[1].strip()

        facility = get_service_class(
            facility_name)() if facility_name else None
        wavelength_units = facility.get_wavelength_units(
        ) if facility else self.DEFAULT_WAVELENGTH_UNITS
        flux_constant = facility.get_flux_constant(
        ) if facility else self.DEFAULT_FLUX_CONSTANT

        spectral_axis = np.array(data['wavelength']) * wavelength_units
        flux = np.array(data['flux']) * flux_constant
        spectrum = Spectrum1D(flux=flux, spectral_axis=spectral_axis)

        return spectrum, Time(date_obs).to_datetime()
Esempio n. 19
0
def facility_observation_form(target, facility, observation_type):
    """
    Displays a form for submitting an observation for a specific facility and observation type, e.g., imaging.
    """
    facility_class = get_service_class(facility)()
    initial_fields = {
        'target_id': target.id,
        'facility': facility,
        'observation_type': observation_type
    }
    obs_form = facility_class.get_form(observation_type)(initial=initial_fields)
    obs_form.helper.form_action = reverse('tom_observations:create', kwargs={'facility': facility})

    return {'obs_form': obs_form}
Esempio n. 20
0
    def handle(self, *args, **options):
        facility_classes = {}
        for facility_name in facility.get_service_classes():
            facility_classes[facility_name] = facility.get_service_class(
                facility_name)()
        observation_records = ObservationRecord.objects.all()
        for record in observation_records:
            if record.status not in facility_classes[
                    record.facility].get_terminal_observing_states():
                facility_classes[record.facility].update_observation_status(
                    record.observation_id)
                facility_classes[record.facility].save_data_products(record)

        return 'completed command'
Esempio n. 21
0
    def perform_create(self, serializer):
        data = serializer.validated_data
        try:
            target = Target.objects.get(pk=data['target'])
            facility_class = get_service_class(data['facility'])
            template = ObservationTemplate.objects.get(
                target=target,
                name=data['template_name'],
                facility=data['facility']
            )
        except Target.DoesNotExist:
            raise NotFound(detail='Target not found.')
        except ImportError:
            raise NotFound(detail='Facility not found.')
        except ObservationTemplate.DoesNotExist:
            err = "Template '{}' not found for target '{}' and facility '{}'".format(
                data['template_name'], target.name, data['facility']
            )
            raise NotFound(detail=err)

        # Construct form for creating an observation
        form_data = {
            'target_id': target.pk,
            'facility': facility_class.name
        }
        form_data.update(json.loads(template.fields))
        id_field = ObservationTemplate.get_identifier_field(facility_class.name)
        form_data[id_field] = template.get_identifier()
        form_data.update(data.get('overrides', {}))
        form = facility_class.get_form(None)(form_data)  # observation type is not relevant to us
        if not form.is_valid():
            raise serializers.ValidationError(form.errors)

        # Submit observation using facility class
        observation_ids = facility_class().submit_observation(form.observation_payload())
        assert len(observation_ids) == 1, (
            'Submittion created multiple observation IDs: {}'.format(observation_ids)
        )
        # Create Observation record and alert
        ob = ObservationRecord.objects.create(
            target=target,
            facility=facility_class.name,
            parameters=form.serialize_parameters(),
            observation_id=observation_ids[0]
        )
        ObservationAlert.objects.create(email=data['email'], observation=ob)
Esempio n. 22
0
    def get(self, request, *args, **kwargs):
        obsr_id = self.kwargs.get('pk')
        obsr = ObservationRecord.objects.get(id=obsr_id)
        facility = get_service_class(obsr.facility)()
        try:
            success = facility.cancel_observation(obsr.observation_id)
            if success:
                messages.success(self.request,
                                 f'Successfully cancelled observation {obsr}')
                facility.update_observation_status(obsr.observation_id)
            else:
                messages.error(self.request, 'Unable to cancel observation.')
        except forms.ValidationError as ve:
            messages.error(self.request, f'Unable to cancel observation: {ve}')

        return redirect(
            reverse('tom_observations:detail', kwargs={'pk': obsr.id}))
Esempio n. 23
0
 def handle(self, *args, **options):
     if options['target_id']:
         try:
             target = Target.objects.get(pk=options['target_id'])
             observation_records = ObservationRecord.objects.filter(target=target)
         except Target.DoesNotExist:
             raise Exception('Invalid target id provided')
     else:
         observation_records = ObservationRecord.objects.all()
     facility = get_service_class('LCO')
     for record in observation_records:
         if not record.terminal:
             facility().update_observation_status(record.observation_id)
         if record.terminal:
             record.save_data()
             #self.save_data_products(observation_record=record)
             self.stdout.write(f'Saved data for {record}')
     return 'Success!'
Esempio n. 24
0
    def _process_spectrum_from_fits(self, data_product):
        """
        Processes the data from a spectrum from a fits file into a Spectrum1D object, which can then be serialized and
        stored as a ReducedDatum for further processing or display. File is read using specutils as specified in the
        below documentation.
        # https://specutils.readthedocs.io/en/doc-testing/specutils/read_fits.html

        :param data_product: Spectroscopic DataProduct which will be processed into a Spectrum1D
        :type data_product: tom_dataproducts.models.DataProduct

        :returns: Spectrum1D object containing the data from the DataProduct
        :rtype: specutils.Spectrum1D

        :returns: Datetime of observation, if it is in the header and the file is from a supported facility, current
            datetime otherwise
        :rtype: AstroPy.Time
        """

        flux, header = fits.getdata(data_product.data.path, header=True)

        for facility_class in get_service_classes():
            facility = get_service_class(facility_class)()
            if facility.is_fits_facility(header):
                flux_constant = facility.get_flux_constant()
                date_obs = facility.get_date_obs_from_fits_header(header)
                break
        else:
            flux_constant = self.DEFAULT_FLUX_CONSTANT
            date_obs = datetime.now()

        dim = len(flux.shape)
        if dim == 3:
            flux = flux[0, 0, :]
        elif flux.shape[0] == 2:
            flux = flux[0, :]
        flux = flux * flux_constant

        header['CUNIT1'] = 'Angstrom'
        wcs = WCS(header=header, naxis=1)

        spectrum = Spectrum1D(flux=flux, wcs=wcs)

        return spectrum, Time(date_obs).to_datetime()
Esempio n. 25
0
def save_reduced_lco_dataproducts(target_id):
    '''
    target_id: unique ID of the target to look up
    '''
    obs_recs = ObservationRecord.objects.filter(target__identifier=target_id)
    if not obs_recs:
        return False
    service_class = get_service_class(obs_recs[0].facility)
    reduced_products = []
    for obs_rec in obs_recs:
        products = service_class().all_data_products(obs_rec)
        # Only save the reduced files
        for product in products['unsaved']:
            if 'e91' in product['filename']:
                p = service_class().save_data_products(obs_rec, product['id'])
                reduced_products.append(p)
    logger.debug('Successfully saved: {0}'.format('\n'.join(
        [str(p) for p in reduced_products])))
    return
Esempio n. 26
0
def get_24hr_airmass(target, start_time, interval, airmass_limit):

    end_time = start_time + datetime.timedelta(days=1)

    visibility = {}
    sun = ephem.Sun()
    body = utils.get_pyephem_instance_for_type(target)

    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():

            positions = [[], []]
            observer = utils.observer_for_site(site_details)

            sun_up_times = get_up_times(observer, sun, start_time, end_time,
                                        interval)
            obj_up_times = get_up_times(observer, body, start_time, end_time,
                                        interval)

            good_times = sorted(list(obj_up_times - sun_up_times))

            for time in good_times:
                observer.date = time
                body.compute(observer)
                alt = Angle(str(body.alt), unit=u.degree)
                az = Angle(str(body.az), unit=u.degree)
                altaz = AltAz(alt=alt.to_string(unit=u.rad),
                              az=az.to_string(unit=u.rad))
                airmass = altaz.secz
                positions[0].append(time)
                positions[1].append(airmass.value if (
                    airmass.value > 1 and airmass.value <= airmass_limit
                ) else None)
            visibility['({0}) {1}'.format(observing_facility,
                                          site)] = positions

    return visibility
Esempio n. 27
0
    def handle(self, *args, **options):
        target = None
        if options['target_id']:
            try:
                target = Target.objects.get(pk=options['target_id'])
            except ObjectDoesNotExist:
                raise Exception('Invalid target id provided')

        failed_records = {}
        for facility_name in facility.get_service_classes():
            clazz = facility.get_service_class(facility_name)
            failed_records[facility_name] = clazz().update_all_observation_statuses(target=target)
        success = True
        for facility_name, errors in failed_records.items():
            if len(errors) > 0:
                success = False
                break
        if success:
            return 'Update completed successfully'
        else:
            return 'Update completed with errors: {0}'.format(str(failed_records))
Esempio n. 28
0
 def post(self, request, *args, **kwargs):
     service_class = get_service_class(request.POST['facility'])
     observation_record = ObservationRecord.objects.get(pk=kwargs['pk'])
     products = request.POST.getlist('products')
     if not products:
         messages.warning(
             request,
             'No products were saved, please select at least one dataproduct'
         )
     elif products[0] == 'ALL':
         products = service_class().save_data_products(observation_record)
         messages.success(request, 'Saved all available data products')
     else:
         for product in products:
             products = service_class().save_data_products(
                 observation_record, product)
             messages.success(
                 request, 'Successfully saved: {0}'.format('\n'.join(
                     [str(p) for p in products])))
     return redirect(
         reverse('tom_observations:detail',
                 kwargs={'pk': observation_record.id}))
Esempio n. 29
0
def dataproduct_list_for_observation_unsaved(observation_record):
    products = get_service_class(
        observation_record.facility)().all_data_products(observation_record)
    return {'products': products}
Esempio n. 30
0
    def run(self):
        # gets the most recent observation because the next observation is just going to modify these parameters
        last_obs = self.dynamic_cadence.observation_group.observation_records.order_by(
            '-created').first()

        # Make a call to the facility to get the current status of the observation
        facility = get_service_class(last_obs.facility)()
        facility.update_observation_status(
            last_obs.observation_id)  # Updates the DB record
        last_obs.refresh_from_db()  # Gets the record updates

        # Boilerplate to get necessary properties for future calls
        start_keyword, end_keyword = facility.get_start_end_keywords()
        observation_payload = last_obs.parameters_as_dict

        # Cadence logic
        # If the observation hasn't finished, do nothing
        if not last_obs.terminal:
            return
        elif last_obs.failed:  # If the observation failed
            # Submit next observation to be taken as soon as possible with the same window length
            window_length = parse(observation_payload[end_keyword]) - parse(
                observation_payload[start_keyword])
            observation_payload[start_keyword] = datetime.now().isoformat()
            observation_payload[end_keyword] = (
                parse(observation_payload[start_keyword]) +
                window_length).isoformat()
        else:  # If the observation succeeded
            # Advance window normally according to cadence parameters
            observation_payload = self.advance_window(
                observation_payload,
                start_keyword=start_keyword,
                end_keyword=end_keyword)

        observation_payload = self.update_observation_payload(
            observation_payload)

        # Submission of the new observation to the facility
        obs_type = last_obs.parameters_as_dict.get('observation_type')
        form = facility.get_form(obs_type)(observation_payload)
        form.is_valid()
        observation_ids = facility.submit_observation(
            form.observation_payload())

        # Creation of corresponding ObservationRecord objects for the observations
        new_observations = []
        for observation_id in observation_ids:
            # Create Observation record
            record = ObservationRecord.objects.create(
                target=last_obs.target,
                facility=facility.name,
                parameters=json.dumps(observation_payload),
                observation_id=observation_id)
            # Add ObservationRecords to the DynamicCadence
            self.dynamic_cadence.observation_group.observation_records.add(
                record)
            self.dynamic_cadence.observation_group.save()
            new_observations.append(record)

        # Update the status of the ObservationRecords in the DB
        for obsr in new_observations:
            facility = get_service_class(obsr.facility)()
            facility.update_observation_status(obsr.observation_id)

        return new_observations