Exemple #1
0
    def handle(self, *args, **kwargs):
        cadenced_groups = DynamicCadence.objects.filter(active=True)

        updated_cadences = []

        for cg in cadenced_groups:
            strategy = get_cadence_strategy(cg.cadence_strategy)(cg)
            new_observations = strategy.run()
            if not new_observations:
                logger.log(msg=f'No changes from dynamic cadence {cg}',
                           level=logging.INFO)
            else:
                logger.log(
                    msg=f'''Cadence update completed for dynamic cadence {cg},
                                   {len(new_observations)} new observations created.''',
                    level=logging.INFO)
                updated_cadences.append(cg.observation_group)

        if updated_cadences:
            msg = 'Created new observations for dynamic cadences with observation groups: {0}.'
            return msg.format(', '.join([str(cg) for cg in updated_cadences]))
        else:
            return 'No new observations for any dynamic cadences.'
Exemple #2
0
    def form_valid(self, form):
        """
        Runs after form validation. Submits the observation to the desired facility and creates an associated
        ``ObservationRecord``, then redirects to the detail page of the target to be observed.

        If the facility returns more than one record, a group is created and all observation
        records from the request are added to it.

        :param form: form containing observating request parameters
        :type form: subclass of GenericObservationForm
        """
        # Submit the observation
        facility = self.get_facility_class()
        target = self.get_target()
        observation_ids = facility().submit_observation(
            form.observation_payload())
        records = []

        for observation_id in observation_ids:
            # Create Observation record
            record = ObservationRecord.objects.create(
                target=target,
                user=self.request.user,
                facility=facility.name,
                parameters=form.serialize_parameters(),
                observation_id=observation_id)
            records.append(record)

        # TODO: redirect to observation list for multiple observations, observation detail otherwise

        if len(records) > 1 or form.cleaned_data.get('cadence_strategy'):
            observation_group = ObservationGroup.objects.create(
                name=form.cleaned_data['name'])
            observation_group.observation_records.add(*records)
            assign_perm('tom_observations.view_observationgroup',
                        self.request.user, observation_group)
            assign_perm('tom_observations.change_observationgroup',
                        self.request.user, observation_group)
            assign_perm('tom_observations.delete_observationgroup',
                        self.request.user, observation_group)

            # TODO: Add a test case that includes a dynamic cadence submission
            if form.cleaned_data.get('cadence_strategy'):
                cadence_parameters = {}
                cadence_form = get_cadence_strategy(
                    form.cleaned_data.get('cadence_strategy')).form
                for field in cadence_form().cadence_fields:
                    cadence_parameters[field] = form.cleaned_data.get(field)
                DynamicCadence.objects.create(
                    observation_group=observation_group,
                    cadence_strategy=form.cleaned_data.get('cadence_strategy'),
                    cadence_parameters=cadence_parameters,
                    active=True)

        if not settings.TARGET_PERMISSIONS_ONLY:
            groups = form.cleaned_data['groups']
            for record in records:
                assign_perm('tom_observations.view_observationrecord', groups,
                            record)
                assign_perm('tom_observations.change_observationrecord',
                            groups, record)
                assign_perm('tom_observations.delete_observationrecord',
                            groups, record)

        return redirect(reverse('tom_targets:detail', kwargs={'pk':
                                                              target.id}))
Exemple #3
0
 def get_cadence_strategy_form(self):
     cadence_strategy = self.request.GET.get('cadence_strategy')
     if not cadence_strategy:
         return CadenceForm
     return get_cadence_strategy(cadence_strategy).form
Exemple #4
0
    def create(self, request, *args, **kwargs):
        """
        Endpoint for submitting a new observation. Please see ObservationRecordViewSet for details on submission.
        """

        # Initialize the observation form, validate the form data, and submit to the observatory
        observation_ids = []
        try:
            facility = get_service_class(self.request.data['facility'])()
            observation_form_class = facility.observation_forms[
                self.request.data['observation_type']]
            target = Target.objects.get(pk=self.request.data['target_id'])
            observing_parameters = self.request.data['observing_parameters']
        except KeyError as ke:
            raise ValidationError(f'Missing required field {ke}.')
        except Exception as e:
            raise ValidationError(e)

        observing_parameters.update({
            k: v
            for k, v in self.request.data.items()
            if k in ['name', 'target_id', 'facility']
        })
        observation_form = observation_form_class(
            self.request.data['observing_parameters'])
        if observation_form.is_valid():
            logger.info(
                f'Submitting observation to {facility} with parameters {observation_form.observation_payload}'
            )
            observation_ids = facility.submit_observation(
                observation_form.observation_payload())
            logger.info(
                f'Successfully submitted to {facility}, received observation ids {observation_ids}'
            )
        else:
            logger.warning(
                f'Unable to submit observation due to errors: {observation_form.errors}'
            )
            raise ValidationError(observation_form.errors)

        # Normally related objects would be created in the serializer--however, because the ObservationRecordSerializer
        # may need to create multiple objects that are related to the same ObservationGroup and DynamicCadence, we are
        # creating the related objects in the ViewSet.
        cadence = self.request.data.get('cadence')
        observation_group = None

        if len(observation_ids) > 1 or cadence:
            # Create the observation group and assign permissions
            observation_group_name = observation_form.cleaned_data.get(
                'name', f'{target.name} at {facility.name}')
            observation_group = ObservationGroup.objects.create(
                name=observation_group_name)
            assign_perm('tom_observations.view_observationgroup',
                        self.request.user, observation_group)
            assign_perm('tom_observations.change_observationgroup',
                        self.request.user, observation_group)
            assign_perm('tom_observations.delete_observationgroup',
                        self.request.user, observation_group)
            logger.info(f'Created ObservationGroup {observation_group}.')

            cadence_parameters = cadence
            if cadence_parameters is not None:
                # Cadence strategy is not used for the cadence form
                cadence_strategy = cadence_parameters.pop(
                    'cadence_strategy', None)
                if cadence_strategy is None:
                    raise ValidationError(
                        'cadence_strategy must be included to initiate a DynamicCadence.'
                    )
                else:
                    # Validate the cadence parameters against the cadence strategy that gets passed in
                    cadence_form_class = get_cadence_strategy(
                        cadence_strategy).form
                    cadence_form = cadence_form_class(cadence_parameters)
                    if cadence_form.is_valid():
                        dynamic_cadence = DynamicCadence.objects.create(
                            observation_group=observation_group,
                            cadence_strategy=cadence_strategy,
                            cadence_parameters=cadence_parameters,
                            active=True)
                        logger.info(
                            f'Created DynamicCadence {dynamic_cadence}.')
                    else:
                        observation_group.delete()
                        raise ValidationError(cadence_form.errors)

        # Create the serializer data used to create the observation records
        serializer_data = []
        for obsr_id in observation_ids:
            obsr_data = {  # TODO: at present, submitted fields have to be added to this dict manually, maybe fix?
                'name': self.request.data.get('name', ''),
                'target': target.id,
                'user': self.request.user.id,
                'facility': facility.name,
                'groups': self.request.data.get('groups', []),
                'parameters': observation_form.serialize_parameters(),
                'observation_id': obsr_id,
            }
            serializer_data.append(obsr_data)

        serializer = self.get_serializer(data=serializer_data, many=True)
        try:
            # Validate the serializer data, create the observation records, and add them to the group, if necessary
            serializer.is_valid(raise_exception=True)
            self.perform_create(serializer)
            if observation_group is not None:
                observation_group.observation_records.add(*serializer.instance)
        except ValidationError as ve:
            observation_group.delete()
            logger.error(
                f'Failed to create ObservationRecord due to exception {ve}')
            raise ValidationError(
                f'''Observation submission successful, but failed to create a corresponding
                                      ObservationRecord due to exception {ve}.'''
            )

        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data,
                        status=status.HTTP_201_CREATED,
                        headers=headers)