Coverage for pesummary/gw/webpage/main.py: 78.4%
379 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
3import os
4import numpy as np
6from pesummary.core.webpage.main import _WebpageGeneration as _CoreWebpageGeneration
7from pesummary.core.webpage.main import PlotCaption
8from pesummary.gw.file.standard_names import descriptive_names
9from pesummary.utils.utils import logger
10from pesummary import conf
12__author__ = ["Charlie Hoy <charlie.hoy@ligo.org>"]
15class CommandLineCaption(object):
16 """Class to handle generating the command line used to generate a plot and
17 a caption to describe the plot
19 Parameters
20 ----------
21 """
22 def __init__(self, command_line_arguments, samples=None):
23 self.args = command_line_arguments
24 self.samples = samples
25 self.executable = self.get_executable("summaryplots")
27 @staticmethod
28 def get_executable(executable):
29 """Return the path to an executable
31 Parameters
32 ----------
33 executable: str
34 the name of the executable you wish to find
35 """
36 from subprocess import check_output
38 path = check_output(["which", executable]).decode("utf-8").strip()
39 return path
41 @property
42 def command_line(self):
43 """Generate the command line used to generate the plot
44 """
45 return "{} {}".format(self.executable, " ".join(self.args))
47 @property
48 def caption(self):
49 """Make a caption to describe the plot
50 """
51 general_cli = ""
52 if "1d_histogram" in self.args[0]:
53 return self.histogram_caption()
54 if "skymap" in self.args[0]:
55 return self.skymap_caption()
56 return general_cli
58 def histogram_caption(self):
59 """Return a caption to describe the 1d histogram plot
60 """
61 args = self.args[0].split(" ")
62 parameter = args[args.index("--parameter") + 1]
63 general_cli = (
64 "1d histogram showing the posterior distribution for "
65 "{}.".format(parameter)
66 )
67 if parameter == "chi_p":
68 general_cli += (
69 " chi_p is the precession parameter and quantifies how much "
70 "precession there is in the system. It ranges from 0 to 1 "
71 "with 0 meaning there is no precession in the system and 1 "
72 "meaning there is maximal precession in the system."
73 )
74 if self.samples is not None:
75 general_cli += (
76 " The median of the distribution is {} with 90% confidence "
77 "interval {}".format(
78 np.round(self.samples.average(type="median"), 3),
79 [np.round(i, 3) for i in self.samples.credible_interval()]
80 )
81 )
82 return general_cli
84 def skymap_caption(self):
85 """Return a caption to describe the skymap plot
86 """
87 general_cli = (
88 "Skymap showing the possible location of the source of the "
89 "source of the gravitational waves"
90 )
93class _WebpageGeneration(_CoreWebpageGeneration):
94 """
95 """
96 def __init__(
97 self, webdir=None, samples=None, labels=None, publication=None,
98 user=None, config=None, same_parameters=None, base_url=None,
99 file_versions=None, hdf5=None, colors=None, custom_plotting=None,
100 pepredicates_probs=None, gracedb=None, approximant=None, key_data=None,
101 file_kwargs=None, existing_labels=None, existing_config=None,
102 existing_file_version=None, existing_injection_data=None,
103 existing_samples=None, existing_metafile=None, add_to_existing=False,
104 existing_file_kwargs=None, existing_weights=None, result_files=None,
105 notes=None, disable_comparison=False, pastro_probs=None, gwdata=None,
106 disable_interactive=False, publication_kwargs={}, no_ligo_skymap=False,
107 psd=None, priors=None, package_information={"packages": []},
108 mcmc_samples=False, external_hdf5_links=False, preliminary_pages=False,
109 existing_plot=None, disable_expert=False, analytic_priors=None
110 ):
111 self.pepredicates_probs = pepredicates_probs
112 self.pastro_probs = pastro_probs
113 self.gracedb = gracedb
114 self.approximant = approximant
115 self.file_kwargs = file_kwargs
116 self.publication = publication
117 self.publication_kwargs = publication_kwargs
118 self.result_files = result_files
119 self.gwdata = gwdata
120 self.no_ligo_skymap = no_ligo_skymap
121 self.psd = psd
122 self.priors = priors
124 super(_WebpageGeneration, self).__init__(
125 webdir=webdir, samples=samples, labels=labels,
126 publication=publication, user=user, config=config,
127 same_parameters=same_parameters, base_url=base_url,
128 file_versions=file_versions, hdf5=hdf5, colors=colors,
129 custom_plotting=custom_plotting,
130 existing_labels=existing_labels, existing_config=existing_config,
131 existing_file_version=existing_file_version,
132 existing_injection_data=existing_injection_data,
133 existing_samples=existing_samples,
134 existing_metafile=existing_metafile,
135 existing_file_kwargs=existing_file_kwargs,
136 existing_weights=existing_weights,
137 add_to_existing=add_to_existing, notes=notes,
138 disable_comparison=disable_comparison,
139 disable_interactive=disable_interactive,
140 package_information=package_information, mcmc_samples=mcmc_samples,
141 external_hdf5_links=external_hdf5_links, key_data=key_data,
142 existing_plot=existing_plot, disable_expert=disable_expert,
143 analytic_priors=analytic_priors
144 )
145 if self.file_kwargs is None:
146 self.file_kwargs = {
147 label: {"sampler": {}, "meta_data": {}} for label in self.labels
148 }
149 if self.approximant is None:
150 self.approximant = {label: None for label in self.labels}
151 if self.result_files is None:
152 self.result_files = [None] * len(self.labels)
153 self.psd_path = {"other": os.path.join("..", "psds")}
154 self.calibration_path = {"other": os.path.join("..", "calibration")}
155 self.preliminary_pages = preliminary_pages
156 if not isinstance(self.preliminary_pages, dict):
157 if self.preliminary_pages:
158 self.preliminary_pages = {
159 label: True for label in self.labels
160 }
161 else:
162 self.preliminary_pages = {
163 label: False for label in self.labels
164 }
165 if all(value for value in self.preliminary_pages.values()):
166 self.all_pages_preliminary = True
167 if len(self.labels) > 1:
168 if any(value for value in self.preliminary_pages.values()):
169 self.preliminary_pages["Comparison"] = True
171 def categorize_parameters(self, parameters):
172 """Categorize the parameters into common headings
174 Parameters
175 ----------
176 parameters: list
177 list of parameters that you would like to sort
178 """
179 return super(_WebpageGeneration, self).categorize_parameters(
180 parameters, starting_letter=False
181 )
183 def categorize_2d_parameters(self, samples):
184 """Categorize the default 2d parameters and decide the common
185 headings
187 Parameters
188 ----------
189 parameters: list
190 list of parameters that you would like to sort
191 """
192 sort = {}
193 for params in conf.gw_2d_plots:
194 if not all(p in samples.keys() for p in params):
195 continue
196 if not all(len(np.unique(samples[p])) > 1 for p in params):
197 continue
198 headings = self.categorize_parameters(params)
199 for hh in headings[::-1]:
200 if len(hh[1]) and hh[0] not in ["others"]:
201 heading = hh[0]
202 break
203 if heading not in sort.keys():
204 sort[heading] = []
205 sort[heading] += params
206 return sort
208 def _kde_from_same_samples(self, param, samples):
209 """Generate KDEs for a set of samples
211 Parameters
212 ----------
213 param: str
214 The parameter that the samples belong to
215 samples: list
216 list of samples for each result file
217 """
218 from pesummary.utils.bounded_1d_kde import ReflectionBoundedKDE
219 from pesummary.gw.plots.plot import _return_bounds
221 xlow, xhigh = _return_bounds(param, samples, comparison=True)
222 return super(_WebpageGeneration, self)._kde_from_same_samples(
223 param, samples, kde=ReflectionBoundedKDE, xlow=xlow, xhigh=xhigh
224 )
226 def make_navbar_for_homepage(self):
227 """Make a navbar for the homepage
228 """
229 links = super(_WebpageGeneration, self).make_navbar_for_homepage()
230 if self.gwdata is not None:
231 links.append(["Detchar", [i for i in self.gwdata.keys()]])
232 return links
234 def make_navbar_for_result_page(self):
235 """Make a navbar for the result page homepage
236 """
237 links = super(_WebpageGeneration, self).make_navbar_for_result_page()
238 for num, label in enumerate(self.labels):
239 links[label].append(
240 ["2d Histograms", [
241 {"masses": label}, {"spins": label}, {"location": label}
242 ]]
243 )
244 if self.pepredicates_probs[label] is not None:
245 links[label].append({"Classification": label})
246 return links
248 def generate_webpages(self):
249 """Generate all webpages for all result files passed
250 """
251 super(_WebpageGeneration, self).generate_webpages()
252 self.make_2d_histogram_pages()
253 if self.publication:
254 self.make_publication_pages()
255 if self.gwdata is not None:
256 self.make_detector_pages()
257 if all(val is not None for key, val in self.pepredicates_probs.items()):
258 self.make_classification_pages()
260 def _make_home_pages(self, pages):
261 """Make the home pages
263 Parameters
264 ----------
265 pages: list
266 list of pages that you wish to create
267 """
268 title = None if self.gracedb is None else (
269 "Parameter Estimation Summary Pages for {}".format(self.gracedb)
270 )
271 banner = "Summary" if self.gracedb is None else (
272 "Summary for {}".format(self.gracedb)
273 )
274 html_file = self.setup_page("home", self.navbar["home"], title=title)
275 html_file.make_banner(approximant=banner, key="Summary")
276 path = self.image_path["home"]
278 if self.make_comparison:
279 if not all(self.approximant[i] is not None for i in self.labels):
280 image_contents = []
281 _plot = os.path.join(path, "compare_time_domain_waveforms.png")
282 if os.path.isfile(_plot):
283 image_contents.append(_plot)
284 image_contents = [image_contents]
285 html_file = self.make_modal_carousel(
286 html_file, image_contents, unique_id=True
287 )
289 for i in self.labels:
290 html_file.make_banner(approximant=i, key=i)
291 image_contents, captions = [], []
292 basic_string = os.path.join(self.webdir, "plots", "{}.png")
293 relative_path = os.path.join(path, "{}.png")
294 if os.path.isfile(basic_string.format("%s_strain" % (i))):
295 image_contents.append(relative_path.format("%s_strain" % (i)))
296 captions.append(PlotCaption("strain"))
297 if os.path.isfile(basic_string.format("%s_psd_plot" % (i))):
298 image_contents.append(relative_path.format("%s_psd_plot" % (i)))
299 captions.append(PlotCaption("psd"))
300 if os.path.isfile(
301 basic_string.format("%s_waveform_time_domain" % (i))
302 ):
303 image_contents.append(
304 relative_path.format("%s_waveform_time_domain" % (i))
305 )
306 captions.append(PlotCaption("time_waveform"))
307 if os.path.isfile(
308 basic_string.format("%s_calibration_plot" % (i))
309 ):
310 image_contents.append(
311 relative_path.format("%s_calibration_plot" % (i))
312 )
313 captions.append(PlotCaption("calibration"))
314 image_contents = [image_contents]
315 html_file = self.make_modal_carousel(
316 html_file, image_contents, unique_id=True, extra_div=True,
317 captions=[captions]
318 )
320 for _key in ["sampler", "meta_data"]:
321 if _key == "sampler":
322 html_file.make_banner(
323 approximant="Sampler kwargs", key="sampler_kwargs",
324 _style="font-size: 26px;"
325 )
326 else:
327 html_file.make_banner(
328 approximant="Meta data", key="meta_data",
329 _style="font-size: 26px;"
330 )
331 _style = "margin-top:3em; margin-bottom:5em; max-width:1400px"
332 _class = "row justify-content-center"
333 html_file.make_container(style=_style)
334 html_file.make_div(4, _class=_class, _style=None)
336 base_label = self.labels[0]
337 total_keys = list(self.file_kwargs[base_label][_key].keys())
338 if len(self.labels) > 1:
339 for _label in self.labels[1:]:
340 total_keys += [
341 key for key in self.file_kwargs[_label][_key].keys()
342 if key not in total_keys
343 ]
344 _headings = ["label"] + total_keys
345 table_contents = [
346 [i] + [
347 self.file_kwargs[i][_key][key] if key in
348 self.file_kwargs[i][_key].keys() else "-" for key in
349 total_keys
350 ] for i in self.labels
351 ]
352 html_file.make_table(
353 headings=_headings, format="table-hover", heading_span=1,
354 contents=table_contents, accordian=False
355 )
356 html_file.end_div(4)
357 html_file.end_container()
358 html_file.export("{}.csv".format(_key))
360 html_file.make_footer(user=self.user, rundir=self.webdir)
361 html_file.close()
362 super(_WebpageGeneration, self)._make_home_pages(pages, make_home=False)
364 def make_2d_histogram_pages(self):
365 """Wrapper function for _make_2d_histogram pages
366 """
367 pages = [
368 "{}_{}_{}".format(i, i, j) for i in self.labels for j in
369 self.categorize_2d_parameters(self.samples[i]).keys()
370 ]
371 self.create_blank_html_pages(pages)
372 self._make_2d_histogram_pages(pages)
374 def _make_2d_histogram_pages(self, pages):
375 """Make the 2d histogram pages
376 """
377 for num, i in enumerate(self.labels):
378 for j, k in self.categorize_2d_parameters(self.samples[i]).items():
379 html_file = self.setup_page(
380 "{}_{}".format(i, j), self.navbar["result_page"][i],
381 i, title="{} Posterior PDFs describing the {}".format(i, j),
382 approximant=i, background_colour=self.colors[num],
383 histogram_download=False, toggle=self.expert_plots
384 )
385 html_file.make_banner(approximant=i, key=i)
386 path = self.image_path["other"]
387 contents = [
388 path + "{}_2d_posterior_{}_{}.png".format(i, k[l], k[l+1])
389 for l in range(0, len(k), 2)
390 ]
391 if len(contents) < 2:
392 autoscale = False
393 else:
394 autoscale = True
395 image_contents = [
396 contents[l:2 + l] for l in range(0, len(contents), 2)
397 ]
398 html_file.make_table_of_images(
399 contents=image_contents, code="changeimage",
400 mcmc_samples=False, autoscale=autoscale
401 )
402 key_data = self.key_data
403 contents = []
404 headings = [" "] + self.key_data_headings.copy()
405 _injection = False
406 rows = []
407 for param in np.unique(k):
408 _row = [param]
409 _row += self.key_data_table[i][param]
410 rows.append(_row)
411 _style = "margin-top:3em; margin-bottom:5em; max-width:1400px"
412 _class = "row justify-content-center"
413 html_file.make_container(style=_style)
414 html_file.make_div(4, _class=_class, _style=None)
415 html_file.make_table(
416 headings=headings, contents=rows, heading_span=1,
417 accordian=False, format="table-hover"
418 )
419 html_file.end_div(4)
420 html_file.end_container()
421 html_file.export("summary_information_{}.csv".format(i))
422 html_file.make_footer(user=self.user, rundir=self.webdir)
423 html_file.close()
425 def make_publication_pages(self):
426 """Wrapper function for _make_publication_pages()
427 """
428 pages = ["Publication"]
429 self.create_blank_html_pages(pages)
430 self._make_publication_pages(pages)
432 def _make_publication_pages(self, pages):
433 """Make the publication pages
435 Parameters
436 ----------
437 pages: list
438 list of pages that you wish to create
439 """
440 from glob import glob
442 executable = self.get_executable("summarypublication")
443 general_cli = "%s --webdir %s --samples %s --labels %s --plot {}" % (
444 executable, os.path.join(self.webdir, "plots", "publication"),
445 " ".join(self.result_files), " ".join(self.labels)
446 )
447 if self.publication_kwargs != {}:
448 general_cli += "--publication_kwargs %s" % (
449 " ".join(
450 [
451 "{}:{}".format(key, value) for key, value in
452 self.publication_kwargs.items()
453 ]
454 )
455 )
456 html_file = self.setup_page(
457 "Publication", self.navbar["home"], title="Publication Plots"
458 )
459 html_file.make_banner(approximant="Publication", key="Publication")
460 path = self.image_path["other"]
461 pub_plots = glob(
462 os.path.join(self.webdir, "plots", "publication", "*.png")
463 )
464 for num, i in enumerate(pub_plots):
465 shortened_path = i.split("/plots/")[-1]
466 pub_plots[num] = path + shortened_path
467 cli = []
468 cap = []
469 posterior_name = \
470 lambda i: "{} ({})".format(i, descriptive_names[i]) if i in \
471 descriptive_names.keys() and descriptive_names[i] != "" else i
472 for i in pub_plots:
473 filename = i.split("/")[-1]
474 if "violin_plot" in filename:
475 parameter = filename.split("violin_plot_")[-1].split(".png")[0]
476 cli.append(
477 general_cli.format("violin") + " --parameters %s" % (
478 parameter
479 )
480 )
481 cap.append(
482 PlotCaption("violin").format(posterior_name(parameter))
483 )
484 elif "spin_disk" in filename:
485 cli.append(general_cli.format("spin_disk"))
486 cap.append(PlotCaption("spin_disk"))
487 elif "2d_contour" in filename:
488 parameters = filename.split("2d_contour_plot_")[-1].split(".png")[0]
489 cli.append(
490 general_cli.format("2d_contour") + " --parameters %s" % (
491 parameters.replace("_and_", " ")
492 )
493 )
494 pp = parameters.split("_and_")
495 cap.append(
496 PlotCaption("2d_contour").format(
497 posterior_name(pp[0]), posterior_name(pp[1])
498 )
499 )
500 image_contents = [
501 pub_plots[i:3 + i] for i in range(0, len(pub_plots), 3)
502 ]
503 command_lines = [
504 cli[i:3 + i] for i in range(0, len(cli), 3)
505 ]
506 captions = [cap[i:3 + i] for i in range(0, len(cap), 3)]
507 html_file = self.make_modal_carousel(
508 html_file, image_contents, cli=command_lines, captions=captions
509 )
510 html_file.make_footer(user=self.user, rundir=self.webdir)
511 html_file.close()
513 def make_detector_pages(self):
514 """Wrapper function for _make_publication_pages()
515 """
516 pages = [i for i in self.gwdata.keys()]
517 self.create_blank_html_pages(pages)
518 self._make_detector_pages(pages)
520 def _make_detector_pages(self, pages):
521 """Make the detector characterisation pages
523 Parameters
524 ----------
525 pages: list
526 list of pages that you wish to create
527 """
528 from pesummary.utils.utils import (
529 determine_gps_time_and_window, command_line_dict
530 )
531 from astropy.time import Time
533 executable = self.get_executable("summarydetchar")
534 try:
535 command_line = command_line_dict()
536 except SystemExit:
537 command_line = {"gwdata": {}}
538 if isinstance(command_line["gwdata"], dict):
539 gwdata_command_line = [
540 "{}:{}".format(key, val) for key, val in
541 command_line["gwdata"].items()
542 ]
543 else:
544 gwdata_command_line = command_line["gwdata"]
545 if gwdata_command_line is None:
546 gwdata_command_line = []
547 general_cli = "%s --webdir %s --gwdata %s --plot {}{}" % (
548 executable, os.path.join(self.webdir, "plots"),
549 " ".join(gwdata_command_line)
550 )
551 path = self.image_path["other"]
552 base = os.path.join(path, "{}_{}.png")
553 ADD_DETCHAR_LINK = True
554 try:
555 maxL_samples = {
556 i: {
557 "geocent_time": self.key_data[i]["geocent_time"]["maxL"]
558 } for i in self.labels
559 }
560 except KeyError:
561 # trying a different name for time
562 try:
563 maxL_samples = {
564 i: {
565 "geocent_time": self.key_data[i][
566 "marginalized_geocent_time"
567 ]["maxL"]
568 } for i in self.labels
569 }
570 except KeyError:
571 logger.warning(
572 "Failed to find a time parameter to link to detchar/"
573 "summary pages. Not adding link to webpages."
574 )
575 ADD_DETCHAR_LINK = False
576 if ADD_DETCHAR_LINK:
577 gps_time, window = determine_gps_time_and_window(maxL_samples, self.labels)
578 t = Time(gps_time, format='gps')
579 t = Time(t, format='datetime')
580 link = (
581 "https://ldas-jobs.ligo-wa.caltech.edu/~detchar/summary/day"
582 "/{}{}{}/".format(
583 t.value.year,
584 "0{}".format(t.value.month) if t.value.month < 10 else t.value.month,
585 "0{}".format(t.value.day) if t.value.day < 10 else t.value.day
586 )
587 )
588 else:
589 link = None
590 gps_time, window = None, None
591 for det in self.gwdata.keys():
592 html_file = self.setup_page(
593 det, self.navbar["home"], title="{} Detchar".format(det)
594 )
595 html_file.make_banner(approximant=det, key="detchar", link=link)
596 image_contents = [
597 [base.format("spectrogram", det), base.format("omegascan", det)]
598 ]
599 command_lines = [
600 [
601 general_cli.format("spectrogram", ""),
602 general_cli.format(
603 "omegascan", "--gps %s --vmin 0 --vmax 25 --window %s" % (
604 gps_time, window
605 )
606 )
607 ]
608 ]
609 html_file = self.make_modal_carousel(
610 html_file, image_contents, cli=command_lines, autoscale=True,
611 )
612 html_file.make_footer(user=self.user, rundir=self.webdir)
613 html_file.close()
615 def make_classification_pages(self):
616 """Wrapper function for _make_publication_pages()
617 """
618 pages = ["{}_{}_Classification".format(i, i) for i in self.labels]
619 self.create_blank_html_pages(pages)
620 self._make_classification_pages(pages)
622 def _make_classification_pages(self, pages):
623 """Make the classification pages
625 Parameters
626 ----------
627 pages: list
628 list of pages that you wish to create
629 """
630 executable = self.get_executable("summaryclassification")
631 general_cli = "%s --samples {}" % (executable)
632 for num, label in enumerate(self.labels):
633 html_file = self.setup_page(
634 "{}_Classification".format(label),
635 self.navbar["result_page"][label], label,
636 title="{} Classification".format(label),
637 background_colour=self.colors[num], approximant=label
638 )
639 html_file.make_banner(approximant=label, key="classification")
641 if self.pepredicates_probs[label] is not None:
642 html_file.make_container()
643 _class = "row justify-content-center"
644 html_file.make_div(4, _class=_class, _style=None)
645 keys = list(self.pepredicates_probs[label]["default"].keys())
646 table_contents = [
647 ["{} prior".format(i)] + [
648 self.pepredicates_probs[label][i][j] for j in keys
649 ] for i in ["default", "population"]
650 ]
651 if self.pastro_probs[label] is not None:
652 keys += ["HasNS"]
653 keys += ["HasRemnant"]
654 table_contents[0].append(self.pastro_probs[label]["default"]["HasNS"])
655 table_contents[0].append(
656 self.pastro_probs[label]["default"]["HasRemnant"]
657 )
658 try:
659 table_contents[1].append(
660 self.pastro_probs[label]["population"]["HasNS"]
661 )
662 table_contents[1].append(
663 self.pastro_probs[label]["population"]["HasRemnant"]
664 )
665 except KeyError:
666 table_contents[1].append("-")
667 table_contents[1].append("-")
668 logger.warning(
669 "Failed to add 'em_bright' probabilities for population "
670 "reweighted prior"
671 )
672 html_file.make_table(
673 headings=[" "] + keys, contents=table_contents,
674 heading_span=1, accordian=False
675 )
676 html_file.make_cli_button(
677 general_cli.format(self.result_files[num])
678 )
679 html_file.export(
680 "classification_{}.csv".format(label),
681 margin_top="-1.5em", margin_bottom="0.5em", json=True
682 )
683 html_file.end_div(4)
684 html_file.end_container()
685 path = self.image_path["other"]
686 base = os.path.join(path, "%s_{}_pepredicates{}.png" % (label))
687 image_contents = [
688 [
689 base.format("default", ""), base.format("default", "_bar"),
690 base.format("population", ""),
691 base.format("population", "_bar")
692 ]
693 ]
694 base = (
695 "%s --webdir %s --labels %s --plot {} --prior {}" % (
696 general_cli.format(self.result_files[num]),
697 os.path.join(self.webdir, "plots"), label
698 )
699 )
700 command_lines = [
701 [
702 base.format("mass_1_mass_2", "default"),
703 base.format("bar", "default"),
704 base.format("mass_1_mass_2", "population"),
705 base.format("bar", "population")
706 ]
707 ]
708 captions = [
709 [
710 PlotCaption("default_classification_mass_1_mass_2"),
711 PlotCaption("default_classification_bar"),
712 PlotCaption("population_classification_mass_1_mass_2"),
713 PlotCaption("population_classification_bar")
714 ]
715 ]
716 html_file = self.make_modal_carousel(
717 html_file, image_contents, cli=command_lines, autoscale=True,
718 captions=captions
719 )
720 html_file.make_footer(user=self.user, rundir=self.webdir)
721 html_file.close()
723 def _make_entry_in_downloads_table(self, html_file, label, num, base_string):
724 """Make a label specific entry into the downloads table
726 Parameters
727 ----------
728 label: str
729 the label you wish to add to the downloads table
730 base_string: str
731 the download string
732 """
733 table = super(_WebpageGeneration, self)._make_entry_in_downloads_table(
734 html_file, label, num, base_string
735 )
736 if not self.no_ligo_skymap:
737 table.append(
738 [
739 base_string.format(
740 "Fits file containing skymap for this analysis",
741 self.results_path["other"] + "%s_skymap.fits" % (label)
742 )
743 ]
744 )
745 if self.psd is not None and self.psd != {} and label in self.psd.keys():
746 for ifo in self.psd[label].keys():
747 if len(self.psd[label][ifo]):
748 table.append(
749 [
750 base_string.format(
751 "%s psd file used for this analysis" % (ifo),
752 os.path.join(
753 self.psd_path["other"],
754 "%s_%s_psd.dat" % (label, ifo)
755 )
756 )
757 ]
758 )
759 if self.priors is not None and "calibration" in self.priors.keys():
760 if label in self.priors["calibration"].keys():
761 for ifo in self.priors["calibration"][label].keys():
762 if len(self.priors["calibration"][label][ifo]):
763 table.append(
764 [
765 base_string.format(
766 "%s calibration envelope file used for "
767 "this analysis" % (ifo), os.path.join(
768 self.calibration_path["other"],
769 "%s_%s_cal.txt" % (label, ifo)
770 )
771 )
772 ]
773 )
774 return table
776 def default_images_for_result_page(self, label):
777 """Return the default images that will be displayed on the result page
778 """
779 path = self.image_path["other"]
780 base_string = path + "%s_{}.png" % (label)
781 image_contents = [
782 [
783 base_string.format("1d_posterior_mass_1"),
784 base_string.format("1d_posterior_mass_2"),
785 ], [
786 base_string.format("1d_posterior_a_1"),
787 base_string.format("1d_posterior_a_2"),
788 base_string.format("1d_posterior_chi_eff")
789 ], [
790 base_string.format("1d_posterior_iota"),
791 base_string.format("skymap"),
792 base_string.format("waveform"),
793 base_string.format("1d_posterior_luminosity_distance"),
794 ]
795 ]
796 executable = self.get_executable("summaryplots")
797 general_cli = (
798 "%s --webdir %s --samples %s --burnin %s --plot {} {} "
799 "--labels %s" % (
800 executable, os.path.join(self.webdir, "plots"),
801 self.result_files[self.labels.index(label)], conf.burnin, label
802 )
803 )
804 cli = [
805 [
806 general_cli.format("1d_histogram", "--parameter mass_1"),
807 general_cli.format("1d_histgram", "--parameter mass_2"),
808 ], [
809 general_cli.format("1d_histogram", "--parameter a_1"),
810 general_cli.format("1d_histogram", "--parameter a_2"),
811 general_cli.format("1d_histogram", "--parameter chi_eff")
812 ], [
813 general_cli.format("1d_histogram", "--parameter iota"),
814 general_cli.format("skymap", ""),
815 general_cli.format("waveform", ""),
816 general_cli.format(
817 "1d_histogram", "--parameter luminosity_distance"
818 ),
819 ]
820 ]
822 caption_1d_histogram = PlotCaption("1d_histogram")
823 posterior_name = \
824 lambda i: "{} ({})".format(i, descriptive_names[i]) if i in \
825 descriptive_names.keys() and descriptive_names[i] != "" else i
826 captions = [
827 [
828 caption_1d_histogram.format(posterior_name("mass_1")),
829 caption_1d_histogram.format(posterior_name("mass_2")),
830 ], [
831 caption_1d_histogram.format(posterior_name("a_1")),
832 caption_1d_histogram.format(posterior_name("a_2")),
833 caption_1d_histogram.format(posterior_name("chi_eff"))
834 ], [
835 caption_1d_histogram.format(posterior_name("iota")),
836 PlotCaption("skymap"), PlotCaption("frequency_waveform"),
837 caption_1d_histogram.format(posterior_name("luminosity_distance"))
838 ]
839 ]
840 return image_contents, cli, captions
842 def default_categories(self):
843 """Return the default categories
844 """
845 categories = self.categories = {
846 "masses": {
847 "accept": ["mass"],
848 "reject": ["source", "final", "torus"]
849 },
850 "source": {
851 "accept": ["source"], "reject": ["final", "torus"]
852 },
853 "remnant": {
854 "accept": ["final", "torus"], "reject": []
855 },
856 "inclination": {
857 "accept": ["theta", "iota", "viewing"], "reject": []
858 },
859 "spins": {
860 "accept": ["spin", "chi_p", "chi_eff", "a_1", "a_2", "precession"],
861 "reject": ["lambda", "final", "gamma", "order"]
862 },
863 "spin_angles": {
864 "accept": ["phi", "tilt", "beta"], "reject": []
865 },
866 "tidal": {
867 "accept": [
868 "lambda", "gamma_", "log_pressure",
869 "spectral_decomposition_gamma_", "compactness_",
870 "tidal_disruption"
871 ],
872 "reject": []
873 },
874 "location": {
875 "accept": [
876 "ra", "dec", "psi", "luminosity_distance", "redshift",
877 "comoving_distance"
878 ],
879 "reject": ["mass_ratio", "radiated", "ram", "ran", "rat"]
880 },
881 "timings": {
882 "accept": ["time"], "reject": []
883 },
884 "SNR": {
885 "accept": ["snr", "subdominant_multipoles"], "reject": []
886 },
887 "calibration": {
888 "accept": ["spcal", "recalib", "frequency"],
889 "reject": ["minimum", "tidal_disruption", "quasinormal"]
890 },
891 "energy": {
892 "accept": ["peak_luminosity", "radiated"],
893 "reject": []
894 },
895 "others": {
896 "accept": ["phase", "likelihood", "prior", "quasinormal"],
897 "reject": ["spcal", "recalib"]
898 }
899 }
900 return categories
902 def default_popular_options(self):
903 """Return a list of popular options
904 """
905 popular_options = [
906 "mass_1, mass_2", "luminosity_distance, theta_jn, ra, dec",
907 "theta_jn, phi_12, phi_jl, tilt_1, tilt_2"
908 ]
909 return popular_options
911 def default_comparison_homepage_plots(self):
912 """Return a list of default plots for the comparison homepage
913 """
914 path = self.image_path["other"]
915 base = os.path.join(path, "{}.png")
916 contents = [
917 [base.format("combined_skymap"), base.format("compare_waveforms")]
918 ]
919 return contents
921 def default_corner_params(self):
922 """Return a list of default corner parameters used by the corner
923 plotting function
924 """
925 return conf.gw_corner_parameters
927 def add_to_expert_pages(self, path, label):
928 """Additional expert plots to add beyond the default. This returns a
929 dictionary keyed by the parameter, with values providing the path
930 to the additional plots you wish to add. The plots are a 2d list
931 where each sublist represents a row in the table of images.
933 Parameters
934 ----------
935 path: str
936 path to the image directory
937 label: str
938 label of the plot you wish to add
939 """
940 mydict = super(_WebpageGeneration, self).add_to_expert_pages(
941 path, label
942 )
943 contour_base = path + "{}_2d_contour_{}_log_likelihood.png"
944 mydict.update({
945 "network_precessing_snr": [
946 [
947 contour_base.format(label, "_b_bar"),
948 contour_base.format(label, "_precessing_harmonics_overlap"),
949 ]
950 ]
951 })
952 return mydict
954 @property
955 def additional_1d_pages(self):
956 """Additional 1d histogram pages beyond one for each parameter. You may,
957 for instance, want a 1d histogram page which combines multiple
958 parameters. This returns a dictionary, keyed by the new 1d histogram
959 page, with values indicating the parameters you wish to include on this
960 page. Only the 1d marginalized histograms are shown.
961 """
962 return conf.additional_1d_pages