Coverage for pesummary/gw/cli/parser.py: 97.1%
68 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-05-02 08:42 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-05-02 08:42 +0000
1# Licensed under an MIT style license -- see LICENSE.md
3from ...core.cli.parser import ArgumentParser as _ArgumentParser
4from ...core.cli.actions import DictionaryAction, DeprecatedStoreTrueAction
6__author__ = ["Charlie Hoy <charlie.hoy@ligo.org>"]
9class ArgumentParser(_ArgumentParser):
10 """Extension of the pesummary.core.cli.parser.ArgumentParser object to handle
11 gw specific command line arguments.
13 Properties
14 ----------
15 fallback_options: dict
16 dictionary of default kwargs
17 pesummary_options: dict
18 dictionary giving pesummary options
19 command_line: str
20 command line run
21 command_line_arguments: list
22 list giving command line arguments
23 dynamic_argparse: list
24 list of dynamic argparse functions that you wish to add to the
25 argparse.Namespace object
26 """
27 @property
28 def dynamic_argparse(self):
29 return [
30 add_dynamic_PSD_to_namespace,
31 add_dynamic_calibration_to_namespace
32 ]
34 @property
35 def gw_options(self):
36 parser = ArgumentParser()
37 parser.add_known_options_to_parser_from_key(parser, "gw")
38 parser.add_known_options_to_parser_from_key(parser, "remnant")
39 opts = [i.dest for i in vars(parser)["_actions"]]
40 defaults = [i.default for i in vars(parser)["_actions"]]
41 return opts, defaults
43 def _pesummary_options(self):
44 core_options = super(ArgumentParser, self)._pesummary_options()
45 options = core_options.copy()
46 gw_options = {
47 "--disable_remnant": {
48 "action": "store_true",
49 "default": False,
50 "help": (
51 "Prevent remnant quantities from being calculated when the "
52 "conversions module is used"
53 ),
54 "key": "remnant",
55 },
56 "--force_BBH_remnant_computation": {
57 "default": False,
58 "action": "store_true",
59 "help": (
60 "Use BBH fits to calculate remnant quantities for systems "
61 "that include tidal deformability parameters"
62 ),
63 "key": "remnant",
64 },
65 "--force_BH_spin_evolution": {
66 "default": False,
67 "action": "store_true",
68 "help": (
69 "Use BH spin evolution methods to evolve spins in systems "
70 "that include tidal deformability parameters"
71 ),
72 "key": "remnant",
73 },
74 "--evolve_spins": {
75 "dest": "evolve_spins_forwards",
76 "action": DeprecatedStoreTrueAction(
77 new_option="--evolve_spins_forwards"
78 ),
79 "help": (
80 "Evolve the spins up to the Schwarzschild ISCO frequency "
81 "for remnant fits evaluation"
82 ),
83 "default": False,
84 "key": "remnant",
85 },
86 "--evolve_spins_forwards": {
87 "action": "store_true",
88 "help": (
89 "Evolve the spins up to the Schwarzschild ISCO frequency "
90 "for remnant fits evaluation"
91 ),
92 "default": False,
93 "key": "remnant",
94 },
95 "--evolve_spins_backwards": {
96 "nargs": "?",
97 "dest": "evolve_spins_backwards",
98 "choices": ["precession_averaged", "hybrid_orbit_averaged"],
99 "default": False,
100 "help": (
101 "Method to use when evolving spins backwards to infinite "
102 "separation. Default 'precession_averaged'."
103 ),
104 "key": "remnant",
105 },
106 "--NRSur_fits": {
107 "nargs": "?",
108 "dest": "NRSur_fits",
109 "default": False,
110 "help": (
111 "The NRSurrogate you wish to use to calculate the remnant "
112 "quantities from your posterior samples. If not passed, "
113 "the average NR fits are used"
114 ),
115 "key": "remnant",
116 },
117 "--waveform_fits": {
118 "action": "store_true",
119 "default": False,
120 "help": (
121 "Use the provided approximant (either from command line or "
122 "stored in the result file) to calculate the remnant "
123 "quantities from your posterior samples. If not passed, "
124 "the average NR fits are used"
125 ),
126 "key": "remnant",
127 },
128 "--approximant": {
129 "dest": "approximant",
130 "help": "waveform approximant used to generate samples",
131 "nargs": "+",
132 "short": "-a",
133 "key": "gw",
134 },
135 "--sensitivity": {
136 "action": "store_true",
137 "default": False,
138 "help": "generate sky sensitivities for HL, HLV",
139 "key": "gw",
140 },
141 "--gracedb": {
142 "dest": "gracedb",
143 "help": "gracedb of the event",
144 "key": "gw",
145 },
146 "--gracedb_server": {
147 "dest": "gracedb_server",
148 "help": "service url to use when accessing gracedb",
149 "key": "gw",
150 },
151 "--gracedb_data": {
152 "dest": "gracedb_data",
153 "nargs": "+",
154 "default": ["t_0", "far", "created"],
155 "help": (
156 "data you wish to download from gracedb and store in the "
157 "metafile"
158 ),
159 "key": "gw",
160 },
161 "--psd": {
162 "dest": "psd",
163 "action": DictionaryAction,
164 "help": "psd files used",
165 "nargs": "+",
166 "default": {},
167 "key": "gw",
168 },
169 "--{}_psd": {
170 "dest": "example_psd",
171 "metavar": "IFO:PATH_to_PSD.dat",
172 "help": (
173 "psd files used for a specific label. '{}' should be "
174 "replaced with the label of interest. For example "
175 "--IMRPhenomPv3_psd H1:IF0_psd.dat"
176 ),
177 "key": "gw",
178 },
179 "--calibration": {
180 "dest": "calibration",
181 "help": "files for the calibration envelope",
182 "nargs": "+",
183 "default": {},
184 "action": DictionaryAction,
185 "key": "gw",
186 },
187 "--{}_calibration": {
188 "dest": "example_calibration",
189 "metavar": "IFO:PATH_to_CAL.txt",
190 "help": (
191 "calibration files used for a specific label. '{}' should "
192 "be replaced with the label of interest. For example "
193 "--IMRPhenomPv3_calibration H1:IF0_cal.dat"
194 ),
195 "key": "gw",
196 },
197 "--trigfile": {
198 "dest": "inj_file",
199 "help": "xml file containing the trigger values",
200 "nargs": "+",
201 "key": "gw",
202 },
203 "--gwdata": {
204 "dest": "gwdata",
205 "help": "channels and paths to strain cache files",
206 "action": DictionaryAction,
207 "metavar": "CHANNEL:CACHEFILE or PICKLEFILE",
208 "nargs": "+",
209 "key": "gw",
210 },
211 "--multi_threading_for_skymap": {
212 "action": "store_true",
213 "default": False,
214 "help": (
215 "use multi-threading to speed up generation of ligo.skymap"
216 ),
217 "key": "gw"
218 },
219 "--nsamples_for_skymap": {
220 "dest": "nsamples_for_skymap",
221 "help": (
222 "The number of samples used to generate the ligo.skymap. "
223 "These samples will be randomly drawn from the posterior "
224 "distributions"
225 ),
226 "key": "gw",
227 },
228 "--calculate_multipole_snr": {
229 "action": "store_true",
230 "default": False,
231 "help": (
232 "Calculate the SNR in the (ell, m) = [(2, 1), (3, 3), "
233 "(4, 4)] subdominant multipoles based on the posterior "
234 "samples"
235 ),
236 "key": "gw",
237 },
238 "--calculate_precessing_snr": {
239 "action": "store_true",
240 "default": False,
241 "help": (
242 "Calculate the precessing SNR based on the posterior "
243 "samples"
244 ),
245 "key": "gw",
246 },
247 "--psd_default": {
248 "dest": "psd_default",
249 "default": "aLIGOZeroDetHighPower",
250 "help": (
251 "The PSD to use for conversions when no psd file is "
252 "provided. Default aLIGOZeroDetHighPower"
253 ),
254 "key": "gw",
255 },
256 "--f_low": {
257 "dest": "f_low",
258 "nargs": "+",
259 "help": "Low frequency cutoff used to generate the samples",
260 "key": "gw",
261 },
262 "--f_ref": {
263 "dest": "f_ref",
264 "help": "Reference frequency used to generate the samples",
265 "nargs": "+",
266 "key": "gw",
267 },
268 "--f_final": {
269 "dest": "f_final",
270 "nargs": "+",
271 "type": float,
272 "help": (
273 "Final frequency to use when calculating the precessing snr"
274 ),
275 "key": "gw"
276 },
277 "--delta_f": {
278 "dest": "delta_f",
279 "help": (
280 "Difference in frequency samples when calculating the "
281 "precessing snr"
282 ),
283 "nargs": "+",
284 "type": float,
285 "key": "gw",
286 },
287 "--no_ligo_skymap": {
288 "action": "store_true",
289 "default": False,
290 "help": "do not generate a skymap with ligo.skymap",
291 "key": "gw",
292 },
293 "--gw": {
294 "action": "store_true",
295 "help": "run with the gravitational wave pipeline",
296 "default": False,
297 "key": "gw",
298 },
299 "--public": {
300 "action": "store_true",
301 "help": "generate public facing summary pages",
302 "default": False,
303 "key": "gw"
304 },
305 "--redshift_method": {
306 "dest": "redshift_method",
307 "help": "The method to use when estimating the redshift",
308 "choices": ["approx", "exact"],
309 "default": "approx",
310 "key": "gw",
311 },
312 "--cosmology": {
313 "dest": "cosmology",
314 "help": "The cosmology to use when calculating the redshift",
315 "default": "Planck15",
316 "key": "gw"
317 },
318 "--no_conversion": {
319 "action": "store_true",
320 "default": False,
321 "help": "Do not generate any conversions",
322 "key": "gw"
323 }
324 }
325 options.update(gw_options)
326 return options
328 def add_gw_group(self):
329 gw_group = self.add_argument_group(
330 "\n\n=====================================================\n"
331 "Options specific for gravitational wave results files\n"
332 "====================================================="
333 )
334 return self.add_known_options_to_parser_from_key(gw_group, "gw")
336 def add_remnant_group(self):
337 remnant_group = self.add_argument_group(
338 "Options specific for calculating the remnant properties\n"
339 "-------------------------------------------------------"
340 )
341 return self.add_known_options_to_parser_from_key(
342 remnant_group, "remnant"
343 )
345 def add_all_groups_to_parser(self):
346 super(ArgumentParser, self).add_all_groups_to_parser()
347 self.add_gw_group()
348 self.add_remnant_group()
351class TGRArgumentParser(ArgumentParser):
352 """Extension of the pesummary.gw.cli.parser.ArgumentParser object to handle
353 TGR specific command line arguments.
355 Properties
356 ----------
357 fallback_options: dict
358 dictionary of default kwargs
359 pesummary_options: dict
360 dictionary giving pesummary options
361 command_line: str
362 command line run
363 command_line_arguments: list
364 list giving command line arguments
365 dynamic_argparse: list
366 list of dynamic argparse functions that you wish to add to the
367 argparse.Namespace object
368 """
369 @property
370 def dynamic_argparse(self):
371 return [add_dynamic_tgr_kwargs_to_namespace]
373 def _pesummary_options(self):
374 TESTS = ["imrct"]
375 _options = super(TGRArgumentParser, self)._pesummary_options()
376 options = {
377 "--test": {
378 "short": "-t",
379 "help": (
380 "What test do you want to run? Currently only supports "
381 "{}".format(", ".join(TESTS))
382 ),
383 "required": True,
384 "choices": TESTS,
385 },
386 "--{test}_kwargs": {
387 "dest": "example_test_kwargs",
388 "help": (
389 "Kwargs you wish to use when postprocessing the results. "
390 "Kwargs should be provided as a dictionary 'kwarg:value'. "
391 "For example `--imrct_kwargs N_bins:201 multi_process:4` "
392 "would pass the kwargs N_bins=201, multi_process=4 to the "
393 "IMRCT function. The test name '{test}' should match the "
394 "test provided with the --test flag"
395 ),
396 },
397 "--labels": {
398 "help": (
399 "Labels used to distinguish runs. The label format is "
400 "dependent on the TGR test you wish to use. For the IMRCT "
401 "test, labels need to be inspiral and postinspiral if "
402 "analysing a single event or {label1}:inspiral,"
403 "{label1}:postinspiral,{label2}:inspiral,"
404 "{label2}:postinspiral,... if analysing two or more events "
405 "(where label1/label2 is a unique string to distinguish "
406 "files from a single event). If a metafile is provided, "
407 "labels need to be {inspiral_label}:inspiral "
408 "{postinspiral_label}:postinspiral where inspiral_label "
409 "and postinspiral_label are the pesummary labels for the "
410 "inspiral and postinspiral analyses respectively."
411 ),
412 "nargs": "+",
413 },
414 "--cutoff_frequency": {
415 "type": float,
416 "nargs": "+",
417 "help": (
418 "Cutoff Frequency for IMRCT. Overrides any cutoff "
419 "frequency present in the supplied files. The supplied "
420 "cutoff frequency will only be used as metadata and "
421 "does not affect the cutoff frequency used in the "
422 "analysis. If only one number is supplied, the inspiral "
423 "maximum frequency and the postinspiral maximum frequency "
424 "are set to the same number. If a list of length 2 is "
425 "supplied, this assumes that the one corresponding to the "
426 "inspiral label is the maximum frequency for the inspiral "
427 "and that corresponding to the postinspiral label is "
428 "the minimum frequency for the postinspiral"
429 )
430 },
431 "--links_to_pe_pages": {
432 "help": "URLs for PE results pages separated by spaces.",
433 "nargs": "+",
434 "default": [],
435 },
436 "--disable_pe_page_generation": {
437 "action": "store_true",
438 "help": (
439 "Disable PE page generation for the input samples. This "
440 "option is only relevant if no URLs for PE results pages "
441 "are provided using --links_to_pe_pages."
442 )
443 },
444 "--pe_page_options": {
445 "type": str,
446 "default": "",
447 "help": (
448 "Additional options to pass to 'summarypages' when "
449 "generating PE webpages. All options should be wrapped in "
450 "quotation marks like, --pe_page_options='--no_ligo_skymap "
451 "--nsamples 1000 --psd...'. See 'summarypages --help' for "
452 "details. These options are added to base executable: "
453 "'summarypages --webdir {} --samples {} --labels {} --gw'"
454 ),
455 },
456 "--make_diagnostic_plots": {
457 "action": "store_true",
458 "help": "Make extra diagnostic plots"
459 }
460 }
461 extra_options = [
462 "--webdir", "--approximant", "--evolve_spins_forwards", "--f_low",
463 "--samples"
464 ]
465 for key in extra_options:
466 options[key] = _options[key]
467 return options
470def add_dynamic_argparse(
471 existing_namespace, pattern, example="--{}_psd", default={},
472 nargs='+', action=DictionaryAction, command_line=None
473):
474 """Add a dynamic argparse argument and add it to an existing
475 argparse.Namespace object
477 Parameters
478 ----------
479 existing_namespace: argparse.Namespace
480 existing namespace you wish to add the dynamic arguments too
481 pattern: str
482 generic pattern for customg argparse. For example '--*_psd'
483 example: str, optional
484 example string to demonstrate usage
485 default: obj, optional
486 the default argument for the dynamic argparse object
487 nargs: str
488 action: argparse.Action
489 argparse action to use for the dynamic argparse
490 command_line: str, optional
491 command line you wish to pass. If None, command line taken from
492 sys.argv
493 """
494 import fnmatch
495 import collections
496 import argparse
497 if command_line is None:
498 from pesummary.utils.utils import command_line_arguments
499 command_line = command_line_arguments()
500 commands = fnmatch.filter(command_line, pattern)
501 duplicates = [
502 item for item, count in collections.Counter(commands).items() if
503 count > 1
504 ]
505 if example in commands:
506 commands.remove(example)
507 if len(duplicates) > 0:
508 raise Exception(
509 "'{}' has been repeated. Please give a unique argument".format(
510 duplicates[0]
511 )
512 )
513 parser = argparse.ArgumentParser()
514 for i in commands:
515 parser.add_argument(
516 i, help=argparse.SUPPRESS, action=action, nargs=nargs,
517 default=default
518 )
519 args, unknown = parser.parse_known_args(args=command_line)
520 existing_namespace.__dict__.update(vars(args))
521 return args, unknown
524def add_dynamic_PSD_to_namespace(existing_namespace, command_line=None):
525 """Add a dynamic PSD argument to the argparse namespace
527 Parameters
528 ----------
529 existing_namespace: argparse.Namespace
530 existing namespace you wish to add the dynamic arguments too
531 command_line: str, optional
532 The command line which you are passing. Default None
533 """
534 return add_dynamic_argparse(
535 existing_namespace, "--*_psd", command_line=command_line
536 )
539def add_dynamic_calibration_to_namespace(existing_namespace, command_line=None):
540 """Add a dynamic calibration argument to the argparse namespace
542 Parameters
543 ----------
544 existing_namespace: argparse.Namespace
545 existing namespace you wish to add the dynamic arguments too
546 command_line: str, optional
547 The command line which you are passing. Default None
548 """
549 return add_dynamic_argparse(
550 existing_namespace, "--*_calibration", example="--{}_calibration",
551 command_line=command_line
552 )
555def add_dynamic_tgr_kwargs_to_namespace(existing_namespace, command_line=None):
556 """Add a dynamic TGR kwargs argument to the argparse namespace
558 Parameters
559 ----------
560 existing_namespace: argparse.Namespace
561 existing namespace you wish to add the dynamic arguments to
562 command_line: str, optional
563 The command line which you are passing. Default None
564 """
565 return add_dynamic_argparse(
566 existing_namespace, "--*_kwargs", example="--{}_kwargs",
567 command_line=command_line
568 )