Skip to content
Snippets Groups Projects
Commit 0c880ace authored by Brandon Piotrzkowski's avatar Brandon Piotrzkowski
Browse files

Automate sky map comparison; Fixes #248

parent 26f87403
No related branches found
No related tags found
No related merge requests found
This commit is part of merge request !725. Comments created here will be created in the context of that merge request.
......@@ -2,8 +2,8 @@
from astropy import units as u
from astropy.coordinates import ICRS, SkyCoord
from astropy_healpix import HEALPix, pixel_resolution_to_nside
# import astropy.utils.data
from celery import group
# import astropy.utils.data
import numpy as np
from ligo.skymap.io import fits
from ligo.skymap.tool import ligo_skymap_combine
......@@ -20,29 +20,37 @@ from ..util.tempfile import NamedTemporaryFile
from ..import _version
def create_combined_skymap(graceid):
def create_combined_skymap(se_id, ext_id):
"""Creates and uploads the combined LVC-Fermi skymap.
This also uploads the external trigger skymap to the external trigger
GraceDB page.
"""
preferred_skymap = get_preferred_skymap(graceid)
message = 'Combined LVC-Fermi sky map using {0}.'.format(preferred_skymap)
new_skymap = re.findall(r'(.*).fits', preferred_skymap)[0] + '-gbm.fits.gz'
external_trigger_id = external_trigger(graceid)
return (external_trigger_heasarc.s(external_trigger_id) |
get_external_skymap.s() |
group(
combine_skymaps.s(gracedb.download(preferred_skymap,
graceid)) |
gracedb.upload.s(
new_skymap, graceid, message, ['sky_loc', 'public']),
gracedb.upload.s('glg_healpix_all_bn_v00.fit',
external_trigger_id,
'Sky map from HEASARC.',
['sky_loc', 'public']))
)
se_skymap_filename = get_preferred_skymap(se_id)
ext_skymap_filename = get_external_skymap_filename(ext_id)
new_skymap_filename = re.findall(r'(.*).fits.gz', se_skymap_filename)[0]
se_skymap = gracedb.download(se_skymap_filename, se_id)
ext_skymap = gracedb.download(ext_skymap_filename, ext_id)
message = 'Combined LVC-external sky map using {0}.'.format(
se_skymap_filename)
message_png = (
'Mollweide projection of <a href="/api/events/{graceid}/files/'
'{filename}">{filename}</a>').format(
graceid=se_id, filename=new_skymap_filename + '-ext.fits.gz')
(
combine_skymaps.si(se_skymap, ext_skymap)
|
group(
gracedb.upload.s(new_skymap_filename + '-ext.fits.gz', se_id,
message, ['sky_loc', 'public']),
skymaps.plot_allsky.s()
|
gracedb.upload.s(new_skymap_filename + '-ext.png', se_id,
message_png, ['sky_loc', 'public'])
)
).delay()
@app.task(autoretry_for=(ValueError,), retry_backoff=10,
......@@ -57,8 +65,7 @@ def get_preferred_skymap(graceid):
for message in reversed(gracedb_log):
comment = message['comment']
filename = message['filename']
if (filename.endswith('.fits.gz') or filename.endswith('.fits')) and \
'copied' in comment:
if filename.endswith('.fits.gz'):
return filename
raise ValueError('No skymap available for {0} yet.'.format(graceid))
......@@ -172,6 +179,8 @@ def get_upload_external_skymap(graceid):
graceid,
'Sky map from HEASARC.',
['sky_loc'])
|
gracedb.create_label.si('LUMIN_GO', graceid)
).delay()
except ValueError:
......@@ -300,4 +309,6 @@ def create_upload_external_skymap(event):
graceid,
message,
['sky_loc'])
|
gracedb.create_label.si('LUMIN_GO', graceid)
).delay()
......@@ -12,6 +12,15 @@ from . import raven
log = get_logger(__name__)
REQUIRED_LABELS_BY_TASK = {
'compare': {'SKYMAP_READY', 'LUMIN_GO', 'EM_COINC'},
'combine': {'SKYMAP_READY', 'LUMIN_GO', 'RAVEN_ALERT'}
}
"""These labels should be present on an event to consider it to
be ready for sky map comparison.
"""
@gcn.handler(gcn.NoticeType.SNEWS,
queue='exttrig',
shared=False)
......@@ -145,15 +154,44 @@ def handle_grb_lvalert(alert):
if alert['alert_type'] == 'new' and \
alert['object'].get('group') == 'External':
raven.coincidence_search(graceid, alert['object'], group='CBC')
raven.coincidence_search(graceid, alert['object'],
group='Burst')
elif 'S' in graceid:
raven.coincidence_search(graceid, alert['object'], group='Burst')
elif alert['alert_type'] == 'new' and 'S' in graceid:
preferred_event_id = gracedb.get_superevent(graceid)['preferred_event']
group = gracedb.get_event(preferred_event_id)['group']
if alert['alert_type'] == 'new':
raven.coincidence_search(graceid, alert['object'],
group=group,
pipelines=['Fermi', 'Swift'])
raven.coincidence_search(graceid, alert['object'],
group=group,
pipelines=['Fermi', 'Swift'])
elif alert['alert_type'] == 'label_added' and \
alert['object'].get('group') == 'External':
if _skymaps_are_ready(alert['object'], 'compare') and \
alert['data']['name'] in REQUIRED_LABELS_BY_TASK['compare']:
# if both sky maps present and a coincidence, compare sky maps
se_id, ext_ids = _get_superevent_ext_ids(graceid, alert['object'],
'compare')
superevent = gracedb.get_superevent(se_id)
preferred_event_id = superevent['preferred_event']
gw_group = gracedb.get_event(preferred_event_id)['group']
raven.raven_pipeline([alert['object']], se_id, superevent,
gw_group)
if _skymaps_are_ready(alert['object'], 'combine') and \
alert['data']['name'] in REQUIRED_LABELS_BY_TASK['combine']:
# if both sky maps present and a raven alert, create combined
# skymap
se_id, ext_id = _get_superevent_ext_ids(graceid, alert['object'],
'combine')
external_skymaps.create_combined_skymap(se_id, ext_id)
elif 'EM_COINC' in alert['object']['labels']:
# if not complete, check if GW sky map; apply label to external
# event if GW sky map
se_labels = gracedb.get_labels(alert['object']['superevent'])
if 'SKYMAP_READY' in se_labels:
gracedb.create_label.si('SKYMAP_READY', graceid).delay()
elif alert['alert_type'] == 'label_added' and 'S' in graceid:
# if sky map in superevent, apply label to all external events
# at the time
if 'SKYMAP_READY' in alert['object']['labels']:
for ext_id in alert['object']['em_events']:
gracedb.create_label.si('SKYMAP_READY', ext_id).delay()
@lvalert.handler('superevent',
......@@ -189,3 +227,27 @@ def handle_snews_lvalert(alert):
if alert['alert_type'] == 'new' and group == 'Burst':
raven.coincidence_search(graceid, alert['object'],
group=group, pipelines=['SNEWS'])
def _skymaps_are_ready(event, task):
label_set = set(event['labels'])
required_labels = REQUIRED_LABELS_BY_TASK[task]
return required_labels.issubset(label_set)
def _get_superevent_ext_ids(graceid, event, task):
if task == 'combine':
if 'S' in graceid:
se_id = event['superevent_id']
ext_id = event['em_type']
else:
se_id = event['superevent']
ext_id = event['graceid']
elif task == 'compare':
if 'S' in graceid:
se_id = event['superevent_id']
ext_id = event['em_events']
else:
se_id = event['superevent']
ext_id = [event['graceid']]
return se_id, ext_id
......@@ -329,6 +329,6 @@ def add_event_to_superevent(superevent_id, graceid):
with client.addEventToSuperevent(superevent_id, graceid):
pass # Close without reading response; we only needed the status
except rest.HTTPError as e:
error_msg = '"is already assigned to a Superevent"'
if not (e.status == 400 and e.message == error_msg):
error_msg = 'is already assigned to a Superevent'
if not (e.status == 400 and error_msg in e.message):
raise
......@@ -326,6 +326,8 @@ def trigger_raven_alert(coinc_far_json, superevent, gracedb_id,
(
gracedb.create_label.si('RAVEN_ALERT', superevent_id)
|
gracedb.create_label.si('RAVEN_ALERT', ext_id)
|
gracedb.create_label.si('RAVEN_ALERT', preferred_gwevent_id)
).delay()
if not pass_far_threshold:
......
......@@ -60,14 +60,24 @@ def mock_get_file_contents(monkeypatch, toy_fits_filecontents): # noqa: F811
'astropy.utils.data.get_file_contents', get_file_contents)
@patch('gwcelery.tasks.gracedb.get_superevent', mock_get_superevent)
@patch('gwcelery.tasks.gracedb.get_event', mock_get_event)
@patch('gwcelery.tasks.gracedb.get_log', mock_get_log)
@patch('astropy.utils.data.get_file_contents', mock_get_file_contents)
def test_create_combined_skymap():
@patch('gwcelery.tasks.skymaps.plot_allsky.run')
@patch('gwcelery.tasks.gracedb.upload.run')
@patch('gwcelery.tasks.external_skymaps.combine_skymaps.run')
@patch('gwcelery.tasks.gracedb.download')
@patch('gwcelery.tasks.external_skymaps.get_external_skymap_filename',
return_value='fermi_skymap.fits.gz,0')
@patch('gwcelery.tasks.external_skymaps.get_preferred_skymap',
return_value='bayestar.fits.gz,0')
def test_create_combined_skymap(mock_get_preferred_skymap,
mock_get_external_skymap_filename,
mock_download,
mock_combine_skymaps, mock_upload,
mock_plot_allsky):
"""Test creating combined LVC and Fermi skymap"""
# Run function under test
external_skymaps.create_combined_skymap('S12345')
external_skymaps.create_combined_skymap('S12345', 'E12345')
mock_combine_skymaps.assert_called_once()
mock_upload.assert_called()
@patch('gwcelery.tasks.gracedb.get_log', mock_get_log)
......
......@@ -99,6 +99,86 @@ def test_handle_replace_grb_event(mock_get_event, mock_get_events,
mock_replace_event.assert_called_once_with('E1', text)
@patch('gwcelery.tasks.gracedb.create_label.run')
@patch('gwcelery.tasks.gracedb.get_labels',
return_value=['SKYMAP_READY'])
def test_handle_create_skymap_label_from_ext_event(mock_get_labels,
mock_create_label):
alert = {"uid": "E1212",
"alert_type": "label_added",
"data": {"name": "EM_COINC"},
"object": {
"group": "External",
"labels": ["EM_COINC", "LUMIN_GO"],
"superevent": "S1234"
}
}
external_triggers.handle_grb_lvalert(alert)
mock_create_label.assert_called_once_with('SKYMAP_READY', 'E1212')
@patch('gwcelery.tasks.gracedb.create_label.run')
def test_handle_create_skymap_label_from_superevent(mock_create_label):
alert = {"uid": "S1234",
"alert_type": "label_added",
"data": {"name": "SKYMAP_READY"},
"object": {
"group": "CBC",
"labels": ["SKYMAP_READY"],
"superevent_id": "S1234",
"em_events": ['E1212']
}
}
external_triggers.handle_grb_lvalert(alert)
mock_create_label.assert_called_once_with('SKYMAP_READY', 'E1212')
@patch('gwcelery.tasks.raven.raven_pipeline')
@patch('gwcelery.tasks.gracedb.get_superevent',
return_value={
'superevent_id': 'S1234',
'preferred_event': 'G1234'
})
@patch('gwcelery.tasks.gracedb.get_event',
return_value={
'graceid': 'G1234',
'group': 'CBC'
})
def test_handle_skymap_comparison(mock_get_event, mock_get_superevent,
mock_raven_pipeline):
alert = {"uid": "E1212",
"alert_type": "label_added",
"data": {"name": "SKYMAP_READY"},
"object": {
"graceid": "E1212",
"group": "External",
"labels": ["EM_COINC", "LUMIN_GO", "SKYMAP_READY"],
"superevent": "S1234"
}
}
external_triggers.handle_grb_lvalert(alert)
mock_raven_pipeline.assert_called_once_with([alert['object']], 'S1234',
{'superevent_id': 'S1234',
'preferred_event': 'G1234'},
'CBC')
@patch('gwcelery.tasks.external_skymaps.create_combined_skymap')
def test_handle_skymap_combine(mock_create_combined_skymap):
alert = {"uid": "E1212",
"alert_type": "label_added",
"data": {"name": "RAVEN_ALERT"},
"object": {
"graceid": "E1212",
"group": "External",
"labels": ["EM_COINC", "LUMIN_GO", "SKYMAP_READY",
"RAVEN_ALERT"],
"superevent": "S1234"}
}
external_triggers.handle_grb_lvalert(alert)
mock_create_combined_skymap.assert_called_once_with('S1234', 'E1212')
@patch('gwcelery.tasks.detchar.dqr_json', return_value='dqrjson')
@patch('gwcelery.tasks.gracedb.upload.run')
@patch('gwcelery.tasks.gracedb.get_event', return_value={
......
......@@ -164,7 +164,9 @@ def test_raven_pipeline(mock_create_label,
threshold, when a coincidence is found but does pass threshold, and when
multiple events are found.
"""
alert_object = {'preferred_event': 'G1', 'pipeline': 'GRB'}
alert_object = {'preferred_event': 'G1', 'pipeline': 'GRB', 'labels': []}
for result in raven_search_results:
result['labels'] = []
if 'E' in graceid:
alert_object['group'] = 'External'
raven.raven_pipeline(raven_search_results, graceid, alert_object, group)
......@@ -309,6 +311,7 @@ def test_trigger_raven_alert(mock_create_label, mock_update_superevent,
if expected_result:
label_calls = [call('RAVEN_ALERT', superevent_id),
call('RAVEN_ALERT', ext_id),
call('RAVEN_ALERT', preferred_id)]
if ext_event['pipeline'] == 'SNEWS':
coinc_far = None
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment