diff --git a/ligo/followup_advocate/__init__.py b/ligo/followup_advocate/__init__.py index 1b620cbb78a38032550b77a7ad7a8e3024e3c5a0..f13f50d30d3b09aa1c4b98f174b78fbb03ebc728 100644 --- a/ligo/followup_advocate/__init__.py +++ b/ligo/followup_advocate/__init__.py @@ -232,6 +232,66 @@ def compose_RAVEN(gracedb_id, authors=(), return '{0}\n{1}'.format(subject, body) +def compose_emcoinc(gracedb_id, authors=(), + service=rest.DEFAULT_SERVICE_URL, client=None): + """Compose EM_COINC GCN Circular draft""" + + path_output_X = ( + '/home/grb.exttrig/Online/O3/processor/runs/X/GRB{}/' + 'auto_web/{}_online_openbox_summary.txt' + ).format(gracedb_id, gracedb_id) # true one? + path_output_X = ( + '/home/grb.exttrig/Online/O2/processor/runs/X/GRBE298784/' + 'auto_web/E298784_online_openbox_summary.txt' + ) # Michal example + path_output_CBC = 'need to be defined' + + if os.path.exists(path_output_X): + output_X = open(path_output_X, 'r') + for line in output_X: + infos_X = line.strip('\n').split(' ') + if infos_X[2] == 'sgc150q9': + UL50 = infos_X[3] + # need to build a function to convert UL50 to exclusion distance ? + + if client is None: + client = rest.GraceDb(service) + super_event = client.superevent(gracedb_id).json() + preferred_event_id = super_event['preferred_event'] + preferred_event = client.event(preferred_event_id).json() + + pipeline = [] + if 'pycbc' in preferred_event['pipeline']: + pipeline += ['CBC pipeline (PyGRB)'] + elif 'CWB' in preferred_event['pipeline']: + pipeline += ['Burst pipeline (X-pipeline)'] + + CBC_FAR = None + Burst_FAR = None + if 'CBC pipeline (PyGRB)' in pipeline: + CBC_FAR = preferred_event['far'] + elif 'Burst pipeline (X-pipeline)' in pipeline: + Burst_FAR = preferred_event['far'] + + kwargs = dict( + pipelines=pipeline, + exclusion=False, # or True + GRB_id='XXXXXX - XXXX128XX', + CITE_GCN='(Klebesadel, et al., GCN Circ. XXXXX)', + NSNS_Mpc='XXX', + NSBH_Mpc='XXX', + Burst_Mpc=12, + CBC_FAR=CBC_FAR, + Burst_FAR=Burst_FAR) + subject = ( + env.get_template('em_coinc_subject.jinja2').render(**kwargs) + .strip()) + body = ( + env.get_template('em_coinc_circular.jinja2').render(**kwargs) + .strip()) + return '{0}\n{1}'.format(subject, body) + + def compose_retraction(gracedb_id, authors=(), service=rest.DEFAULT_SERVICE_URL, client=None): """Compose GCN retraction circular""" diff --git a/ligo/followup_advocate/templates/em_coinc_circular.jinja2 b/ligo/followup_advocate/templates/em_coinc_circular.jinja2 new file mode 100644 index 0000000000000000000000000000000000000000..d5b0f996b7e56586aa156d9736de3e5e2c676e0d --- /dev/null +++ b/ligo/followup_advocate/templates/em_coinc_circular.jinja2 @@ -0,0 +1,144 @@ +{%- include 'authors.jinja2' %} + +{# case of exclusion -#} +{% if exclusion %} +{% for pipeline_name in pipelines -%} +{% if loop.length == 1 or not loop.last %}The online, triggered +{%- if loop.length > 1 %}{{" "}}CBC pipeline (PyGRB) and triggered Burst pipeline +(X-pipeline) did not find a candidate GW event associated with GRB +{{GRB_id}} {{CITE_GCN}}.{{"\n"}} + +{%- else -%} {{" "+pipeline_name}} did not find a candidate GW +event associated with GRB {{GRB_id}} {{CITE_GCN}}. +{% endif %} + +Preliminary exclusion distances with the below assumptions: +{%- endif %} +{% endfor -%} + +{% for pipeline_name in pipelines %} + +{%- if loop.length == 1 -%} + +{%- if 'CBC pipeline (PyGRB)' in pipelines %} + + +NS-NS: {{NSNS_Mpc}} Mpc, 90% CL +NS-BH: {{NSBH_Mpc}} Mpc, 90% CL + +Exclusion distance from a Gaussian distribution of mass, uniform +distribution of spin and inclination. NS-NS: a Gaussian distribution +of component masses 1-3 M_sun, and uniform distributions of spin 0-0.4 +and inclination angle up to a maximum of 30 deg. NS-BH: as above for +NS; BH mass and spin distributions 3-15 M_sun, 0-0.98. + +{%- elif 'Burst pipeline (X-pipeline)' in pipelines %} + + +Burst (model-dependent): {{Burst_Mpc}} Mpc, 90% CL + +Exclusion distance from an ad hoc model with a circularly polarized, +sine-Gaussian waveform with Q-factor = 9 and center frequency = 150 Hz, +assuming E_GW = 10^-2 M_sun c^2 of energy emitted as GWs. Exclusion +distance scales roughly as sqrt(E_GW). + +{%- endif -%} + +{%- elif loop.length > 1 -%} +{%- if not loop.last %} + + +NS-NS: {{NSNS_Mpc}} Mpc, 90% CL +NS-BH: {{NSBH_Mpc}} Mpc, 90% CL +Burst (model-dependent): {{Burst_Mpc}} Mpc, 90% CL + +For CBC, exclusion distance from a Gaussian distribution of mass, +uniform distribution of spin and inclination. NS-NS: a Gaussian +distribution of component masses 1-3 M_sun, and uniform distributions +of spin 0-0.4 and inclination angle up to a maximum of 30 deg. NS-BH: +as above for NS; BH mass and spin distributions 3-15 M_sun, 0-0.98. + +For Burst, exclusion distance from an ad hoc model with a circularly +polarized, sine-Gaussian waveform with Q-factor = 9 and center +frequency = 150 Hz, assuming E_GW = 10^-2 M_sun c^2 of energy emitted +as GWs. Exclusion distance scales roughly as sqrt(E_GW). +{%- endif -%} +{%- endif -%} {#- if loop.length == / > 1 -#} + +{%- endfor -%}{#- for pipeline_name in pipelines -#} + +{#- case of candidate identification -#} +{%- elif not exclusion %} +{% for pipeline_name in pipelines %} +{%- if loop.length == 1 or not loop.last %}The online, triggered + +{%- if loop.length > 1 -%}{{" "}}CBC pipeline (PyGRB) and triggered Burst +pipeline (X-pipeline) have + +{%- else -%}{{" "+pipeline_name}} has +{%- endif -%} +{{" "}}made a preliminary {%- if loop.length == 1 -%}{{"\n"}}{%- endif -%} +identification of a GW {% if not loop.length == 1 -%}{{"\n"}}{%- endif -%} +candidates associated with the time and sky position +{%- if loop.length == 1 -%}{{"\n"}}{%- endif %}of GRB +{%- if not loop.length == 1 -%}{{"\n"}}{%- endif -%} +{%- if loop.length == 1 -%}{{" "}}{%- endif %}{{GRB_id}} {{CITE_GCN}}. + +{% endif -%} + + +{%- endfor -%}{#- for pipeline_name in pipelines -#} + +{% for pipeline_name in pipelines %} + +{%- if loop.length == 1 -%} + +{%- if 'CBC pipeline (PyGRB)' in pipelines -%} + +The candidate is consistent with a binary coalescence with +False Alarm Probability of {{CBC_FAR}}. + +The False Alarm Probability is calculated by counting the fraction of +background trials containing an event with a greater detection statistic +than the loudest on-source event. The off-source trials are of 6 s +duration. + +An offline analysis is ongoing. Any significant updates will be provided +by a new Circular. + +{%- elif 'Burst pipeline (X-pipeline)' in pipelines -%} + +The candidate is an unmodeled GW transient with False Alarm Probability +of {{Burst_FAR}}. + +The False Alarm Probability is calculated by counting the fraction of +background trials containing an event with a greater detection statistic +than the loudest on-source event. The off-source trials are of 660 s +duration. + +An offline analysis is ongoing. Any significant updates will be provided +by a new Circular. + +{%- endif -%}{#- if loop.length == 1 -#} + +{% elif loop.length > 1 %} +{% if not loop.last %} +In PyGRB, the candidate is consistent with a binary coalescence with +False Alarm Probability of {{CBC_FAR}}. + +In X-pipeline, the candidate is an unmodeled GW transient with +False Alarm Probability of {{Burst_FAR}}. + +The False Alarm Probability is calculated by counting the fraction of +background trials containing an event with a greater detection statistic +than the loudest on-source event. The off-source trials are of 6 s +duration for CBC and 660 s duration for Burst. + +Offline analyses are ongoing. Any significant updates will be provided +by a new Circular. +{%- endif -%} +{%- endif -%} + +{%- endfor -%}{#- for pipeline_name in pipelines -#} + +{%- endif -%}{#- case of exclusion/indentification -#} \ No newline at end of file diff --git a/ligo/followup_advocate/templates/em_coinc_subject.jinja2 b/ligo/followup_advocate/templates/em_coinc_subject.jinja2 new file mode 100644 index 0000000000000000000000000000000000000000..e57533fa0ec11401c3f1bada50174ddf574796ba --- /dev/null +++ b/ligo/followup_advocate/templates/em_coinc_subject.jinja2 @@ -0,0 +1,8 @@ +{% if exclusion %} +SUBJECT: LIGO/Virgo GRB {{GRB_id}}: Non-detection in gravitational waves + +{% else -%} +SUBJECT: LIGO/Virgo GRB {{GRB_id}}: Identification of a possible +gravitational-wave counterpart + +{% endif %} diff --git a/ligo/followup_advocate/test/data/S1234/files/em_coinc.json b/ligo/followup_advocate/test/data/S1234/files/em_coinc.json new file mode 100644 index 0000000000000000000000000000000000000000..a1fcb644514c0c3c11c9ef81fe6bd5e300aedb80 --- /dev/null +++ b/ligo/followup_advocate/test/data/S1234/files/em_coinc.json @@ -0,0 +1,11 @@ +{ + "pipelines": ["CBC pipeline (PyGRB)","Burst pipeline (X-pipeline)"], + "exclusion": false, + "GRB_id": "XXXXXX - XXXX128XX", + "CITE_GCN": "(Klebesadel, et al., GCN Circ. XXXXX)", + "NSNS_Mpc": 40, + "NSBH_Mpc": 32, + "Burst_Mpc": 12, + "CBC_FAR": 1e-2, + "Burst_FAR": 1e-1 +} \ No newline at end of file diff --git a/ligo/followup_advocate/test/test_tool.py b/ligo/followup_advocate/test/test_tool.py index 0d09f90b400f8d6464a37b60f5d8979fae9123f2..c5f46fd28cff756a679d2b91161d187e5888dea7 100644 --- a/ligo/followup_advocate/test/test_tool.py +++ b/ligo/followup_advocate/test/test_tool.py @@ -79,6 +79,11 @@ def test_RAVEN_without_initial_circular(mock_gracedb): 'S5678']) +def test_emcoinc(mock_gracedb): + main(['--service', 'https://gracedb.invalid/api/', 'compose_emcoinc', + 'S1234']) + + def test_retraction(mock_gracedb): main(['--service', 'https://gracedb.invalid/api/', 'compose_retraction', 'S1234']) diff --git a/ligo/followup_advocate/tool.py b/ligo/followup_advocate/tool.py index 02203697d57811fbfb996ee6542799c639267108..1ed6a89b0f94749bfc9a7eb63f35fd5bf36dcc24 100644 --- a/ligo/followup_advocate/tool.py +++ b/ligo/followup_advocate/tool.py @@ -34,6 +34,9 @@ def main(args=None): cmd = add_command(followup_advocate.compose_RAVEN, parents=[authors]) cmd.add_argument('gracedb_id', metavar='G123456', help='GraceDB ID') + cmd = add_command(followup_advocate.compose_emcoinc, parents=[authors]) + cmd.add_argument('gracedb_id', metavar='G123456', help='GraceDB ID') + cmd = add_command(followup_advocate.compose_retraction, parents=[authors]) cmd.add_argument('gracedb_id', metavar='G123456', help='GraceDB ID')