Skip to content

Instantly share code, notes, and snippets.

@zemogle
Created July 9, 2019 08:20
Show Gist options
  • Save zemogle/cb80fe0bf8526a74064310708f9b1984 to your computer and use it in GitHub Desktop.
Save zemogle/cb80fe0bf8526a74064310708f9b1984 to your computer and use it in GitHub Desktop.
Schedule observations of Moon using Las Cumbres Observatory
from datetime import datetime, timedelta
import os
import requests
import logging
import json
import click
from astropy.time import Time
from astropy.coordinates import EarthLocation, get_moon, AltAz, get_sun
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
# handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s | %(message)s',
'%Y-%m-%d %H:%M:%S')
handler.setFormatter(formatter)
logger.addHandler(handler)
PROPOSAL_ID = 'INSERT_PROPOSAL_CODE'
TOKEN = 'INSERT_OBSERVATION_PORTAL_TOKEN'
PORTAL_REQUEST_SUBMIT_API = 'https://observe.lco.global/api/requestgroups/'
PORTAL_REQUEST_API = 'https://observe.lco.global/api/'
EXPOSURE = '1.0'
DEFAULT_CAMERAS = { '1m0' : '1M0-SCICAM-SBIG',
'2m0' : '2M0-SCICAM-SPECTRAL',
'0m4' : '0M4-SCICAM-SBIG'
}
SITES = {
'ogg': {'lat': 20.7075, 'lon': -156.256111,'alt':3055},
'coj': {'lat': -31.273333, 'lon': 149.071111,'alt':1116},
'lsc': {'lat': -30.1675, 'lon': -70.804722,'alt':2198},
'elp': {'lat': 30.67, 'lon': -104.02,'alt':2070},
'cpt': {'lat': -32.38, 'lon': 20.81,'alt':1460},
'tfn': {'lat': 28.3, 'lon': -16.51,'alt':2330},
}
def get_observation_status(requestid):
'''
Get status of RequestID from the Valhalla API
'''
if not requestid:
return False, "No request ID provided"
headers = {'Authorization': 'Token {}'.format(TOKEN)}
url = PORTAL_REQUEST_API + requestid
try:
r = requests.get(url, headers=headers, timeout=20.0)
except requests.exceptions.Timeout:
msg = "Observing portal API timed out"
logger.error(msg)
params['error_msg'] = msg
return False, msg
if r.status_code in [200,201]:
logger.debug('Submitted request')
req = r.json()
return requestid, req['state']
else:
logger.error("Could not send request: {}".format(r.content))
return False, r.content
def submit_observation_request(params):
'''
Send the observation parameters and the authentication cookie to the Scheduler API
'''
headers = {'Authorization': 'Token {}'.format(TOKEN)}
url = PORTAL_REQUEST_SUBMIT_API
logger.debug('Submitting request')
try:
r = requests.post(url, json=params, headers=headers, timeout=20.0)
except requests.exceptions.Timeout:
msg = "Observing portal API timed out"
logger.error(msg)
params['error_msg'] = msg
return False, msg
if r.status_code in [200,201]:
logger.debug('Submitted request')
return True, r.json()['requests'][0]['id']
else:
logger.error("Could not send request: {}".format(r.content))
return False, r.content
def request_format(ra, dec, start, end, proposal, site, aperture='0m4'):
'''
Format a simple request using the schema the Scheduler understands
'''
target = {
'name' : 'Moon',
'ra' : ra.value, # RA (degrees)
'dec' : dec.value, # Dec (Degrees)
'epoch' : 2000,
'type' : 'ICRS'
}
# this selects any telescope on the 1 meter network
location = {
'telescope_class' : aperture,
'site' : site
}
constraints = {
'max_airmass': 2.0,
'min_lunar_distance': 0.0
}
# f_str = json.loads(obs_filter)
configurations = [
{
'type': 'EXPOSE',
'instrument_type': DEFAULT_CAMERAS[aperture],
'target': target,
'constraints': constraints,
'acquisition_config': {},
'guiding_config': {},
'instrument_configs': [
{
'exposure_time': EXPOSURE,
'exposure_count': 1,
'optical_elements': {
'filter': 'up'
}
}
]
}]
# Do the observation between these dates
window = {
'start' : str(start),
'end' : str(end)
}
request_group = {
"name": "moon{}".format(start.strftime("%m%dt%H%M%S")),
"proposal": proposal,
"ipp_value" : 1.05,
"operator" : "SINGLE",
"observation_type": "NORMAL",
'requests': [{
'configurations': configurations,
'windows': [window],
'location': location,
}]
}
return request_group
def moon_coords(date, site):
loc = EarthLocation(lat=SITES[site]['lat'], lon=SITES[site]['lon'], height=SITES[site]['alt'])
time = Time(date)
coords = get_moon(time,loc)
altazframe = AltAz(obstime=time,location=loc)
earth_coords = coords.transform_to(altazframe)
sunaltaz = get_sun(time).transform_to(altazframe)
logger.debug('Alt: {:.2f}'.format(earth_coords.alt.value))
logger.debug('Sun at: {:.2f}'. format(sunaltaz.alt.value))
return coords, time, earth_coords.alt.value, sunaltaz.alt.value
@click.command()
@click.option('-d', '--date',type=str)
@click.option('-s', '--site',type=str)
def main(date, site):
coords,time, alt, sun = moon_coords(date,site)
if alt < 30.:
logger.error('Too low at site {}'.format(site))
return
if sun > -18.:
logger.error('Sky not dark enough')
return
start = time.datetime - timedelta(seconds=60)
end = time.datetime + timedelta(seconds=180)
params = request_format(coords.ra, coords.dec, start, end, PROPOSAL_ID, site)
resp_status, resp_msg = submit_observation_request(params=params)
logger.debug(resp_msg)
return
if __name__ == '__main__':
main()
@zemogle
Copy link
Author

zemogle commented Jul 9, 2019

To run this e.g. python moon.py -d 2019-07-09T08:45:00 -s coj where the datetime is UT and the site is one of the 3 letter LCO site codes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment