Coverage for pesummary/core/webpage/main.py: 88.2%
848 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-12-09 22:34 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-12-09 22:34 +0000
1# Licensed under an MIT style license -- see LICENSE.md
3import os
4import sys
5import uuid
6from glob import glob
7from pathlib import Path
8import shutil
10import numpy as np
11import math
13import pesummary
14from pesummary import conf, __version_string__
15from pesummary.utils.utils import (
16 logger, LOG_FILE, jensen_shannon_divergence_from_pdfs, safe_round, make_dir
17)
18from pesummary.core.webpage import webpage
20__author__ = ["Charlie Hoy <charlie.hoy@ligo.org>"]
23class PlotCaption(object):
24 """Class to handle the generation of a plot caption
26 Parameters
27 ----------
28 plot: str
29 name of the plot you wish to generate a caption for
30 """
31 def __new__(cls, plot="1d_histogram"):
32 super(PlotCaption, cls).__init__(cls)
33 obj = cls.caption(plot)
34 return obj
36 def __init__(self, plot="1d_histogram"):
37 self.plot = plot
39 @staticmethod
40 def caption(plot):
41 if hasattr(conf, "caption_{}".format(plot)):
42 return getattr(conf, "caption_{}".format(plot))
43 return "No caption found for {}".format(plot)
46class _WebpageGeneration(object):
47 """Super class to handle the webpage generation for a given set of result
48 files
50 Parameters
51 ----------
52 savedir: str
53 the directory to store the plots
54 webdir: str
55 the web directory of the run
56 samples: dict
57 dictionary of posterior samples stored in the result files
58 labels: list
59 list of labels used to distinguish the result files
60 publication: Bool
61 Bool to determine the generation of a publication webpage
62 user: str
63 the user that submitted the job
64 config: list
65 list of configuration files used for each result file
66 same_parameters: list
67 list of paramerers that are common in all result files
68 base_url: str
69 the url corresponding to the web directory
70 file_versions: dict
71 dictionary of file versions for each result file
72 hdf5: Bool
73 Bool to determine if the metafile has been saved as hdf5 or not
74 colors: list
75 colors that you wish to use to distinguish different result files
76 custom_plotting:
77 existing_labels: list
78 list of labels stored in an existing metafile
79 existing_config: list
80 list of configuration files stored in the existing metafile
81 existing_file_version: dict
82 dictionary of file versions stored in the existing metafile
83 existing_injection_data: dict
84 dictionary of injection data stored in an existing metafile
85 existing_samples: dict
86 dictionary of posterior samples stored in an existing metafile
87 existing_metafile: str
88 path to the existing metafile
89 existing_file_kwargs: dict
90 dictionary of file kwargs stored in an existing metafile
91 add_to_existing: Bool
92 Bool to determine if you wish to add to an existing webpage
93 notes: str
94 notes that you wish to put on the webpages
95 disable_comparison: bool
96 Whether to make comparison pages
97 package_information: dict
98 dictionary of package information
99 mcmc_samples: Bool
100 Whether or not mcmc samples have been passed
101 """
102 def __init__(
103 self, webdir=None, samples=None, labels=None, publication=None,
104 user=None, config=None, same_parameters=None, base_url=None,
105 file_versions=None, hdf5=None, colors=None, custom_plotting=None,
106 existing_labels=None, existing_config=None, existing_file_version=None,
107 existing_injection_data=None, existing_samples=None,
108 existing_metafile=None, existing_file_kwargs=None,
109 existing_weights=None, add_to_existing=False, notes=None,
110 disable_comparison=False, disable_interactive=False,
111 package_information={"packages": [], "manager": "pypi"},
112 mcmc_samples=False, external_hdf5_links=False, key_data=None,
113 existing_plot=None, disable_expert=False, analytic_priors=None,
114 ):
115 self.webdir = webdir
116 make_dir(self.webdir)
117 make_dir(os.path.join(self.webdir, "html"))
118 make_dir(os.path.join(self.webdir, "css"))
119 self.samples = samples
120 self.labels = labels
121 self.publication = publication
122 self.user = user
123 self.config = config
124 self.same_parameters = same_parameters
125 self.base_url = base_url
126 self.file_versions = file_versions
127 if self.file_versions is None:
128 self.file_versions = {
129 label: "No version information found" for label in self.labels
130 }
131 self.hdf5 = hdf5
132 self.colors = colors
133 if self.colors is None:
134 self.colors = list(conf.colorcycle)
135 self.custom_plotting = custom_plotting
136 self.existing_labels = existing_labels
137 self.existing_config = existing_config
138 self.existing_file_version = existing_file_version
139 self.existing_samples = existing_samples
140 self.existing_metafile = existing_metafile
141 self.existing_file_kwargs = existing_file_kwargs
142 self.add_to_existing = add_to_existing
143 self.analytic_priors = analytic_priors
144 if self.analytic_priors is None:
145 self.analytic_priors = {label: None for label in self.samples.keys()}
146 self.key_data = key_data
147 _label = self.labels[0]
148 if self.samples is not None:
149 if key_data is None:
150 self.key_data = {
151 label: _samples.key_data for label, _samples in
152 self.samples.items()
153 }
154 self.key_data_headings = sorted(
155 list(self.key_data[_label][list(self.samples[_label].keys())[0]])
156 )
157 self.key_data_table = {
158 label: {
159 param: [
160 safe_round(self.key_data[label][param].get(key, None), 3) for key
161 in self.key_data_headings
162 ] for param in self.samples[label].keys()
163 } for label in self.labels
164 }
165 self.notes = notes
166 self.make_interactive = not disable_interactive
167 self.package_information = package_information
168 self.mcmc_samples = mcmc_samples
169 self.external_hdf5_links = external_hdf5_links
170 self.existing_plot = existing_plot
171 self.expert_plots = not disable_expert
172 self.make_comparison = (
173 not disable_comparison and self._total_number_of_labels > 1
174 )
175 self.preliminary_pages = {label: False for label in self.labels}
176 self.all_pages_preliminary = False
177 self._additional_1d_pages = {label: [] for label in self.labels}
178 if self.additional_1d_pages is not None:
179 for j, _parameters in self.additional_1d_pages.items():
180 for i in self.labels:
181 if all(
182 param in self.samples[i].keys() for param in
183 _parameters
184 ):
185 self._additional_1d_pages[i].append(j)
186 self.categories = self.default_categories()
187 self.popular_options = self.default_popular_options()
188 self.navbar = {
189 "home": self.make_navbar_for_homepage(),
190 "result_page": self.make_navbar_for_result_page(),
191 "comparison": self.make_navbar_for_comparison_page()
192 }
193 self.image_path = {
194 "home": os.path.join(".", "plots", ""),
195 "other": os.path.join("..", "plots", "")
196 }
197 self.results_path = {
198 "home": "./samples/", "other": "../samples/"
199 }
200 self.config_path = {
201 "home": "./config/", "other": "../config/"
202 }
203 if self.make_comparison:
204 try:
205 self.comparison_stats = self.generate_comparison_statistics()
206 except Exception as e:
207 self.comparison_stats = None
208 logger.info(
209 "Failed to generate comparison statistics because {}. As a "
210 "result they will not be added to the webpages".format(e)
211 )
213 @property
214 def _metafile(self):
215 return (
216 "posterior_samples.json" if not self.hdf5 else
217 "posterior_samples.h5"
218 )
220 @property
221 def _total_number_of_labels(self):
222 _number_of_labels = 0
223 for item in [self.labels, self.existing_labels]:
224 if isinstance(item, list):
225 _number_of_labels += len(item)
226 return _number_of_labels
228 def copy_css_and_js_scripts(self):
229 """Copy css and js scripts from the package to the web directory
230 """
231 import shutil
232 from pesummary import core
233 files_to_copy = []
234 path = core.__path__[0]
235 scripts = glob(os.path.join(path, "js", "*.js"))
236 for i in scripts:
237 files_to_copy.append(
238 [i, os.path.join(self.webdir, "js", os.path.basename(i))]
239 )
240 scripts = glob(os.path.join(path, "css", "*.css"))
241 for i in scripts:
242 files_to_copy.append(
243 [i, os.path.join(self.webdir, "css", os.path.basename(i))]
244 )
245 for _dir in ["js", "css"]:
246 try:
247 os.mkdir(os.path.join(self.webdir, _dir))
248 except FileExistsError:
249 pass
250 for ff in files_to_copy:
251 shutil.copy(ff[0], ff[1])
253 def make_modal_carousel(
254 self, html_file, image_contents, unique_id=False, **kwargs
255 ):
256 """Make a modal carousel for a table of images
258 Parameters
259 ----------
260 html_file: pesummary.core.webpage.webpage.page
261 open html file
262 image_contents: list
263 list of images to place in a table
264 unique_id: Bool, optional
265 if True, assign a unique identifer to the modal
266 **kwargs: dict, optional
267 all additional kwargs passed to `make_table_of_images` function
268 """
269 if unique_id:
270 unique_id = '{}'.format(uuid.uuid4().hex.upper()[:6])
271 else:
272 unique_id = None
273 html_file.make_table_of_images(
274 contents=image_contents, unique_id=unique_id, **kwargs
275 )
276 images = [y for x in image_contents for y in x]
277 html_file.make_modal_carousel(images=images, unique_id=unique_id)
278 return html_file
280 def generate_comparison_statistics(self):
281 """Generate comparison statistics for all parameters that are common to
282 all result files
283 """
284 data = {
285 i: self._generate_comparison_statistics(
286 i, [self.samples[j][i] for j in self.labels]
287 ) for i in self.same_parameters
288 }
289 return data
291 def _generate_comparison_statistics(self, param, samples):
292 """Generate comparison statistics for a set of samples
294 Parameters
295 ----------
296 samples: list
297 list of samples for each result file
298 """
299 from pesummary.utils.utils import kolmogorov_smirnov_test
301 rows = range(len(samples))
302 columns = range(len(samples))
303 ks = [
304 [
305 kolmogorov_smirnov_test([samples[i], samples[j]]) for i in
306 rows
307 ] for j in columns
308 ]
309 # JS divergence is symmetric and therefore we just need to loop over
310 # one triangle
311 js = np.zeros((len(samples), len(samples)))
312 pdfs = self._kde_from_same_samples(param, samples)
313 for num, i in enumerate(range(1, len(js))):
314 for idx, j in enumerate(range(0, i)):
315 js[i][idx] += jensen_shannon_divergence_from_pdfs(
316 [pdfs[i], pdfs[j]]
317 )
318 js = js + js.T
319 return [ks, js.tolist()]
321 def _kde_from_same_samples(self, param, samples, **kwargs):
322 """Generate KDEs for a set of samples
324 Parameters
325 ----------
326 param: str
327 The parameter that the samples belong to
328 samples: list
329 list of samples for each result file
330 """
331 from pesummary.utils.utils import samples_to_kde
332 return samples_to_kde(samples, **kwargs)
334 @staticmethod
335 def get_executable(executable):
336 """Return the path to an executable
338 Parameters
339 ----------
340 executable: str
341 the name of the executable you wish to find
342 """
343 return shutil.which(
344 executable,
345 path=os.pathsep.join((
346 os.getenv("PATH", ""),
347 str(Path(sys.executable).parent),
348 )),
349 )
351 def _result_page_links(self):
352 """Return the navbar structure for the Result Page tab.
353 """
354 return [{i: i} for i in self.labels]
356 def make_navbar_for_homepage(self):
357 """Make a navbar for the homepage
358 """
359 links = [
360 "home", ["Result Pages", self._result_page_links()], "Logging",
361 "Version"
362 ]
363 if self.make_comparison:
364 links[1][1] += ["Comparison"]
365 if self.publication:
366 links.insert(2, "Publication")
367 if self.notes is not None:
368 links.append("Notes")
369 return links
371 def make_navbar_for_result_page(self):
372 """Make a navbar for the result page homepage
373 """
374 links = {
375 i: ["1d Histograms", [{"Custom": i}, {"All": i}]] for i in
376 self.labels
377 }
378 for num, label in enumerate(self.labels):
379 _params = list(self.samples[label].keys())
380 if len(self._additional_1d_pages[label]):
381 _params += self._additional_1d_pages[label]
382 for j in self.categorize_parameters(_params):
383 j = [j[0], [{k: label} for k in j[1]]]
384 links[label].append(j)
386 final_links = {
387 i: [
388 "home", ["Result Pages", self._result_page_links()],
389 {"Corner": i}, {"Config": i}, links[i]
390 ] for i in self.labels
391 }
392 if self.make_comparison:
393 for label in self.labels:
394 final_links[label][1][1] += ["Comparison"]
395 _dummy_label = self.labels[0]
396 if len(final_links[_dummy_label][1][1]) > 1:
397 for label in self.labels:
398 _options = [{l: "switch"} for l in self.labels if l != label]
399 if self.make_comparison:
400 _options.append({"Comparison": "switch"})
401 final_links[label].append(["Switch", _options])
402 if self.make_interactive:
403 for label in self.labels:
404 final_links[label].append(
405 ["Interactive", [{"Interactive_Corner": label}]]
406 )
407 if self.existing_plot is not None:
408 for _label in self.labels:
409 if _label in self.existing_plot.keys():
410 final_links[_label].append(
411 {"Additional": _label}
412 )
413 return final_links
415 def make_navbar_for_comparison_page(self):
416 """Make a navbar for the comparison homepage
417 """
418 if self.same_parameters is not None:
419 links = ["1d Histograms", ["Custom", "All"]]
420 for i in self.categorize_parameters(self.same_parameters):
421 links.append(i)
422 final_links = [
423 "home", ["Result Pages", self._result_page_links()], links
424 ]
425 final_links[1][1] += ["Comparison"]
426 final_links.append(
427 ["Switch", [{l: "switch"} for l in self.labels]]
428 )
429 if self.make_interactive:
430 final_links.append(
431 ["Interactive", ["Interactive_Ridgeline"]]
432 )
433 return final_links
434 return None
436 def categorize_parameters(
437 self, parameters, starting_letter=True, heading_all=True
438 ):
439 """Categorize the parameters into common headings
441 Parameters
442 ----------
443 parameters: list
444 list of parameters that you would like to sort
445 """
446 params = []
447 for heading, category in self.categories.items():
448 if any(
449 any(i[0] in j for j in category["accept"]) for i in parameters
450 ):
451 cond = self._condition(
452 category["accept"], category["reject"],
453 starting_letter=starting_letter
454 )
455 part = self._partition(cond, parameters)
456 if heading_all and len(part):
457 part = ["{}_all".format(heading)] + part
458 params.append([heading, part])
459 used_headings = [i[0] for i in params]
460 other_index = \
461 used_headings.index("others") if "others" in used_headings else None
462 other_params = []
463 for pp in parameters:
464 if not any(pp in j[1] for j in params):
465 if other_index is not None:
466 params[other_index][1].append(pp)
467 else:
468 other_params.append(pp)
469 if other_index is None:
470 params.append(["others", other_params])
471 return params
473 def _condition(self, true, false, starting_letter=False):
474 """Setup a condition
476 Parameters
477 ----------
478 true: list
479 list of strings that you would like to include
480 false: list
481 list of strings that you would like to neglect
482 """
483 def _starting_letter(param, condition):
484 if condition:
485 return param[0]
486 return param
487 if len(true) != 0 and len(false) == 0:
488 condition = lambda j: True if any(
489 i in _starting_letter(j, starting_letter) for i in true
490 ) else False
491 elif len(true) == 0 and len(false) != 0:
492 condition = lambda j: True if any(
493 i not in _starting_letter(j, starting_letter) for i in false
494 ) else False
495 elif len(true) and len(false) != 0:
496 condition = lambda j: True if any(
497 i in _starting_letter(j, starting_letter) and all(
498 k not in _starting_letter(j, starting_letter) for k in false
499 ) for i in true
500 ) else False
501 return condition
503 def _partition(self, condition, array):
504 """Filter the list according to a condition
506 Parameters
507 ----------
508 condition: func
509 lambda function containing the condition that you want to use to
510 filter the array
511 array: list
512 List of parameters that you would like to filter
513 """
514 return sorted(list(filter(condition, array)))
516 def generate_webpages(self):
517 """Generate all webpages for all result files passed
518 """
519 if self.add_to_existing:
520 self.add_existing_data()
521 self.make_home_pages()
522 self.make_1d_histogram_pages()
523 self.make_corner_pages()
524 self.make_config_pages()
525 if self.make_comparison:
526 self.make_comparison_pages()
527 if self.make_interactive:
528 self.make_interactive_pages()
529 if self.existing_plot is not None:
530 self.make_additional_plots_pages()
531 self.make_error_page()
532 self.make_version_page()
533 self.make_logging_page()
534 if self.notes is not None:
535 self.make_notes_page()
536 self.make_downloads_page()
537 self.make_about_page()
538 try:
539 self.generate_specific_javascript()
540 except Exception:
541 pass
543 def create_blank_html_pages(self, pages, stylesheets=[]):
544 """Create blank html pages
546 Parameters
547 ----------
548 pages: list
549 list of pages that you wish to create
550 """
551 webpage.make_html(
552 web_dir=self.webdir, pages=pages, stylesheets=stylesheets
553 )
555 def setup_page(
556 self, html_page, links, label=None, title=None, approximant=None,
557 background_colour=None, histogram_download=False, toggle=False
558 ):
559 """Set up each webpage with a header and navigation bar.
561 Parameters
562 ----------
563 html_page: str
564 String containing the html page that you would like to set up
565 links: list
566 List containing the navbar structure that you would like to include
567 label: str, optional
568 The label that prepends your webpage name
569 title: str, optional
570 String that you would like to include in your header
571 approximant: str, optional
572 The approximant that you would like associated with your html_page
573 background_colour: str, optional
574 String containing the background colour of your header
575 histogram_download: bool, optional
576 If true, a download link for the each histogram is displayed in
577 the navbar
578 """
579 html_file = webpage.open_html(
580 web_dir=self.webdir, base_url=self.base_url, html_page=html_page,
581 label=label
582 )
583 _preliminary_keys = self.preliminary_pages.keys()
584 if self.all_pages_preliminary:
585 html_file.make_watermark()
586 elif approximant is not None and approximant in _preliminary_keys:
587 if self.preliminary_pages[approximant]:
588 html_file.make_watermark()
590 html_file.make_header(approximant=approximant)
591 if html_page == "home" or html_page == "home.html":
592 html_file.make_navbar(
593 links=links, samples_path=self.results_path["home"],
594 background_color=background_colour,
595 hdf5=self.hdf5, toggle=toggle
596 )
597 elif histogram_download:
598 html_file.make_navbar(
599 links=links, samples_path=self.results_path["other"],
600 toggle=toggle, histogram_download=os.path.join(
601 "..", "samples", "dat", label, "{}_{}_samples.dat".format(
602 label, html_page
603 )
604 ), background_color=background_colour, hdf5=self.hdf5
605 )
606 else:
607 html_file.make_navbar(
608 links=links, samples_path=self.results_path["home"],
609 background_color=background_colour, hdf5=self.hdf5,
610 toggle=toggle
611 )
612 return html_file
614 def make_home_pages(self):
615 """Wrapper function for _make_home_pages()
616 """
617 pages = ["{}_{}".format(i, i) for i in self.labels]
618 pages.append("home")
619 self.create_blank_html_pages(pages)
620 self._make_home_pages(pages)
622 def _make_home_pages(
623 self, pages, title=None, banner="Summary", make_home=True,
624 make_result=True, return_html=False
625 ):
626 """Make the home pages
628 Parameters
629 ----------
630 pages: list
631 list of pages that you wish to create
632 """
633 if make_home:
634 html_file = self.setup_page("home", self.navbar["home"], title=title)
635 html_file.make_banner(approximant=banner, key="Summary")
636 if return_html:
637 return html_file
638 if not make_result:
639 return
641 for num, i in enumerate(self.labels):
642 html_file = self.setup_page(
643 i, self.navbar["result_page"][i], i, approximant=i,
644 title="{} Summary page".format(i),
645 background_colour=self.colors[num]
646 )
647 images, cli, captions = self.default_images_for_result_page(i)
648 _images_available = [
649 item for sublist in images for item in sublist if os.path.isfile(
650 item.replace(
651 self.image_path["other"], "{}/plots/".format(self.webdir)
652 )
653 )
654 ]
655 if len(_images_available) > 2:
656 html_file.make_banner(approximant=i, key=i)
657 html_file = self.make_modal_carousel(
658 html_file, images, cli=cli, unique_id=True,
659 captions=captions, autoscale=True
660 )
661 else:
662 html_file.make_banner(approximant=i, key="custom", custom="")
664 if self.custom_plotting:
665 custom_plots = glob(
666 "{}/plots/{}_custom_plotting_*".format(self.webdir, i)
667 )
668 path = self.image_path["other"]
669 for num, i in enumerate(custom_plots):
670 custom_plots[num] = path + i.split("/")[-1]
671 image_contents = [
672 custom_plots[i:4 + i] for i in range(
673 0, len(custom_plots), 4
674 )
675 ]
676 html_file = self.make_modal_carousel(
677 html_file, image_contents, unique_id=True
678 )
680 html_file.make_banner(
681 approximant="Summary Table", key="summary_table",
682 _style="font-size: 26px;"
683 )
684 _style = "margin-top:3em; margin-bottom:5em; max-width:1400px"
685 _class = "row justify-content-center"
686 html_file.make_container(style=_style)
687 html_file.make_div(4, _class=_class, _style=None)
689 key_data = self.key_data
690 contents = []
691 headings = [" "] + self.key_data_headings.copy()
692 _injection = False
693 if "injected" in headings:
694 _injection = not all(
695 math.isnan(_data["injected"]) for _data in
696 self.key_data[i].values()
697 )
698 if _injection:
699 headings.append("injected")
700 for j in self.samples[i].keys():
701 row = []
702 row.append(j)
703 row += self.key_data_table[i][j]
704 if _injection:
705 row.append(safe_round(self.key_data[i][j]["injected"], 3))
706 contents.append(row)
708 html_file.make_table(
709 headings=headings, contents=contents, heading_span=1,
710 accordian=False, format="table-hover header-fixed",
711 sticky_header=True
712 )
713 html_file.end_div(4)
714 html_file.end_container()
715 html_file.export(
716 "summary_information_{}.csv".format(i)
717 )
718 html_file.make_footer(user=self.user, rundir=self.webdir)
719 html_file.close()
721 def make_1d_histogram_pages(self):
722 """Wrapper function for _make_1d_histogram pages
723 """
724 pages = [
725 "{}_{}_{}".format(i, i, j) for i in self.labels for j in
726 self.samples[i].keys()
727 ]
728 pages += ["{}_{}_Custom".format(i, i) for i in self.labels]
729 pages += ["{}_{}_All".format(i, i) for i in self.labels]
730 for i in self.labels:
731 if len(self._additional_1d_pages[i]):
732 pages += [
733 "{}_{}_{}".format(i, i, j) for j in
734 self._additional_1d_pages[i]
735 ]
736 pages += [
737 "{}_{}_{}_all".format(i, i, j[0]) for i in self.labels for j in
738 self.categorize_parameters(self.samples[i].keys()) if len(j[1])
739 ]
740 self.create_blank_html_pages(pages)
741 self._make_1d_histogram_pages(pages)
743 def _make_1d_histogram_pages(self, pages):
744 """Make the 1d histogram pages
746 Parameters
747 ----------
748 pages: list
749 list of pages that you wish to create
750 """
751 for num, i in enumerate(self.labels):
752 if len(self._additional_1d_pages[i]):
753 for j in self._additional_1d_pages[i]:
754 _parameters = self.additional_1d_pages[j]
755 html_file = self.setup_page(
756 "{}_{}".format(i, j), self.navbar["result_page"][i],
757 i, title="{} Posterior PDFs describing {}".format(i, j),
758 approximant=i, background_colour=self.colors[num],
759 histogram_download=False, toggle=self.expert_plots
760 )
761 html_file.make_banner(approximant=i, key=i)
762 path = self.image_path["other"]
763 _plots = [
764 path + "{}_1d_posterior_{}.png".format(i, param) for
765 param in _parameters
766 ]
767 contents = [
768 _plots[i:2 + i] for i in range(0, len(_plots), 2)
769 ]
770 html_file.make_table_of_images(
771 contents=contents, code="changeimage",
772 mcmc_samples=self.mcmc_samples, autoscale=True
773 )
774 key_data = self.key_data
775 contents = []
776 headings = [" "] + self.key_data_headings.copy()
777 _injection = False
778 rows = []
779 for param in _parameters:
780 _row = [param]
781 _row += self.key_data_table[i][param]
782 rows.append(_row)
783 _style = "margin-top:3em; margin-bottom:5em; max-width:1400px"
784 _class = "row justify-content-center"
785 html_file.make_container(style=_style)
786 html_file.make_div(4, _class=_class, _style=None)
787 html_file.make_table(
788 headings=headings, contents=rows, heading_span=1,
789 accordian=False, format="table-hover"
790 )
791 html_file.end_div(4)
792 html_file.end_container()
793 html_file.export("summary_information_{}.csv".format(i))
794 html_file.make_footer(user=self.user, rundir=self.webdir)
795 html_file.close()
796 for j in self.samples[i].keys():
797 html_file = self.setup_page(
798 "{}_{}".format(i, j), self.navbar["result_page"][i],
799 i, title="{} Posterior PDF for {}".format(i, j),
800 approximant=i, background_colour=self.colors[num],
801 histogram_download=False, toggle=self.expert_plots
802 )
803 if j.description != "Unknown parameter description":
804 _custom = (
805 "The figures below show the plots for {}: {}"
806 )
807 html_file.make_banner(
808 approximant=i, key="custom",
809 custom=_custom.format(j, j.description)
810 )
811 else:
812 html_file.make_banner(approximant=i, key=i)
813 path = self.image_path["other"]
814 contents = [
815 [path + "{}_1d_posterior_{}.png".format(i, j)],
816 [
817 path + "{}_sample_evolution_{}.png".format(i, j),
818 path + "{}_autocorrelation_{}.png".format(i, j)
819 ]
820 ]
821 captions = [
822 [PlotCaption("1d_histogram").format(j)],
823 [
824 PlotCaption("sample_evolution").format(j),
825 PlotCaption("autocorrelation").format(j)
826 ]
827 ]
828 html_file.make_table_of_images(
829 contents=contents, rows=1, columns=2, code="changeimage",
830 captions=captions, mcmc_samples=self.mcmc_samples
831 )
832 contents = [
833 [path + "{}_2d_contour_{}_log_likelihood.png".format(i, j)],
834 [
835 path + "{}_sample_evolution_{}_{}_colored.png".format(
836 i, j, "log_likelihood"
837 ), path + "{}_1d_posterior_{}_bootstrap.png".format(i, j)
838 ]
839 ]
840 captions = [
841 [PlotCaption("2d_contour").format(j, "log_likelihood")],
842 [
843 PlotCaption("sample_evolution_colored").format(
844 j, "log_likelihood"
845 ),
846 PlotCaption("1d_histogram_bootstrap").format(100, j, 1000)
847 ],
848 ]
849 if self.expert_plots:
850 html_file.make_table_of_images(
851 contents=contents, rows=1, columns=2, code="changeimage",
852 captions=captions, mcmc_samples=self.mcmc_samples,
853 display='none', container_id='expert_div',
854 close_container=False
855 )
856 _additional = self.add_to_expert_pages(path, i)
857 if _additional is not None and j in _additional.keys():
858 html_file.make_table_of_images(
859 contents=_additional[j], code="changeimage",
860 mcmc_samples=self.mcmc_samples,
861 autoscale=True, display='none',
862 add_to_open_container=True,
863 )
864 html_file.end_div()
865 html_file.export(
866 "", csv=False, json=False, shell=False, margin_bottom="1em",
867 histogram_dat=os.path.join(
868 self.results_path["other"], i, "{}_{}.dat".format(i, j)
869 )
870 )
871 key_data = self.key_data
872 contents = []
873 headings = self.key_data_headings.copy()
874 _injection = False
875 if "injected" in headings:
876 _injection = not math.isnan(self.key_data[i][j]["injected"])
877 row = self.key_data_table[i][j]
878 if _injection:
879 headings.append("injected")
880 row.append(safe_round(self.key_data[i][j]["injected"], 3))
881 _style = "margin-top:3em; margin-bottom:5em; max-width:1400px"
882 _class = "row justify-content-center"
883 html_file.make_container(style=_style)
884 html_file.make_div(4, _class=_class, _style=None)
885 html_file.make_table(
886 headings=headings, contents=[row], heading_span=1,
887 accordian=False, format="table-hover"
888 )
889 html_file.end_div(4)
890 html_file.end_container()
891 html_file.export(
892 "summary_information_{}.csv".format(i)
893 )
894 html_file.make_footer(user=self.user, rundir=self.webdir)
895 html_file.close()
896 html_file = self.setup_page(
897 "{}_Custom".format(i), self.navbar["result_page"][i],
898 i, title="{} Posteriors for multiple".format(i),
899 approximant=i, background_colour=self.colors[num]
900 )
901 html_file.make_banner(approximant=i, key=i)
902 ordered_parameters = self.categorize_parameters(
903 self.samples[i].keys()
904 )
905 ordered_parameters = [i for j in ordered_parameters for i in j[1]]
906 popular_options = self.popular_options
907 html_file.make_search_bar(
908 sidebar=[i for i in self.samples[i].keys()],
909 popular_options=popular_options + [{
910 "all": ", ".join(ordered_parameters)
911 }],
912 label=self.labels[num], code="combines"
913 )
914 html_file.make_footer(user=self.user, rundir=self.webdir)
915 html_file.close()
916 html_file = self.setup_page(
917 "{}_All".format(i), self.navbar["result_page"][i],
918 i, title="All posteriors for {}".format(i),
919 approximant=i, background_colour=self.colors[num]
920 )
921 html_file.make_banner(approximant=i, key=i)
922 for j in self.samples[i].keys():
923 html_file.make_banner(
924 approximant=j, _style="font-size: 26px;"
925 )
926 contents = [
927 [path + "{}_1d_posterior_{}.png".format(i, j)],
928 [
929 path + "{}_sample_evolution_{}.png".format(i, j),
930 path + "{}_autocorrelation_{}.png".format(i, j)
931 ]
932 ]
933 html_file.make_table_of_images(
934 contents=contents, rows=1, columns=2, code="changeimage")
935 html_file.close()
936 for j in self.categorize_parameters(self.samples[i].keys()):
937 if not len(j[1]):
938 continue
939 html_file = self.setup_page(
940 "{}_{}_all".format(i, j[0]), self.navbar["result_page"][i],
941 i, title="All posteriors for describing {}".format(j[0]),
942 approximant=i, background_colour=self.colors[num]
943 )
944 for k in j[1][1:]:
945 html_file.make_banner(
946 approximant=k, _style="font-size: 26px;"
947 )
948 contents = [
949 [path + "{}_1d_posterior_{}.png".format(i, k)],
950 [
951 path + "{}_sample_evolution_{}.png".format(i, k),
952 path + "{}_autocorrelation_{}.png".format(i, k)
953 ]
954 ]
955 html_file.make_table_of_images(
956 contents=contents, rows=1, columns=2, code="changeimage"
957 )
958 html_file.make_banner(
959 approximant="Summary Table", key="summary_table",
960 _style="font-size: 26px;"
961 )
962 _style = "margin-top:3em; margin-bottom:5em; max-width:1400px"
963 _class = "row justify-content-center"
964 html_file.make_container(style=_style)
965 html_file.make_div(4, _class=_class, _style=None)
966 headings = [" "] + self.key_data_headings.copy()
967 contents = []
968 for k in j[1][1:]:
969 row = [k]
970 row += self.key_data_table[i][k]
971 contents.append(row)
972 html_file.make_table(
973 headings=headings, contents=contents, heading_span=1,
974 accordian=False, format="table-hover",
975 sticky_header=True
976 )
977 html_file.end_div(4)
978 html_file.end_container()
979 html_file.export("{}_summary_{}.csv".format(j[0], i))
980 html_file.make_footer(user=self.user, rundir=self.webdir)
981 html_file.close()
983 def make_additional_plots_pages(self):
984 """Wrapper function for _make_additional_plots_pages
985 """
986 pages = [
987 "{}_{}_Additional".format(i, i) for i in self.labels if i in
988 self.existing_plot.keys()
989 ]
990 self.create_blank_html_pages(pages)
991 self._make_additional_plots_pages(pages)
993 def _make_additional_plots_pages(self, pages):
994 """Make the additional plots pages
996 Parameters
997 ----------
998 pages: list
999 list of pages that you wish to create
1000 """
1001 from PIL import Image
1002 for num, i in enumerate(self.labels):
1003 if i not in self.existing_plot.keys():
1004 continue
1005 html_file = self.setup_page(
1006 "{}_Additional".format(i), self.navbar["result_page"][i], i,
1007 title="Additional plots for {}".format(i), approximant=i,
1008 background_colour=self.colors[num]
1009 )
1010 html_file.make_banner(approximant=i, key="additional")
1011 if isinstance(self.existing_plot[i], list):
1012 images = sorted(
1013 self.existing_plot[i],
1014 key=lambda _path: Image.open(_path).size[1]
1015 )
1016 tol = 2.
1017 # if all images are of similar height, then grid them uniformly, else
1018 # grid by heights
1019 cond = all(
1020 Image.open(_path).size[1] / tol < Image.open(images[0]).size[1]
1021 for _path in images
1022 )
1023 if cond:
1024 image_contents = [
1025 [
1026 self.image_path["other"] + Path(_path).name for
1027 _path in images[j:4 + j]
1028 ] for j in range(0, len(self.existing_plot[i]), 4)
1029 ]
1030 else:
1031 heights = [Image.open(_path).size[1] for _path in images]
1032 image_contents = [
1033 [self.image_path["other"] + Path(images[0]).name]
1034 ]
1035 row = 0
1036 for num, _height in enumerate(heights[1:]):
1037 if _height / tol < heights[num]:
1038 image_contents[row].append(
1039 self.image_path["other"] + Path(images[num + 1]).name
1040 )
1041 else:
1042 row += 1
1043 image_contents.append(
1044 [self.image_path["other"] + Path(images[num + 1]).name]
1045 )
1046 margin_left = None
1047 else:
1048 image_contents = [
1049 [self.image_path["other"] + Path(self.existing_plot[i]).name]
1050 ]
1051 margin_left = "-250px"
1052 html_file = self.make_modal_carousel(
1053 html_file, image_contents, unique_id=True, autoscale=True,
1054 margin_left=margin_left
1055 )
1056 html_file.make_footer(user=self.user, rundir=self.webdir)
1057 html_file.close()
1059 def make_corner_pages(self):
1060 """Wrapper function for _make_corner_pages
1061 """
1062 pages = ["{}_{}_Corner".format(i, i) for i in self.labels]
1063 self.create_blank_html_pages(pages)
1064 self._make_corner_pages(pages)
1066 def _make_corner_pages(self, pages):
1067 """Make the corner pages
1069 Parameters
1070 ----------
1071 pages: list
1072 list of pages that you wish to create
1073 """
1074 for num, i in enumerate(self.labels):
1075 html_file = self.setup_page(
1076 "{}_Corner".format(i), self.navbar["result_page"][i], i,
1077 title="{} Corner Plots".format(i), approximant=i,
1078 background_colour=self.colors[num]
1079 )
1080 html_file.make_banner(approximant=i, key="corner")
1081 popular_options = self.popular_options
1082 if len(self.default_corner_params()):
1083 params = self.default_corner_params()
1084 included_parameters = [
1085 i for i in list(self.samples[i].keys()) if i in params
1086 ]
1087 popular_options += [{
1088 "all": ", ".join(included_parameters)
1089 }]
1090 else:
1091 included_parameters = list(self.samples[i].keys())
1092 html_file.make_search_bar(
1093 sidebar=included_parameters,
1094 popular_options=popular_options, label=i
1095 )
1096 html_file.make_footer(user=self.user, rundir=self.webdir)
1097 html_file.close()
1099 def make_config_pages(self):
1100 """Wrapper function for _make_config_pages
1101 """
1102 pages = ["{}_{}_Config".format(i, i) for i in self.labels]
1103 self.create_blank_html_pages(pages, stylesheets=pages)
1104 self._make_config_pages(pages)
1106 def _make_config_pages(self, pages):
1107 """Make the config pages
1109 Parameters
1110 ----------
1111 pages: list
1112 list of pages that you wish to create
1113 """
1114 for num, i in enumerate(self.labels):
1115 html_file = self.setup_page(
1116 "{}_Config".format(i), self.navbar["result_page"][i], i,
1117 title="{} Configuration".format(i), approximant=i,
1118 background_colour=self.colors[num]
1119 )
1120 html_file.make_banner(approximant=i, key="config")
1121 if self.config and num < len(self.config) and self.config[num]:
1122 with open(self.config[num], 'r') as f:
1123 contents = f.read()
1124 html_file.make_container()
1125 styles = html_file.make_code_block(
1126 language='ini', contents=contents
1127 )
1128 html_file.end_container()
1129 with open(
1130 "{0:s}/css/{1:s}_{2:s}_Config.css".format(
1131 self.webdir, i, i
1132 ), "w"
1133 ) as f:
1134 f.write(styles)
1135 _fix = False
1136 else:
1137 html_file.add_content(
1138 "<div class='row justify-content-center'; "
1139 "style='font-family: Arial-body; font-size: 14px'>"
1140 "<p style='margin-top:2.5em'> No configuration file was "
1141 "provided </p></div>"
1142 )
1143 _fix = True
1144 if i in self.analytic_priors.keys():
1145 if self.analytic_priors[i] is not None:
1146 html_file.make_div(indent=2, _class='paragraph')
1147 html_file.add_content(
1148 "Below is the prior file for %s" % (i)
1149 )
1150 html_file.end_div()
1151 html_file.make_container()
1152 styles = html_file.make_code_block(
1153 language='ini', contents=self.analytic_priors[i]
1154 )
1155 html_file.end_container()
1156 _fix = False
1157 html_file.make_footer(
1158 user=self.user, rundir=self.webdir, fix_bottom=_fix
1159 )
1160 html_file.close()
1162 def make_comparison_pages(self):
1163 """Wrapper function for _make_comparison_pages
1164 """
1165 pages = ["Comparison_{}".format(i) for i in self.same_parameters]
1166 pages += ["Comparison_Custom"]
1167 pages += ["Comparison_All"]
1168 pages += ["Comparison"]
1169 pages += [
1170 "Comparison_{}_all".format(j[0]) for j in
1171 self.categorize_parameters(self.same_parameters) if len(j[1])
1172 ]
1173 self.create_blank_html_pages(pages)
1174 self._make_comparison_pages(pages)
1176 def _make_comparison_pages(self, pages):
1177 """Make pages to compare all result files
1179 Parameters
1180 ----------
1181 pages: list
1182 list of pages that you wish to create
1183 """
1184 html_file = self.setup_page(
1185 "Comparison", self.navbar["comparison"], approximant="Comparison",
1186 title="Comparison Summary Page"
1187 )
1188 html_file.make_banner(approximant="Comparison", key="Comparison")
1189 path = self.image_path["other"]
1190 if len(self.default_comparison_homepage_plots()):
1191 contents = self.default_comparison_homepage_plots()
1192 html_file = self.make_modal_carousel(
1193 html_file, contents, unique_id=True
1194 )
1195 if self.custom_plotting:
1196 from glob import glob
1198 custom_plots = glob(
1199 os.path.join(
1200 self.webdir, "plots", "combined_custom_plotting_*"
1201 )
1202 )
1203 for num, i in enumerate(custom_plots):
1204 custom_plots[num] = path + i.split("/")[-1]
1205 image_contents = [
1206 custom_plots[i:4 + i] for i in range(0, len(custom_plots), 4)
1207 ]
1208 html_file = self.make_modal_carousel(
1209 html_file, image_contents, unique_id=True
1210 )
1211 path = self.image_path["other"]
1213 if self.comparison_stats is not None:
1214 for _num, _key in enumerate(["KS_test", "JS_test"]):
1215 if _key == "KS_test":
1216 html_file.make_banner(
1217 approximant="KS test", key="ks_test",
1218 _style="font-size: 26px;"
1219 )
1220 else:
1221 html_file.make_banner(
1222 approximant="JS test", key="js_test",
1223 _style="font-size: 26px;"
1224 )
1225 _style = "margin-top:3em; margin-bottom:5em; max-width:1400px"
1226 _class = "row justify-content-center"
1227 html_file.make_container(style=_style)
1228 html_file.make_div(4, _class=_class, _style=None)
1230 rows = range(len(self.labels))
1231 table_contents = {
1232 i: [
1233 [self.labels[j]] + self.comparison_stats[i][_num][j] for
1234 j in rows
1235 ] for i in self.same_parameters
1236 }
1237 _headings = [" "] + self.labels
1238 html_file.make_table(
1239 headings=_headings, format="table-hover scroll-table",
1240 heading_span=1, contents=table_contents, accordian=False,
1241 scroll_table=True
1242 )
1243 html_file.end_div(4)
1244 html_file.end_container()
1245 html_file.export("{}_total.csv".format(_key))
1246 html_file.make_footer(user=self.user, rundir=self.webdir)
1248 for num, i in enumerate(self.same_parameters):
1249 html_file = self.setup_page(
1250 "Comparison_{}".format(i), self.navbar["comparison"],
1251 title="Comparison PDF for {}".format(i),
1252 approximant="Comparison"
1253 )
1254 html_file.make_banner(approximant="Comparison", key="Comparison")
1255 path = self.image_path["other"]
1256 contents = [
1257 [path + "combined_1d_posterior_{}.png".format(i)],
1258 [
1259 path + "combined_cdf_{}.png".format(i),
1260 path + "combined_boxplot_{}.png".format(i)
1261 ]
1262 ]
1263 html_file.make_table_of_images(
1264 contents=contents, rows=1, columns=2, code="changeimage"
1265 )
1266 html_file.make_banner(
1267 approximant="Summary Table", key="summary_table",
1268 _style="font-size: 26px;"
1269 )
1270 _style = "margin-top:3em; margin-bottom:5em; max-width:1400px"
1271 _class = "row justify-content-center"
1272 html_file.make_container(style=_style)
1273 html_file.make_div(4, _class=_class, _style=None)
1274 headings = [" "] + self.key_data_headings.copy()
1275 contents = []
1276 for label in self.labels:
1277 row = [label]
1278 row += self.key_data_table[label][i]
1279 contents.append(row)
1280 html_file.make_table(
1281 headings=headings, contents=contents, heading_span=1,
1282 accordian=False, format="table-hover",
1283 sticky_header=True
1284 )
1285 html_file.end_div(4)
1286 html_file.end_container()
1287 html_file.export("comparison_summary_{}.csv".format(i))
1289 if self.comparison_stats is not None:
1290 for _num, _key in enumerate(["KS_test", "JS_test"]):
1291 if _key == "KS_test":
1292 html_file.make_banner(
1293 approximant="KS test", key="ks_test",
1294 _style="font-size: 26px;"
1295 )
1296 else:
1297 html_file.make_banner(
1298 approximant="JS test", key="js_test",
1299 _style="font-size: 26px;"
1300 )
1301 _style = "margin-top:3em; margin-bottom:5em; max-width:1400px"
1302 _class = "row justify-content-center"
1303 html_file.make_container(style=_style)
1304 html_file.make_div(4, _class=_class, _style=None)
1306 table_contents = [
1307 [self.labels[j]] + self.comparison_stats[i][_num][j]
1308 for j in rows
1309 ]
1310 _headings = [" "] + self.labels
1311 html_file.make_table(
1312 headings=_headings, format="table-hover",
1313 heading_span=1, contents=table_contents, accordian=False
1314 )
1315 html_file.end_div(4)
1316 html_file.end_container()
1317 html_file.export("{}_{}.csv".format(_key, i))
1319 html_file.make_footer(user=self.user, rundir=self.webdir)
1320 html_file.close()
1321 html_file = self.setup_page(
1322 "Comparison_Custom", self.navbar["comparison"],
1323 approximant="Comparison", title="Comparison Posteriors for multiple"
1324 )
1325 html_file.make_search_bar(
1326 sidebar=self.same_parameters, label="None", code="combines",
1327 popular_options=[
1328 {"all": ", ".join(self.same_parameters)}
1329 ]
1330 )
1331 html_file.make_footer(user=self.user, rundir=self.webdir)
1332 html_file.close()
1333 html_file = self.setup_page(
1334 "Comparison_All", self.navbar["comparison"],
1335 title="All posteriors for Comparison", approximant="Comparison"
1336 )
1337 html_file.make_banner(approximant="Comparison", key="Comparison")
1338 for j in self.same_parameters:
1339 html_file.make_banner(
1340 approximant=j, _style="font-size: 26px;"
1341 )
1342 contents = [
1343 [path + "combined_1d_posterior_{}.png".format(j)],
1344 [
1345 path + "combined_cdf_{}.png".format(j),
1346 path + "combined_boxplot_{}.png".format(j)
1347 ]
1348 ]
1349 html_file.make_table_of_images(
1350 contents=contents, rows=1, columns=2, code="changeimage")
1351 html_file.close()
1352 for j in self.categorize_parameters(self.same_parameters):
1353 if not len(j[1]):
1354 continue
1355 html_file = self.setup_page(
1356 "Comparison_{}_all".format(j[0]), self.navbar["comparison"],
1357 title="All posteriors for describing {}".format(j[0]),
1358 approximant="Comparison"
1359 )
1360 for k in j[1][1:]:
1361 html_file.make_banner(
1362 approximant=k, _style="font-size: 26px;"
1363 )
1364 contents = [
1365 [path + "combined_1d_posterior_{}.png".format(k)],
1366 [
1367 path + "combined_cdf_{}.png".format(k),
1368 path + "combined_boxplot_{}.png".format(k)
1369 ]
1370 ]
1371 html_file.make_table_of_images(
1372 contents=contents, rows=1, columns=2, code="changeimage"
1373 )
1374 html_file.make_footer(user=self.user, rundir=self.webdir)
1375 html_file.close()
1377 def make_interactive_pages(self):
1378 """Wrapper function for _make_interactive_pages
1379 """
1380 pages = ["{}_{}_Interactive_Corner".format(i, i) for i in self.labels]
1381 if self.make_comparison:
1382 pages += ["Comparison_Interactive_Ridgeline"]
1383 self.create_blank_html_pages(pages)
1384 savedir = os.path.join(self.webdir, "plots")
1385 html_files = glob(os.path.join(savedir, "*interactive*.html"))
1386 html_files += glob(os.path.join(savedir, "corner", "*interactive*.html"))
1387 self._make_interactive_pages(pages, html_files)
1389 def _make_interactive_pages(self, pages, html_files):
1390 """Make a page that shows all interactive plots
1392 Parameters
1393 ----------
1394 pages: list
1395 list of pages that you wish to create
1396 """
1397 for num, i in enumerate(self.labels):
1398 html_file = self.setup_page(
1399 "{}_Interactive_Corner".format(i),
1400 self.navbar["result_page"][i], i,
1401 title="{} Interactive Corner Plots".format(i), approximant=i,
1402 background_colour=self.colors[num]
1403 )
1404 html_file.make_banner(approximant=i, key="interactive_corner")
1405 html_file.make_container()
1406 corner_files = [
1407 figure for figure in html_files if "/corner/" in figure
1408 and i in figure
1409 ]
1410 for plot in corner_files:
1411 with open(plot, "r") as f:
1412 data = f.read()
1413 html_file.add_content(data)
1414 html_file.end_container()
1415 html_file.make_footer(user=self.user, rundir=self.webdir)
1416 html_file.close()
1417 if not self.make_comparison:
1418 return
1419 html_file = self.setup_page(
1420 "Comparison_Interactive_Ridgeline", self.navbar["comparison"],
1421 approximant="Comparison", title="Interactive Ridgeline Plots"
1422 )
1423 html_file.make_banner(
1424 approximant="Comparison", key="interactive_ridgeline"
1425 )
1426 posterior_files = [
1427 figure for figure in html_files if "ridgeline" in figure
1428 ]
1429 for plot in posterior_files:
1430 with open(plot, "r") as f:
1431 data = f.read()
1432 parameter = \
1433 plot.split("interactive_ridgeline_")[1].split(".html")[0]
1434 html_file.make_banner(
1435 approximant=parameter, _style="font-size: 26px;"
1436 )
1437 html_file.make_container()
1438 html_file.add_content(data)
1439 html_file.end_container()
1440 html_file.make_footer(user=self.user, rundir=self.webdir)
1441 html_file.close()
1443 def make_error_page(self):
1444 """Wrapper function for _make_error_page
1445 """
1446 pages = ["error"]
1447 self.create_blank_html_pages(pages)
1448 self._make_error_page(pages)
1450 def _make_error_page(self, pages):
1451 """Make a page that is shown when something goes wrong
1453 Parameters
1454 ----------
1455 pages: list
1456 list of pages that you wish to create
1457 """
1458 webpage.make_html(web_dir=self.webdir, pages=pages)
1459 html_file = webpage.open_html(
1460 web_dir=self.webdir, base_url=self.base_url, html_page="error"
1461 )
1462 html_file.make_div(
1463 _class="jumbotron text-center",
1464 _style="background-color: #D3D3D3; margin-bottom:0"
1465 )
1466 html_file.make_div(
1467 _class="container",
1468 _style="margin-top:1em; background-color: #D3D3D3; width: 45em"
1469 )
1470 html_file.add_content(
1471 "<h1 style='color:white; font-size: 8em'>404</h1>"
1472 )
1473 html_file.add_content(
1474 "<h2 style='color:white;'> Something went wrong... </h2>"
1475 )
1476 html_file.end_div()
1477 html_file.end_div()
1478 html_file.close()
1480 def make_version_page(self):
1481 """Wrapper function for _make_version_page
1482 """
1483 pages = ["Version"]
1484 self.create_blank_html_pages(pages, stylesheets=pages)
1485 self._make_version_page(pages)
1487 def _make_version_page(self, pages):
1488 """Make a page to display the version information
1490 Parameters
1491 ----------
1492 pages: list
1493 list of pages that you wish to create
1494 """
1495 from pesummary._version_helper import install_path
1497 html_file = webpage.open_html(
1498 web_dir=self.webdir, base_url=self.base_url, html_page="Version"
1499 )
1500 html_file = self.setup_page(
1501 "Version", self.navbar["home"], title="Version Information"
1502 )
1503 html_file.make_banner(approximant="Version", key="Version")
1504 contents = __version_string__
1505 contents += install_path(return_string=True)
1506 for i in self.labels:
1507 contents = (
1508 "# {} version information\n\n{}_version={}\n\n".format(
1509 i, i, self.file_versions[i]
1510 )
1511 ) + contents
1512 html_file.make_container()
1513 styles = html_file.make_code_block(language='shell', contents=contents)
1514 with open('{0:s}/css/Version.css'.format(self.webdir), 'w') as f:
1515 f.write(styles)
1516 html_file.end_container()
1517 packages = self.package_information["packages"]
1518 style = "margin-top:{}; margin-bottom:{};"
1519 if len(packages):
1520 html_file.make_table(
1521 headings=[x.title().replace('_', ' ') for x in packages.dtype.names],
1522 contents=[[pp.decode("utf-8") for pp in pkg] for pkg in packages],
1523 accordian=False, style=style.format("1em", "1em")
1524 )
1525 if self.package_information["manager"] == "conda":
1526 html_file.export(
1527 "environment.yml", margin_top="1em", csv=False,
1528 conda=True
1529 )
1530 else:
1531 html_file.export(
1532 "requirements.txt", margin_top="1em", csv=False,
1533 requirements=True
1534 )
1535 html_file.make_footer(user=self.user, rundir=self.webdir)
1536 html_file.close()
1538 def make_logging_page(self):
1539 """Wrapper function for _make_logging_page
1540 """
1541 pages = ["Logging"]
1542 self.create_blank_html_pages(pages, stylesheets=pages)
1543 self._make_logging_page(pages)
1545 def _make_logging_page(self, pages):
1546 """Make a page to display the logging output from PESummary
1548 Parameters
1549 ----------
1550 pages: list
1551 list of pages that you wish to create
1552 """
1553 html_file = webpage.open_html(
1554 web_dir=self.webdir, base_url=self.base_url, html_page="Logging"
1555 )
1556 html_file = self.setup_page(
1557 "Logging", self.navbar["home"], title="Logger Information"
1558 )
1559 html_file.make_banner(approximant="Logging", key="Logging")
1560 path = pesummary.__file__[:-12]
1561 log_file = LOG_FILE
1562 if not os.path.isfile(log_file):
1563 log_file = ".tmp/pesummary/no_log_information.log"
1564 with open(log_file, "w") as f:
1565 f.writelines(["No log information stored"])
1567 with open(log_file, 'r') as f:
1568 contents = f.read()
1569 html_file.make_container()
1570 styles = html_file.make_code_block(language='shell', contents=contents)
1571 with open('{0:s}/css/Logging.css'.format(self.webdir), 'w') as f:
1572 f.write(styles)
1573 html_file.end_container()
1574 html_file.make_footer(user=self.user, rundir=self.webdir)
1575 html_file.close()
1577 def make_about_page(self):
1578 """Wrapper function for _make_about_page
1579 """
1580 pages = ["About"]
1581 self.create_blank_html_pages(pages, stylesheets=pages)
1582 self._make_about_page(pages)
1584 def _make_about_page(self, pages):
1585 """Make a page informing the user of the run directory, user that ran
1586 the job etc
1588 Parameters
1589 ----------
1590 pages: list
1591 list of pages you wish to create
1592 """
1593 html_file = webpage.open_html(
1594 web_dir=self.webdir, base_url=self.base_url, html_page="About"
1595 )
1596 html_file = self.setup_page(
1597 "About", self.navbar["home"], title="About"
1598 )
1599 html_file.make_banner(approximant="About", key="About")
1600 html_file.make_banner(
1601 approximant="On the command-line", key="command_line",
1602 _style="font-size: 26px;", link=os.getcwd()
1603 )
1604 command = ""
1605 for i in sys.argv:
1606 command += " "
1607 if i[0] == "-":
1608 command += "\n"
1609 command += "{}".format(i)
1610 html_file.make_container()
1611 styles = html_file.make_code_block(language="shell", contents=command)
1612 with open('{0:s}/css/About.css'.format(self.webdir), 'w') as g:
1613 g.write(styles)
1614 html_file.end_container()
1615 html_file.export(
1616 "pesummary.sh", csv=False, json=False, shell=True,
1617 margin_top="-4em"
1618 )
1619 html_file.make_footer(
1620 user=self.user, rundir=self.webdir, fix_bottom=True
1621 )
1622 html_file.close()
1624 def make_downloads_page(self):
1625 """Wrapper function for _make_downloads_page
1626 """
1627 pages = ["Downloads"]
1628 self.create_blank_html_pages(pages)
1629 self._make_downloads_page(pages)
1631 def _make_downloads_page(self, pages, fix_bottom=False):
1632 """Make a page with links to files which can be downloaded
1634 Parameters
1635 ----------
1636 pages: list
1637 list of pages you wish to create
1638 """
1639 html_file = webpage.open_html(
1640 web_dir=self.webdir, base_url=self.base_url, html_page="Downloads"
1641 )
1642 html_file = self.setup_page(
1643 "Downloads", self.navbar["home"], title="Downloads"
1644 )
1645 html_file.make_banner(approximant="Downloads", key="Downloads")
1646 html_file.make_container()
1647 base_string = "{} can be downloaded <a href={} download>here</a>"
1648 style = "margin-top:{}; margin-bottom:{};"
1649 headings = ["Description"]
1650 metafile_row = [
1651 [
1652 base_string.format(
1653 "The complete metafile containing all information "
1654 "about the analysis",
1655 self.results_path["other"] + self._metafile
1656 )
1657 ]
1658 ]
1659 if self.external_hdf5_links:
1660 string = ""
1661 for label in self.labels:
1662 string += (
1663 "The hdf5 sub file for {} can be downloaded "
1664 "<a href={} download>here</a>. ".format(
1665 label, self.results_path["other"] + "_{}.h5".format(
1666 label
1667 )
1668 )
1669 )
1670 metafile_row += [
1671 [
1672 "The complete metafile uses external hdf5 links. Each "
1673 "analysis is therefore stored in seperate meta files. "
1674 "{}".format(string)
1675 ]
1676 ]
1677 metafile_row += [
1678 [
1679 (
1680 "Information about reading this metafile can be seen "
1681 " <a href={}>here</a>".format(
1682 "https://lscsoft.docs.ligo.org/pesummary/"
1683 "stable/data/reading_the_metafile.html"
1684 )
1685 )
1686 ]
1687 ]
1688 html_file.make_table(
1689 headings=headings, contents=metafile_row,
1690 accordian=False, style=style.format("1em", "1em")
1691 )
1692 for num, i in enumerate(self.labels):
1693 table_contents = self._make_entry_in_downloads_table(
1694 html_file, i, num, base_string
1695 )
1696 if table_contents is not None:
1697 html_file.make_table(
1698 headings=headings, contents=table_contents, accordian=False
1699 )
1700 html_file.end_container()
1701 html_file.make_footer(
1702 user=self.user, rundir=self.webdir, fix_bottom=fix_bottom
1703 )
1704 html_file.close()
1706 def _make_entry_in_downloads_table(self, html_file, label, num, base_string):
1707 """Make a label specific entry into the downloads table
1709 Parameters
1710 ----------
1711 label: str
1712 the label you wish to add to the downloads table
1713 base_string: str
1714 the download string
1715 """
1716 import glob
1717 identifier = label if not self.mcmc_samples else "chain"
1718 _original = glob.glob(
1719 os.path.join(self.webdir, "samples", "{}_*".format(identifier))
1720 )
1721 html_file.add_content(
1722 "<div class='banner', style='margin-left:-4em'>{}</div>".format(
1723 label
1724 )
1725 )
1726 if not self.mcmc_samples and len(_original) > 0:
1727 table_contents = [
1728 [
1729 base_string.format(
1730 "Original file provided to PESummary",
1731 self.results_path["other"] + Path(_original[0]).name
1732 )
1733 ]
1734 ]
1735 elif self.mcmc_samples and len(_original) > 0:
1736 table_contents = [
1737 [
1738 base_string.format(
1739 "Original chain {} provided to PESummary".format(num),
1740 self.results_path["other"] + Path(_original[num]).name
1741 )
1742 ] for num in range(len(_original))
1743 ]
1744 else:
1745 table_contents = []
1746 table_contents.append(
1747 [
1748 base_string.format(
1749 "Dat file containing posterior samples",
1750 self.results_path["other"] + "%s_pesummary.dat" % (label)
1751 )
1752 ]
1753 )
1754 if self.config is not None and self.config[num] is not None:
1755 table_contents.append(
1756 [
1757 base_string.format(
1758 "Config file used for this analysis",
1759 self.config_path["other"] + "%s_config.ini" % (label)
1760 )
1761 ]
1762 )
1763 return table_contents
1765 def make_notes_page(self):
1766 """Wrapper function for _make_notes_page
1767 """
1768 pages = ["Notes"]
1769 self.create_blank_html_pages(pages, stylesheets=pages)
1770 self._make_notes_page(pages)
1772 def _make_notes_page(self, pages):
1773 """Make a page to display the custom notes
1775 Parameters
1776 ----------
1777 pages: list
1778 list of pages that you wish to create
1779 """
1780 html_file = webpage.open_html(
1781 web_dir=self.webdir, base_url=self.base_url, html_page="Notes"
1782 )
1783 html_file = self.setup_page(
1784 "Notes", self.navbar["home"], title="Notes"
1785 )
1786 html_file.make_banner(approximant="Notes", key="Notes")
1787 html_file.make_container()
1788 styles = html_file.make_code_block(
1789 language='shell', contents=self.notes
1790 )
1791 with open('{0:s}/css/Notes.css'.format(self.webdir), 'w') as f:
1792 f.write(styles)
1793 html_file.end_container()
1794 html_file.make_footer(user=self.user, rundir=self.webdir)
1795 html_file.close()
1797 def generate_specific_javascript(self):
1798 """Tailor the javascript to the specific situation.
1799 """
1800 path = self.webdir + "/js/grab.js"
1801 existing = open(path)
1802 existing = existing.readlines()
1803 ind = existing.index(" if ( param == approximant ) {\n")
1804 content = existing[:ind]
1805 for i in [list(j.keys())[0] for j in self._result_page_links()]:
1806 content.append(" if ( param == \"%s\" ) {\n" % (i))
1807 content.append(" approx = \"None\" \n")
1808 content.append(" }\n")
1809 for i in existing[ind + 1:]:
1810 content.append(i)
1811 new_file = open(path, "w")
1812 new_file.writelines(content)
1813 new_file.close()
1815 def default_categories(self):
1816 """Return the default categories
1817 """
1818 categories = {
1819 "A-D": {
1820 "accept": ["a", "A", "b", "B", "c", "C", "d", "D"], "reject": []
1821 },
1822 "E-F": {
1823 "accept": ["e", "E", "f", "F", "g", "G", "h", "H"], "reject": []
1824 },
1825 "I-L": {
1826 "accept": ["i", "I", "j", "J", "k", "K", "l", "L"], "reject": []
1827 },
1828 "M-P": {
1829 "accept": ["m", "M", "n", "N", "o", "O", "p", "P"], "reject": []
1830 },
1831 "Q-T": {
1832 "accept": ["q", "Q", "r", "R", "s", "S", "t", "T"], "reject": []
1833 },
1834 "U-X": {
1835 "accept": ["u", "U", "v", "V", "w", "W", "x", "X"], "reject": []
1836 },
1837 "Y-Z": {
1838 "accept": ["y", "Y", "z", "Z"], "reject": []
1839 }
1840 }
1841 return categories
1843 def default_images_for_result_page(self, label):
1844 """Return the default images that will be displayed on the result page
1845 """
1846 return [], [], []
1848 def default_popular_options(self):
1849 """Return a list of default options
1850 """
1851 return []
1853 def default_comparison_homepage_plots(self):
1854 """Return a list of default plots for the comparison homepage
1855 """
1856 return []
1858 def default_corner_params(self):
1859 """Return a list of default corner parameters used by the corner
1860 plotting function
1861 """
1862 return []
1864 def add_existing_data(self):
1865 """
1866 """
1867 from pesummary.utils.utils import _add_existing_data
1869 self = _add_existing_data(self)
1871 def add_to_expert_pages(self, path, label):
1872 """Additional expert plots to add beyond the default. This returns a
1873 dictionary keyed by the parameter, with values providing the path
1874 to the additional plots you wish to add. The plots are a 2d list
1875 where each sublist represents a row in the table of images.
1877 Parameters
1878 ----------
1879 path: str
1880 path to the image directory
1881 label: str
1882 label of the plot you wish to add
1883 """
1884 mydict = {}
1885 contour_base = path + "{}_2d_contour_{}_{}.png"
1886 histogram_base = path + "{}_1d_posterior_{}_{}.png"
1887 if not hasattr(self.samples[label], "debug_keys"):
1888 return mydict
1889 for param in self.samples[label].debug_keys():
1890 if "_non_reweighted" in param:
1891 base_param = param.split("_non_reweighted")[0][1:]
1892 if base_param in self.samples[label].keys():
1893 mydict[base_param] = [[
1894 histogram_base.format(label, base_param, param),
1895 contour_base.format(label, base_param, param)
1896 ]]
1897 return mydict
1899 @property
1900 def additional_1d_pages(self):
1901 """Additional 1d histogram pages beyond one for each parameter. You may,
1902 for instance, want a 1d histogram page which combines multiple
1903 parameters. This returns a dictionary, keyed by the new 1d histogram
1904 page, with values indicating the parameters you wish to include on this
1905 page. Only the 1d marginalized histograms are shown.
1906 """
1907 return None