Source code for tom_observations.facilities.lco_redirect

from urllib.parse import urljoin
import logging
import urllib.parse

from django.conf import settings
from django.shortcuts import get_object_or_404

from tom_observations.facility import BaseRedirectObservationFacility
from tom_observations.facilities.lco import LCOFacility
from tom_observations.facilities.ocs import make_request
from tom_observations.models import ObservationRecord, ObservationGroup
from tom_targets.models import Target

logger = logging.getLogger(__name__)


[docs] class LCORedirectFacility(BaseRedirectObservationFacility): """ The ``LCORedirectFacility`` is a little different from the other TOMToolkit Facilities. This facility temporarily redirects users from the TOM to the LCO observing portal, providing them with full access to the observation request options provided by that interface. Once the observation, or group of observations, are submitted, the user is redirected back to the TOM. The user must have access to the LCO observing portal, but will log in with their own credentials, rather than those stored by the TOM. In order to retrieve the observations, the TOM must have access to an LCO API token with permission to access the relevant proposals. For more information on submitting to LCO, Soar, or Blanco, see the `LCO Documentation <https://lco.global/documentation/>`__ . To use this facility you will need to add it to your `TOM_FACILITY_CLASSES` list in ``settings.py`` and have an `api_key` in your `LCO` dictionary in `FACILITIES`: .. code-block:: python :caption: settings.py TOM_FACILITY_CLASSES = [ ... 'tom_observations.facilities.LCORedirectFacility', ... ] FACILITIES = { 'LCO': { 'portal_url': 'https://observe.lco.global', 'api_key': os.getenv('LCO_API_KEY'), }, } """ name = "LCORedirect" observation_types = [("Default", "")] button_label = "LCO/SOAR/BLANCO" button_tooltip = "Redirect to LCO/SOAR/BLANCO observation portal" def __init__(self, *args, **kwargs): self.lco_facility = LCOFacility(name_override=self.name) def target_to_query_params(self, target) -> str: set_fields = { "target_" + k: v for k, v in target.as_dict().items() if v is not None } return urllib.parse.urlencode(set_fields) def observation_portal_url(self) -> str: return settings.FACILITIES.get("LCO", {}).get( "portal_url", "https://observe.lco.global" ) def redirect_url(self, target_id, callback_url): target = get_object_or_404(Target, pk=target_id) query_params = self.target_to_query_params(target) callback_url = urllib.parse.quote_plus(callback_url) portal_url = self.observation_portal_url() url = f"{portal_url}/create?{query_params}&redirect_uri={callback_url}" return url def update_all_observation_statuses(self, *args, **kwargs): return self.lco_facility.update_all_observation_statuses(*args, **kwargs)
[docs] def get_observation_url(self, observation_id): return self.lco_facility.get_observation_url(observation_id)
[docs] def get_terminal_observing_states(self): return self.lco_facility.get_terminal_observing_states()
[docs] def get_observing_sites(self): return self.lco_facility.get_observing_sites()
def get_observation_status(self, observation_id): return self.lco_facility.get_observation_status(observation_id) def data_products(self, observation_id, product_id=None): return self.lco_facility.data_products(observation_id, product_id)
[docs] def get_flux_constant(self): return self.lco_facility.get_flux_constant()
[docs] def get_wavelength_units(self): return self.lco_facility.get_wavelength_units()
[docs] def request_id_to_group(self, observation_id, user, target, parameters): """ The OCS groups individual requests into a single RequestGroup, which is the ID it passes back. This method is responsible for querying the individual request IDs associated with the RequestGroup and mapping them to an ObservationGroup/ObservationRecord in the TOM. """ # Retrieve the RequestGroup from the OCS API response = make_request( 'GET', urljoin(self.observation_portal_url(), f'/api/requestgroups/{observation_id}/'), headers=self.lco_facility._portal_headers() ) response.raise_for_status() response = response.json() # Create observation group - maps to OCS RequestGroup observation_group = ObservationGroup.objects.create( name=response['name'] ) # Create and associate observation records for each child request for request in response['requests']: obs_record = ObservationRecord.objects.create( facility=self.name, user=user, target=target, observation_id=request['id'], parameters=parameters ) observation_group.observation_records.add(obs_record) return observation_group
[docs] def get_facility_status(self): return self.lco_facility.get_facility_status()