Commit 02d7aa3a authored by Philippe Nguyen's avatar Philippe Nguyen
Browse files

resolve merge conflicts; debugged compose_emcoinc

parent 4615e0d3
Pipeline #50244 failed with stages
in 7 minutes and 11 seconds
......@@ -14,8 +14,8 @@ from ligo.skymap.io.fits import read_sky_map
from ligo.skymap.postprocess.ellipse import find_ellipse
from ligo.skymap.postprocess.find_injection import find_injection_moc
from jinja import env
from version import __version__ # noqa
from .jinja import env
from .version import __version__ # noqa
def authors(authors, service=rest.DEFAULT_SERVICE_URL):
......@@ -153,8 +153,6 @@ def compose(gracedb_id, authors=(), mailto=False,
return '{0}\n{1}'.format(subject, body)
<<<<<<< HEAD
<<<<<<< HEAD
def compose_RAVEN(gracedb_id, authors=(),
service=rest.DEFAULT_SERVICE_URL, client=None):
"""Compose EM_COINC RAVEN GCN Circular draft"""
......@@ -230,223 +228,69 @@ def compose_RAVEN(gracedb_id, authors=(),
.strip())
body = (
env.get_template('RAVEN_circular.jinja2').render(**kwargs)
=======
<<<<<<< HEAD
=======
=======
>>>>>>> 014a14bb2bde3ae36d03c0fce7f5e2c5e121fad6
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
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'
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)
table = client.event(gracedb_id).json()
pipeline = []
if 'pycbc' in table['pipeline']:
pipeline += ['CBC pipeline (PyGRB)']
elif 'CWB' in table['pipeline']:
pipeline += ['Burst pipeline (X-pipeline)']
elif pipeline == []:
pipeline = None
CBC_FAR=None
Burst_FAR=None
if 'CBC pipeline (PyGRB)' in pipeline:
CBC_FAR = table['far']
elif 'Burst pipeline (X-pipeline)' in pipeline:
Burst_FAR = table['far']
# kwargs = client.files(gracedb_id, 'em_coinc.json').json()
print(table.keys())
print(table)
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_RAVEN(gracedb_id, authors=(),
service=rest.DEFAULT_SERVICE_URL, client=None):
"""Compose EM_COINC GCN Circular draft"""
if client is None:
client = rest.GraceDb(service)
<<<<<<< HEAD
=======
<<<<<<< HEAD
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
table = client.event(gracedb_id).json()
# kwargs = client.files(gracedb_id, 'em_coinc.json').json()
print(table.keys())
print(table)
kwargs = dict(SNEWS=True,
GRB=True,
<<<<<<< HEAD
time_coinc_FAR=12,
combined_skymap=True,
space_time_coinc_FAR=13
)
=======
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_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'
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 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)
table = client.event(gracedb_id).json()
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 table['pipeline']:
if 'pycbc' in preferred_event['pipeline']:
pipeline += ['CBC pipeline (PyGRB)']
elif 'CWB' in table['pipeline']:
elif 'CWB' in preferred_event['pipeline']:
pipeline += ['Burst pipeline (X-pipeline)']
elif pipeline == []:
pipeline = None
CBC_FAR=None
Burst_FAR=None
CBC_FAR = None
Burst_FAR = None
if 'CBC pipeline (PyGRB)' in pipeline:
CBC_FAR = table['far']
CBC_FAR = preferred_event['far']
elif 'Burst pipeline (X-pipeline)' in pipeline:
Burst_FAR = table['far']
# kwargs = client.files(gracedb_id, 'em_coinc.json').json()
print(table.keys())
print(table)
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)
<<<<<<< HEAD
>>>>>>> 41fd8a2... added compose_emcoinc functionality
=======
def compose_RAVEN(gracedb_id, authors=(),
service=rest.DEFAULT_SERVICE_URL, client=None):
"""Compose EM_COINC GCN Circular draft"""
Burst_FAR = preferred_event['far']
if client is None:
client = rest.GraceDb(service)
=======
=======
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
table = client.superevent(gracedb_id).json()
print(table.keys())
print(table)
if 'EM_COINC' not in table['labels']:
return
for items in table['em_events']:
SNEWS=True
GRB=True
# kwargs = client.files(gracedb_id, 'em_coinc.json').json()
kwargs = dict(SNEWS=SNEWS,
GRB=GRB,
<<<<<<< HEAD
=======
>>>>>>> 014a14bb2bde3ae36d03c0fce7f5e2c5e121fad6
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
time_coinc_FAR=12,
combined_skymap=True,
space_time_coinc_FAR=13
)
<<<<<<< HEAD
>>>>>>> 40a5568... filling the template(not over)
=======
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
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 = (
<<<<<<< HEAD
env.get_template('em_coinc_circular.jinja2').render(**kwargs)
<<<<<<< HEAD
<<<<<<< HEAD
=======
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
>>>>>>> added compose_emcoinc functionality
.strip())
return '{0}\n{1}'.format(subject, body)
print(compose_RAVEN('G298045'))
=======
<<<<<<< HEAD
.strip())
return '{0}\n{1}'.format(subject, body)
<<<<<<< HEAD
>>>>>>> 41fd8a2... added compose_emcoinc functionality
=======
print(compose_RAVEN('G298045'))
>>>>>>> 40a5568... filling the template(not over)
=======
=======
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
env.get_template('RAVEN_circular.jinja2').render(**kwargs)
.strip())
return '{0}\n{1}'.format(subject, body)
print(compose_RAVEN('G299270'))
<<<<<<< HEAD
>>>>>>> 1130fe2... first step on the RAVEN circular
=======
>>>>>>> 014a14bb2bde3ae36d03c0fce7f5e2c5e121fad6
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
def compose_retraction(gracedb_id, authors=(),
service=rest.DEFAULT_SERVICE_URL, client=None):
......
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
=======
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
{% from 'macros.jinja2' import naturalfar %}
{% include 'authors.jinja2' %}
......@@ -38,38 +33,3 @@ The false alarm rate for the space-time coincidence is{% if space_time_coinc_FAR
{% include 'userguide_conclusion.jinja2'%}
{% endfilter %}
=======
<<<<<<< HEAD
{% include 'em_coinc_subject.jinja2' -%}
=======
>>>>>>> 1130fe2... first step on the RAVEN circular
=======
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
{%- include 'authors.jinja2' %}
{%- if SNEWS -%}
A search performed by the RAVEN pipeline found a temporal coincidence between
(Superevent) and a SNEWS neutrino (external trigger)
{%- endif %}
{% if GRB -%}
A search performed by the RAVEN pipeline found a temporal coincidence between
(Superevent) and a GRB (external trigger). The false alarm rate for the time
coincidence is {{time_coinc_FAR}}.
{%- endif %}
{% if combined_skymap -%}
A combined skymap is also available: {{url_combined_skymap}}.
The false alarm rate for the space-time coincidence is {{space_time_coinc_FAR}}
{%- endif -%}
<<<<<<< HEAD
>>>>>>> f555715... New EM_COINC specific circulars upon RAVEN coincidences; Fixes #12
=======
>>>>>>> 014a14bb2bde3ae36d03c0fce7f5e2c5e121fad6
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
{%- 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
<<<<<<< HEAD
<<<<<<< HEAD
{
"coinc.xml": "https://gracedb-dev1.ligo.org/api/events/S1234/files/coinc.xml",
"initial.data": "https://gracedb-dev1.ligo.org/api/events/S1234/files/initial.data",
......@@ -19,13 +17,3 @@
"coincidence_far.json": "https://gracedb-dev1.ligo.org/api/events/S1234/files/coincidence_far.json",
"bayestar-gbm.fits.gz": "https://gracedb-dev1.ligo.org/api/events/S1234/files/bayestar-gbm.fits.gz"
}
=======
{"coinc.xml": "https://gracedb-dev1.ligo.org/api/events/S1234/files/coinc.xml", "initial.data": "https://gracedb-dev1.ligo.org/api/events/S1234/files/initial.data", "initial.data,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/initial.data,0", "event.log,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/event.log,0", "psd.xml.gz,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/psd.xml.gz,0", "event.log": "https://gracedb-dev1.ligo.org/api/events/S1234/files/event.log", "bayestar.fits.gz,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/bayestar.fits.gz,0", "psd.xml.gz": "https://gracedb-dev1.ligo.org/api/events/S1234/files/psd.xml.gz", "coinc.xml,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/coinc.xml,0", "bayestar.fits.gz": "https://gracedb-dev1.ligo.org/api/events/S1234/files/bayestar.fits.gz", "LALInference.fits.gz": "https://gracedb-dev1.ligo.org/api/events/S1234/files/LALInference.fits.gz", "LALInference.fits.gz,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/LALInference.fits.gz,0", "S1234-1-Initial.xml": "https://gracedb-dev1.ligo.org/api/events/S1234/files/S1234-1-Initial.xml", "S1234-2-Update.xml": "https://gracedb-dev1.ligo.org/api/events/S1234/files/S1234-2-Update.xml", "source_classification.json": "https://gracedb-dev1.ligo.org/api/events/S1234/files/source_classification.json", "em_coinc.json": "https://gracedb-dev1.ligo.org/api/events/S1234/files/em_coinc.json"}
>>>>>>> added compose_emcoinc functionality
=======
{"coinc.xml": "https://gracedb-dev1.ligo.org/api/events/S1234/files/coinc.xml", "initial.data": "https://gracedb-dev1.ligo.org/api/events/S1234/files/initial.data", "initial.data,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/initial.data,0", "event.log,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/event.log,0", "psd.xml.gz,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/psd.xml.gz,0", "event.log": "https://gracedb-dev1.ligo.org/api/events/S1234/files/event.log", "bayestar.fits.gz,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/bayestar.fits.gz,0", "psd.xml.gz": "https://gracedb-dev1.ligo.org/api/events/S1234/files/psd.xml.gz", "coinc.xml,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/coinc.xml,0", "bayestar.fits.gz": "https://gracedb-dev1.ligo.org/api/events/S1234/files/bayestar.fits.gz", "LALInference.fits.gz": "https://gracedb-dev1.ligo.org/api/events/S1234/files/LALInference.fits.gz", "LALInference.fits.gz,0": "https://gracedb-dev1.ligo.org/api/events/S1234/files/LALInference.fits.gz,0", "S1234-1-Initial.xml": "https://gracedb-dev1.ligo.org/api/events/S1234/files/S1234-1-Initial.xml", "S1234-2-Update.xml": "https://gracedb-dev1.ligo.org/api/events/S1234/files/S1234-2-Update.xml", "source_classification.json": "https://gracedb-dev1.ligo.org/api/events/S1234/files/source_classification.json", "em_coinc.json": "https://gracedb-dev1.ligo.org/api/events/S1234/files/em_coinc.json"}
<<<<<<< HEAD
>>>>>>> 41fd8a2... added compose_emcoinc functionality
=======
>>>>>>> 014a14bb2bde3ae36d03c0fce7f5e2c5e121fad6
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
......@@ -69,8 +69,6 @@ def test_compose_mailto(mock_gracedb, mock_webbrowser_open):
assert mock_webbrowser_open.called_once()
<<<<<<< HEAD
<<<<<<< HEAD
def test_RAVEN_with_initial_circular(mock_gracedb):
main(['--service', 'https://gracedb.invalid/api/', 'compose_RAVEN',
'S1234'])
......@@ -81,26 +79,11 @@ def test_RAVEN_without_initial_circular(mock_gracedb):
'S5678'])
=======
=======
<<<<<<< HEAD
>>>>>>> 41fd8a2... added compose_emcoinc functionality
=======
>>>>>>> 014a14bb2bde3ae36d03c0fce7f5e2c5e121fad6
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
def test_emcoinc(mock_gracedb):
main(['--service', 'https://gracedb.invalid/api/', 'compose_emcoinc',
'S1234'])
<<<<<<< HEAD
>>>>>>> added compose_emcoinc functionality
=======
<<<<<<< HEAD
>>>>>>> 41fd8a2... added compose_emcoinc functionality
=======
>>>>>>> 014a14bb2bde3ae36d03c0fce7f5e2c5e121fad6
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
def test_retraction(mock_gracedb):
main(['--service', 'https://gracedb.invalid/api/', 'compose_retraction',
'S1234'])
......@@ -31,19 +31,10 @@ def main(args=None):
help='Open new message in default e-mail client [default: false]')
cmd.add_argument('gracedb_id', metavar='G123456', help='GraceDB ID')
<<<<<<< HEAD
<<<<<<< HEAD
cmd = add_command(followup_advocate.compose_RAVEN, parents=[authors])
=======
cmd = add_command(followup_advocate.compose_emcoinc, parents=[authors])
>>>>>>> added compose_emcoinc functionality
=======
cmd.add_argument('gracedb_id', metavar='G123456', help='GraceDB ID')
cmd = add_command(followup_advocate.compose_emcoinc, parents=[authors])
<<<<<<< HEAD
>>>>>>> 41fd8a2... added compose_emcoinc functionality
=======
>>>>>>> 014a14bb2bde3ae36d03c0fce7f5e2c5e121fad6
>>>>>>> 7abd548ef1a31d13e91dd89b29851a7b2512d462
cmd.add_argument('gracedb_id', metavar='G123456', help='GraceDB ID')
cmd = add_command(followup_advocate.compose_retraction, parents=[authors])
......
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