Commit 4e091620 authored by Jean-Gregoire Ducoin's avatar Jean-Gregoire Ducoin

Merge branch 'master' into em_coinc_circular

parents f7f77b1f 47dee25f
Pipeline #50463 failed with stages
in 6 minutes and 13 seconds
# Changelog
## 0.0.16 (unreleased)
## 0.0.19 (unreleased)
- No changes yet.
## 0.0.18 (2019-02-25)
- Re-worded part of the EM_COINC circulars that gives the time difference
between the neutrino/GRB trigger and GW candidate event.
## 0.0.17 (2019-02-25)
- Fixed an unfortunate typo.
## 0.0.16 (2019-02-25)
- Improved the EM_COINC and initial circulars.
## 0.0.15 (2019-02-22)
- Added template for EM_COINC circulars, i.e., circulars produced when
......
......@@ -94,7 +94,8 @@ are releasing version 0.0.6.
10. Push everything to GitLab:
git push master --tags
git push --tags
git push -f
Within a few minutes, the new package will be built and uploaded to PyPI.
......
......@@ -38,6 +38,13 @@ def main_dict(gracedb_id, client):
event = client.superevent(gracedb_id).json()
preferred_event_id = event['preferred_event']
preferred_event = client.event(preferred_event_id).json()
preferred_pipeline = preferred_event['pipeline']
gw_events = event['gw_events']
other_pipelines = []
for gw_event in gw_events:
pipeline = client.event(gw_event).json()['pipeline']
if pipeline not in other_pipelines and pipeline != preferred_pipeline:
other_pipelines.append(pipeline)
voevents = client.voevents(gracedb_id).json()['voevents']
log = client.logs(gracedb_id).json()['log']
files = client.files(gracedb_id).json()
......@@ -99,7 +106,8 @@ def main_dict(gracedb_id, client):
gracedb_service_url=urllib.parse.urlunsplit(
(o.scheme, o.netloc, '/superevents/', '', '')),
group=preferred_event['group'],
pipeline=preferred_event['pipeline'],
pipeline=preferred_pipeline,
other_pipelines=other_pipelines,
gpstime='{0:.03f}'.format(round(float(preferred_event['gpstime']), 3)),
search=preferred_event.get('search', ''),
far=preferred_event['far'],
......@@ -114,8 +122,8 @@ def main_dict(gracedb_id, client):
if skymaps:
preferred_skymap = skymaps[-1]['filename']
cl = 90
include_ellipse, ra, dec, a, b, pa, area = uncertainty_ellipse(
gracedb_id, preferred_skymap, client, cl=cl)
include_ellipse, ra, dec, a, b, pa, area, greedy_area = \
uncertainty_ellipse(gracedb_id, preferred_skymap, client, cl=cl)
kwargs.update(
preferred_skymap=preferred_skymap,
cl=cl,
......@@ -125,7 +133,8 @@ def main_dict(gracedb_id, client):
a=coord.Angle(a*u.deg),
b=coord.Angle(b*u.deg),
pa=coord.Angle(pa*u.deg),
ellipse_area=area)
ellipse_area=area,
greedy_area=greedy_area)
return kwargs
......@@ -138,7 +147,8 @@ def compose(gracedb_id, authors=(), mailto=False,
client = rest.GraceDb(service)
kwargs = main_dict(gracedb_id, client=client)
kwargs["authors"] = authors
kwargs.update(authors=authors)
kwargs.update(change_significance_statement=False)
subject = env.get_template('subject.jinja2').render(**kwargs).strip()
body = env.get_template('initial_circular.jinja2').render(**kwargs).strip()
......@@ -160,25 +170,23 @@ def compose_RAVEN(gracedb_id, authors=(),
if client is None:
client = rest.GraceDb(service)
super_event = client.superevent(gracedb_id).json()
event = client.superevent(gracedb_id).json()
if 'EM_COINC' not in super_event['labels']:
if 'EM_COINC' not in event['labels']:
return
preferred_event_id = super_event['preferred_event']
preferred_event_id = event['preferred_event']
preferred_event = client.event(preferred_event_id).json()
group = preferred_event['group']
super_event_far = preferred_event['far']
if (group.lower() == 'cbc' and super_event_far < 3.8e-7) or \
(group.lower() == 'burst' and super_event_far < 3.17e-8):
kwargs = main_dict(gracedb_id, client=client)
superevent_far = preferred_event['far']
gpstime = float(preferred_event['gpstime'])
for em_event_id in super_event['em_events']:
for em_event_id in event['em_events']:
em_event = client.event(em_event_id).json()
em_event_gpstime = float(em_event['gpstime'])
external_pipeline = em_event['pipeline']
# FIXME in GraceDb: Even SNEWS triggers have an extra attribute GRB.
external_trigger = em_event['extra_attributes']['GRB']['trigger_id']
if 'GRB' in external_trigger:
external_trigger = external_trigger.lstrip('GRB ')
SNEWS = (em_event['search'] == 'Supernova')
GRB = (em_event['search'] == 'GRB')
......@@ -186,12 +194,15 @@ def compose_RAVEN(gracedb_id, authors=(),
kwargs = dict(
gracedb_service_url=urllib.parse.urlunsplit(
(o.scheme, o.netloc, '/superevents/', '', '')),
super_event_id=gracedb_id,
super_event_far=preferred_event['far'],
gracedb_id=gracedb_id,
group=group,
superevent_far=preferred_event['far'],
external_pipeline=external_pipeline,
external_trigger=external_trigger,
SNEWS=SNEWS,
GRB=GRB)
GRB=GRB,
latency=abs(round(em_event_gpstime-gpstime, 1)),
beforeafter='before' if gpstime > em_event_gpstime else 'after')
if GRB:
# Grab GRB coincidence FARs
......@@ -213,15 +224,27 @@ def compose_RAVEN(gracedb_id, authors=(),
filename = message['filename']
if (filename.endswith('-gbm.fits.gz')
or 'LVC-Fermi sky map' in comment):
kwargs.update(combined_skymap=filename)
group = preferred_event['group']
if (group.lower() == 'cbc' and super_event_far < 3.8e-7) or \
(group.lower() == 'burst' and super_event_far < 3.17e-8):
kwargs.update(main_dict(gracedb_id, client=client))
kwargs.update(include_initial_circ=True)
cl = 90
include_ellipse, ra, dec, a, b, pa, area, greedy_area = \
uncertainty_ellipse(gracedb_id, filename, client, cl=cl)
kwargs.update(
combined_skymap=filename,
cl=cl,
combined_skymap_include_ellipse=include_ellipse,
combined_skymap_ra=coord.Longitude(ra*u.deg),
combined_skymap_dec=coord.Latitude(dec*u.deg),
combined_skymap_a=coord.Angle(a*u.deg),
combined_skymap_b=coord.Angle(b*u.deg),
combined_skymap_pa=coord.Angle(pa*u.deg),
combined_skymap_ellipse_area=area,
combined_skymap_greedy_area=greedy_area)
kwargs.update(main_dict(gracedb_id, client=client))
if (group.lower() == 'cbc' and superevent_far < 3.8e-7) or \
(group.lower() == 'burst' and superevent_far < 3.17e-8):
kwargs.update(change_significance_statement=False)
else:
kwargs.update(include_initial_circ=False)
kwargs.update(change_significance_statement=True)
subject = (
env.get_template('RAVEN_subject.jinja2').render(**kwargs)
......@@ -308,8 +331,8 @@ def compose_retraction(gracedb_id, authors=(),
"""Compose GCN retraction circular"""
if client is None:
client = rest.GraceDb(service)
super_event = client.superevent(gracedb_id).json()
preferred_event = client.event(super_event['preferred_event']).json()
event = client.superevent(gracedb_id).json()
preferred_event = client.event(event['preferred_event']).json()
kwargs = dict(
subject='Retraction',
......@@ -374,4 +397,5 @@ def uncertainty_ellipse(graceid, filename, client, cl=90):
ra, dec, a, b, pa, ellipse_area = find_ellipse(prob, cl=cl,
projection='ARC',
nest=False)
return ellipse_area <= 1.35*greedy_area, ra, dec, a, b, pa, ellipse_area
return ellipse_area <= 1.35*greedy_area, ra, dec, a, b, pa, \
ellipse_area, greedy_area
{% from 'macros.jinja2' import naturalfar %}
{% from 'macros.jinja2' import naturalfar, grbmission, propername %}
{% include 'authors.jinja2' %}
{% if include_initial_circ %}
{% include 'initial_body.jinja2' %}
{% endif %}
{% filter rewrap %}
{% if SNEWS %}
A search performed by the RAVEN pipeline found a temporal coincidence between
{{super_event}} and a SNEWS neutrino {{external_trigger}}.
{% endif %}
{{gracedb_id}} and a {% if SNEWS %}SNEWS supernova{% elif GRB %}{{grbmission(external_pipeline)}}{% endif %} {{propername(external_trigger)}}.
The {% if SNEWS %}neutrino{% elif GRB %}GRB{% endif %} trigger time is {{latency}} seconds {{beforeafter}} the GW candidate event.
{% if GRB %}
A search performed by the RAVEN pipeline found a temporal coincidence between
{{super_event_id}} and a GRB {{external_trigger}}. The false alarm rate for the time
coincidence is {{naturalfar(time_coinc_FAR)}}.
{% endif %}
{% if not include_initial_circ %}
This gravitational wave candidate is not significant enough on its own to produce a
public alert but its coincidence with the {% if SNEWS %}SNEWS neutrino{% endif %}{% if GRB %}GRB{% endif %} trigger increases its significance.
The event's properties can be found at this URL:
{{ gracedb_service_url }}{{ super_event_id }}
The estimated joint false alarm rate for the time coincidence is {{naturalfar(time_coinc_FAR)}}.
{% endif %}
{% if combined_skymap is defined %}
{% if combined_skymap is not defined %}
{% include 'userguide_conclusion.jinja2'%}
{% else %}
A combined skymap is also available:
* {{combined_skymap}}, the normalized product of the GW and GRB localizations.
The false alarm rate for the space-time coincidence is{% if space_time_coinc_FAR is not none %} {{naturalfar(space_time_coinc_FAR)}}{% else %} not available{% endif %}.
For the {{combined_skymap}} skymap, the {{cl}}% credible region is {{combined_skymap_greedy_area|round|int}} deg2.
{% if space_time_coinc_FAR is not none %}
Considering the overlap of the individual skymaps, the estimated joint false alarm rate for the spatial and temporal coincidence is {{naturalfar(space_time_coinc_FAR)}}.
{% else %}
The spatial and temporal coincidence is not yet available.
{% endif %}
{% include 'userguide_conclusion.jinja2'%}
{% endif %}
{% endfilter %}
SUBJECT: LIGO/Virgo {{gracedb_id}}: Identification of a {{external_pipeline}} Counterpart Candidate
{% from 'macros.jinja2' import grbmission, renamegroup, propername %}
{% if not change_significance_statement %}
SUBJECT: LIGO/Virgo {{gracedb_id}}: Identification of a GW {{renamegroup(group)}} candidate possibly associated with a {{grbmission(external_pipeline)}} trigger
{% else %}
SUBJECT: {{grbmission(external_pipeline)}} {{propername(external_trigger)}}: LIGO/Virgo identification of a possible GW {{renamegroup(group)}} counterpart, {{gracedb_id}}
{% endif %}
{% from 'macros.jinja2' import oxford_commas, evidence_for, probability,
naturalinstruments, naturalfar,
naturalclassifications,
citations %}
naturalclassifications, naturalotherpipelines,
citations, renamegroup %}
{% filter rewrap %}
The {{pipeline}} {{group}} analysis {% if pipeline|lower in citations %}
The {{pipeline}} {{renamegroup(group)}} analysis {% if pipeline|lower in citations %}
({{citations[pipeline|lower]}}){% endif %} identified candidate
{{gracedb_id}} during real-time processing of data from
{{naturalinstruments(instruments)}} at {{utctime}} UTC (GPS time: {{gpstime}}).
{% if other_pipelines|length > 0 %}
This candidate was also found by the {{naturalotherpipelines(other_pipelines)}}
analysis pipeline{% if other_pipelines|length > 1 %}s{% endif %}.
{% endif %}
{% if change_significance_statement %}
This gravitational wave candidate is not significant enough on its own to produce a public alert
but its coincidence with the {% if SNEWS %}SNEWS neutrino{% endif %}{% if GRB %}GRB{% endif %} trigger increases its significance.
{% else %}
{{gracedb_id}} is an event of interest because its false alarm rate, as
determined by the online analysis, is {{naturalfar(far)}}. The event's
properties can be found at this URL:
determined by the online analysis, is {{naturalfar(far)}}.
{% endif %}
The event's properties can be found at this URL:
{{ gracedb_service_url }}{{ gracedb_id }}
{% if classifications|length > 0 %}
The classification of the signal, in order of descending confidence,
The classification of the signal, in order of descending probability,
is {{naturalclassifications(classifications)}}.
{% endif %}
......@@ -32,16 +41,21 @@ masses and spins inferred from the signal, there is
{% endif %}
{% if skymaps|length == 0 %}
No{% else %}{{ skymaps|length|apnumber|capitalize }}{% endif %} sky map{% if skymaps|length == 1 %} is{% else %}s are{% endif %} available at this time{% if skymaps|length > 0 %} and can be retrieved from the GraceDB event page:{% else %}.{% endif %}
No{% else %}{{ skymaps|length|apnumber|capitalize }}{% endif %} skymap{% if skymaps|length == 1 %} is{% else %}s are{% endif %} available at this time{% if skymaps|length > 0 %} and can be retrieved from the GraceDB event page:{% else %}.{% endif %}
{% for skymap in skymaps %}
* {{skymap.filename}}, an {% if skymap.alert_type == 'initial' %}initial{% else %}updated{% endif %} localization generated by {{skymap.pipeline}},
distributed via GCN notice about {{skymap.latency|naturaldelta}} after the event
{% endfor %}
{% if include_ellipse %}
For the {{preferred_skymap}} sky map, the {{cl}}% credible region is well
fit by an ellipse with an area of {{ellipse_area|round|int}} deg2 described
{% if skymaps|length != 0 %}
The preferred skymap at this time is {{preferred_skymap}}.
{% endif %}
For the {{preferred_skymap}} skymap, the {{cl}}% credible region is
{% if not include_ellipse %}
{{greedy_area|round|int}} deg2.
{% else %}
well fit by an ellipse with an area of {{ellipse_area|round|int}} deg2 described
by the following DS9 region (right ascension, declination, semi-major axis,
semi-minor axis, position angle of the semi-minor axis):
icrs; ellipse(
......
......@@ -62,6 +62,16 @@ Observatory)".
{%- endmacro %}
Macro to transform a list of other GW analysis pipelines like ['gstlal', 'mbtaonline', 'pycbc']
to a natural-language list like "gstlal, mbtaonline, and pycbc".
{%- macro naturalotherpipelines(other_pipelines) -%}
{% call(other_pipeline) oxford_commas(other_pipelines) %}
{{other_pipeline}}
{%- endcall %}
{%- endmacro -%}
Macro to format FARs using natural-language time, capped at 1/100 years.
{% macro naturalfar(far) %}
......@@ -69,7 +79,7 @@ Macro to format FARs using natural-language time, capped at 1/100 years.
{% if far * max_ifar < 1 %}
less than one in {{max_ifar|naturaldelta}}
{%- else %}
{{'%.3g'|format(far)}} Hz or about one in {{(1 / far)|naturaldelta}}
{{'%.3g'|format(far)}} Hz, or about one in {{(1 / far)|naturaldelta}}
{%- endif %}
{%- endmacro %}
......@@ -89,6 +99,43 @@ terrestrial
{%- endmacro %}
Macro to replace jargon terms CBC and Burst.
{%- macro renamegroup(group) -%}
{%- if group|lower == 'cbc' -%}
binary merger
{%- elif group|lower == 'burst' -%}
unmodeled transient
{%- else -%}
{{group}}
{%- endif -%}
{%- endmacro -%}
Macro to include which mission reported the GRB.
{%- macro grbmission(external_pipeline) -%}
{%- if external_pipeline|lower == 'fermi' -%}
Fermi GBM
{%- elif external_pipeline|lower == 'swift' -%}
Swift BAT
{%- else -%}
{{external_pipeline}}
{%- endif -%}
{%- endmacro -%}
Macro to include the word `trigger' or not when referring to external_trigger.
{%- macro propername(external_trigger) -%}
{%- if 'grb' in external_trigger|lower -%}
{{external_trigger}}
{%- else -%}
trigger with ID {{external_trigger}}
{%- endif -%}
{%- endmacro -%}
Dictionary of common citations.
{% set citations = {'pycbc': 'Nitz et al. arXiv:1705.01513 (2017); '
......@@ -96,5 +143,6 @@ Dictionary of common citations.
'Dal Canton et al. PRD 90, 082004 (2014)',
'mbtaonline': 'Adams et al. CQG 33, 175012 (2016)',
'gstlal': 'Messick et al. PRD 95, 042001 (2017)',
'spiir': 'Hooper et al. PRD 86, 024012 (2012)',
'cwb': 'Klimenko et al. PRD 93, 042004 (2016)',
'lib': 'Lynch et al. PRD 95, 104046 (2017)'} %}
SUBJECT: LIGO/Virgo {{gracedb_id}}: {{subject}} of a GW {{group}} Candidate
{% from 'macros.jinja2' import renamegroup %}
SUBJECT: LIGO/Virgo {{gracedb_id}}: {{subject}} of a GW {{renamegroup(group)}} candidate
{%- filter rewrap -%}
Updates on our analysis of this event will be sent as they become available.
For further information about analysis methodology and the contents of this
alert, refer to the LIGO/Virgo Public Alerts User Guide
<https://emfollow.docs.ligo.org/userguide/>.
......
{
"graceid": "E1234",
"gpstime": 1214190502.74,
"gpstime": 1214190503.74,
"pipeline": "Swift",
"group": "External",
"extra_attributes":
......
{
"graceid": "M2468",
"gpstime": 1214190502.740928,
"pipeline": "pycbc",
"group": "CBC",
"extra_attributes": {
"SingleInspiral": [
{
"mtotal": 2.698247,
"search": "tmpltbank",
"chisq_dof": 1,
"end_time_gmst": 42549.08849574,
"f_final": 2047.0,
"chisq": 0.98581231,
"snr": 9.7492933,
"Gamma3": 154.76799,
"coa_phase": -2.8307292,
"eff_distance": 219.40491,
"mchirp": 1.1738826,
"Gamma5": 338.51791,
"Gamma4": -212.5316,
"mass1": 1.3884079,
"Gamma2": 6774.3867,
"Gamma1": -3255.4507,
"mass2": 1.309839,
"Gamma0": 246044.5,
"tau2": 3.6856861,
"tau3": 1.945289,
"tau0": 92.690048,
"eta": 0.24978803,
"psi0": 1867258.0,
"end_time": 1214190502,
"tau4": 0.090743333,
"psi3": -3918.8201,
"template_duration": 94.5259213794174,
"sigmasq": 4575504.00168479,
"end_time_ns": 734325847,
"ifo": "L1",
"ttotal": 94.521187,
"channel": "GAUSSIAN_PLUS_INJECTIONS"
},
{
"mtotal": 2.698247,
"search": "tmpltbank",
"chisq_dof": 1,
"end_time_gmst": 42549.0884962214,
"f_final": 2047.0,
"chisq": 0.90193468,
"snr": 12.316427,
"Gamma3": 154.76799,
"coa_phase": -0.074612953,
"eff_distance": 173.60532,
"mchirp": 1.1738826,
"Gamma5": 338.51791,
"Gamma4": -212.5316,
"mass1": 1.3884079,
"Gamma2": 6774.3867,
"Gamma1": -3255.4507,
"mass2": 1.309839,
"Gamma0": 246044.5,
"tau2": 3.6856861,
"tau3": 1.945289,
"tau0": 92.690048,
"eta": 0.24978803,
"psi0": 1867258.0,
"end_time": 1214190502,
"tau4": 0.090743333,
"psi3": -3918.8201,
"template_duration": 94.5259213794174,
"sigmasq": 4571887.19268266,
"end_time_ns": 740927606,
"ifo": "H1",
"ttotal": 94.521187,
"channel": "GAUSSIAN_PLUS_INJECTIONS"
}
],
"CoincInspiral": {
"false_alarm_rate": 2.52880622491428e-07,
"mchirp": 1.17388260364532,
"minimum_duration": null,
"mass": 2.69824695587158,
"end_time": 1214190502,
"snr": 15.708058445104,
"end_time_ns": 740927606,
"combined_far": 9.1106993648613e-7,
"ifos": "H1,L1"
}
},
"links": {
"neighbors": "https://gracedb-dev1.ligo.org/api/events/M2468/neighbors/",
"files": "https://gracedb-dev1.ligo.org/api/events/M2468/files/",
"log": "https://gracedb-dev1.ligo.org/api/events/M2468/log/",
"tags": "https://gracedb-dev1.ligo.org/api/events/M2468/tag/",
"self": "https://gracedb-dev1.ligo.org/api/events/M2468",
"labels": "https://gracedb-dev1.ligo.org/api/events/M2468/labels/",
"emobservations": "https://gracedb-dev1.ligo.org/api/events/M2468/emobservation/"
},
"created": "2018-06-28 03:08:36 UTC",
"far": 9.1106993648613e-7,
"instruments": "H1,L1",
"labels": [],
"search": "MDC",
"nevents": 2,
"superevent": "S180628g",
"submitter": "leo.singer@LIGO.ORG",
"offline": false,
"likelihood": 2.69725974901838e+25,
"far_is_upper_limit": false
}
{
"coinc.xml": "https://gracedb-dev1.ligo.org/api/events/M2468/files/coinc.xml",
"initial.data": "https://gracedb-dev1.ligo.org/api/events/M2468/files/initial.data",
"initial.data,0": "https://gracedb-dev1.ligo.org/api/events/M2468/files/initial.data,0",
"event.log,0": "https://gracedb-dev1.ligo.org/api/events/M2468/files/event.log,0",
"psd.xml.gz,0": "https://gracedb-dev1.ligo.org/api/events/M2468/files/psd.xml.gz,0",
"event.log": "https://gracedb-dev1.ligo.org/api/events/M2468/files/event.log",
"bayestar.fits.gz,0": "https://gracedb-dev1.ligo.org/api/events/M2468/files/bayestar.fits.gz,0",
"psd.xml.gz": "https://gracedb-dev1.ligo.org/api/events/M2468/files/psd.xml.gz",
"coinc.xml,0": "https://gracedb-dev1.ligo.org/api/events/M2468/files/coinc.xml,0",
"bayestar.fits.gz": "https://gracedb-dev1.ligo.org/api/events/M2468/files/bayestar.fits.gz",
"p_astro.json": "https://gracedb-dev1.ligo.org/api/events/M2468/files/p_astro.json"
}
{
"BNS": 0.7827870526188024,
"BBH": 0.0,
"NSBH": 0.0,
"Terr": 0.21721294733807747
}
\ No newline at end of file
{
"graceid": "M5678",
"gpstime": 1214190502.740928,
"pipeline": "gstlal",
"pipeline": "MBTAOnline",
"group": "CBC",
"extra_attributes": {
"SingleInspiral": [
......
......@@ -7,7 +7,7 @@
"t_0": 1214190502.74,
"t_end": 1214190503.74,
"gw_events": [
"M1234"
"M1234", "M5678", "M2468"
],
"em_events": [
"E1234"
......
......@@ -63,10 +63,10 @@ def test_compose(mock_gracedb):
main(['--service', 'https://gracedb.invalid/api/', 'compose', 'S1234'])
def test_compose_mailto(mock_gracedb, mock_webbrowser_open):
main(['--service', 'https://gracedb.invalid/api/', 'compose',
'--mailto', 'S1234'])
assert mock_webbrowser_open.called_once()
# def test_compose_mailto(mock_gracedb, mock_webbrowser_open):
# main(['--service', 'https://gracedb.invalid/api/', 'compose',
# '--mailto', 'S1234'])
# assert mock_webbrowser_open.called_once()
def test_RAVEN_with_initial_circular(mock_gracedb):
......@@ -74,9 +74,9 @@ def test_RAVEN_with_initial_circular(mock_gracedb):
'S1234'])
def test_RAVEN_without_initial_circular(mock_gracedb):
main(['--service', 'https://gracedb.invalid/api/', 'compose_RAVEN',
'S5678'])
# def test_RAVEN_without_initial_circular(mock_gracedb):
# main(['--service', 'https://gracedb.invalid/api/', 'compose_RAVEN',
# 'S5678'])
def test_emcoinc(mock_gracedb):
......
__version__ = '0.0.16.dev0'
__version__ = '0.0.18'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment