Coverage for pesummary/cli/summaryreview.py: 27.8%

360 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-05-02 08:42 +0000

1#! /usr/bin/env python 

2 

3# Licensed under an MIT style license -- see LICENSE.md 

4 

5from pesummary.core.cli.parser import ArgumentParser as _ArgumentParser 

6from pesummary.gw.file.standard_names import standard_names, lalinference_map 

7from pesummary.utils.samples_dict import SamplesDict 

8from pesummary.io import read 

9from pesummary.core.webpage.main import _WebpageGeneration 

10from pesummary.utils.utils import logger 

11import subprocess 

12import numpy as np 

13import sys 

14import shutil 

15import os 

16from glob import glob 

17from getpass import getuser 

18 

19__author__ = ["Charlie Hoy <charlie.hoy@ligo.org>"] 

20 

21 

22REVIEW_TESTS = [ 

23 "all", "core_plots", "ligo.skymap", "spin_disk" 

24] 

25 

26 

27class ArgumentParser(_ArgumentParser): 

28 def _pesummary_options(self): 

29 options = super(ArgumentParser, self)._pesummary_options() 

30 options.update( 

31 { 

32 "--samples": { 

33 "short": "-s", 

34 "help": "Posterior samples hdf5 file", 

35 }, 

36 "--test": { 

37 "short": "-t", 

38 "help": "Review test that you wish to perform", 

39 "choices": REVIEW_TESTS, 

40 "default": "all" 

41 } 

42 } 

43 ) 

44 return options 

45 

46 

47def get_executable_path(executable): 

48 """Return the path to the executable 

49 

50 Parameters 

51 ---------- 

52 executable: str 

53 name of the executable 

54 """ 

55 try: 

56 path = subprocess.check_output(["which", "%s" % (executable)]) 

57 path = path.decode("utf-8") 

58 except Exception: 

59 path = None 

60 return path 

61 

62 

63def make_cli(executable, default_arguments, add_symbol=False): 

64 """Generate a command line 

65 

66 Parameters 

67 ---------- 

68 executable: str 

69 executable you wish to run 

70 default_arguments: list 

71 list of arguments you wish to pass to the executable 

72 add_symbol: Bool, optional 

73 if True, prepend the cli with a '$' symbol 

74 """ 

75 executable_path = get_executable_path(executable) 

76 if executable_path is None: 

77 raise Exception( 

78 "'{}' is not installed in your environment.".format(executable) 

79 ) 

80 cli = executable + " " + " ".join(default_arguments) 

81 if add_symbol: 

82 cli = "$ {}".format(cli) 

83 return cli 

84 

85 

86def _launch_lalinference_cli( 

87 webdir, path_to_results_file, trigger_file=None, add_symbol=False 

88): 

89 """Command line to launch the lalinference job 

90 

91 Parameters 

92 ---------- 

93 webdir: str 

94 path to the directory to store the output pages 

95 path_to_results_file: str 

96 path to the results file. Must be compatible with the LALInference 

97 pipeline 

98 trigger_file: str, optional 

99 path to an xml trigger file. 

100 add_symbol: Bool, optional 

101 if True, prepend the cli with a '$' symbol 

102 """ 

103 webdir += "/lalinference" 

104 default_arguments = ["--skyres", "0.5", "--outpath", webdir, 

105 path_to_results_file] 

106 

107 if trigger_file is not None: 

108 default_arguments.append("--trig") 

109 default_arguments.append(trigger_file) 

110 

111 cli = make_cli("cbcBayesPostProc", default_arguments, add_symbol=add_symbol) 

112 return [cli] 

113 

114 

115def launch_lalinference(webdir, path_to_results_file, trigger_file=None): 

116 """Launch a subprocess to generate the lalinference pages 

117 

118 Parameters 

119 ---------- 

120 webdir: str 

121 path to the directory to store the output pages 

122 path_to_results_file: str 

123 path to the results file. Must be compatible with the LALInference 

124 pipeline 

125 trigger_file: str, optional 

126 path to an xml trigger file. 

127 """ 

128 cli = _launch_lalinference_cli( 

129 webdir, path_to_results_file, trigger_file=trigger_file, add_symbol=False 

130 ) 

131 logger.info("Running %s" % (cli)) 

132 ess = subprocess.Popen( 

133 cli, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

134 ess.wait() 

135 

136 

137def _launch_skymap_cli( 

138 webdir, path_to_results_file, add_symbol=False, multi_process=1 

139): 

140 """Command lines to launch to the skymap job 

141 

142 Parameters 

143 ---------- 

144 webdir: str 

145 path to the directory to store the output pages 

146 path_to_results_file: str 

147 path to the results file. Must be compatible with the LALInference 

148 pipeline 

149 trigger_file: str, optional 

150 path to an xml trigger file. 

151 add_symbol: Bool, optional 

152 if True, prepend each cli with a '$' symbol 

153 multi_process: int, optional 

154 number of cpus to run on 

155 """ 

156 cli = [] 

157 default_arguments = [ 

158 path_to_results_file, "-j {}".format(multi_process), "--enable-multiresolution", 

159 "--outdir", webdir 

160 ] 

161 cli.append( 

162 make_cli("ligo-skymap-from-samples", default_arguments, add_symbol=add_symbol) 

163 ) 

164 default_arguments = [ 

165 "{}/skymap.fits".format(webdir), "--annotate", "--contour 50 90", 

166 "-o {}/skymap.png".format(webdir) 

167 ] 

168 cli.append( 

169 make_cli("ligo-skymap-plot", default_arguments, add_symbol=add_symbol) 

170 ) 

171 default_arguments = [ 

172 "{}/skymap.fits".format(webdir), "-p 50 90", 

173 "-o {}/skymap.txt".format(webdir) 

174 ] 

175 cli.append( 

176 make_cli("ligo-skymap-stats", default_arguments, add_symbol=add_symbol) 

177 ) 

178 return cli 

179 

180 

181def launch_skymap(webdir, path_to_results_file, multi_process=1): 

182 """Generate a skymap with the `ligo.skymap` package. 

183 

184 Parameters 

185 ---------- 

186 webdir: str 

187 path to the directory to store the output pages 

188 path_to_results_file: str 

189 path to the results file. Must be compatible with the LALInference 

190 pipeline 

191 multi_process: int, optional 

192 number of cpus to run on 

193 """ 

194 webdir += "/ligo_skymap" 

195 cli = _launch_skymap_cli(webdir, path_to_results_file, multi_process=multi_process) 

196 for _cli in cli: 

197 ess = subprocess.run(_cli, shell=True) 

198 

199 

200def _launch_pesummary_cli( 

201 webdir, path_to_results_file, trigger_file=None, add_symbol=False 

202): 

203 """Command lines to launch the pesummary job 

204 

205 Parameters 

206 ---------- 

207 webdir: str 

208 path to the directory to store the output pages 

209 path_to_results_file: str 

210 path to the results file. Must be compatible with the LALInference 

211 pipeline 

212 trigger_file: str, optional 

213 path to an xml trigger file. 

214 multi_process: int, optional 

215 number of cpus to run on 

216 """ 

217 executable = "summarypages" 

218 executable_path = get_executable_path(executable) 

219 

220 if executable_path is None: 

221 raise Exception( 

222 "'summarypages' is not installed in your environment. failed " 

223 "to generate PESummary pages") 

224 

225 webdir += "/pesummary" 

226 default_arguments = ["--webdir", webdir, "--samples", path_to_results_file, 

227 "--approximant", "IMRPhenomPv2", "--gw", 

228 "--labels", "pesummary", "--cosmology", "planck15_lal", 

229 "--multi_process 18"] 

230 

231 if trigger_file is not None: 

232 default_arguments.append("--trig_file") 

233 default_arguments.append(trigger_file) 

234 

235 cli = executable + " " + " ".join(default_arguments) 

236 if add_symbol: 

237 cli = "$ {}".format(cli) 

238 return [cli] 

239 

240 

241def launch_pesummary( 

242 webdir, path_to_results_file, trigger_file=None, multi_process=1 

243): 

244 """Launch a subprocess to generate the PESummary pages 

245 

246 Parameters 

247 ---------- 

248 webdir: str 

249 path to the directory to store the output pages 

250 path_to_results_file: str 

251 path to the results file. Must be compatible with the LALInference 

252 pipeline 

253 trigger_file: str, optional 

254 path to an xml trigger file. 

255 multi_process: int, optional 

256 number of cpus to run on 

257 """ 

258 cli = _launch_pesummary_cli( 

259 webdir, path_to_results_file, trigger_file=trigger_file 

260 )[0] 

261 executable = "summarypages" 

262 executable_path = get_executable_path(executable) 

263 

264 if executable_path is None: 

265 raise Exception( 

266 "'summarypages' is not installed in your environment. failed " 

267 "to generate PESummary pages") 

268 

269 webdir += "/pesummary" 

270 default_arguments = ["--webdir", webdir, "--samples", path_to_results_file, 

271 "--approximant", "IMRPhenomPv2", "--gw", 

272 "--labels", "pesummary", "--cosmology", "planck15_lal", 

273 "--multi_process {}".format(multi_process)] 

274 

275 if trigger_file is not None: 

276 default_arguments.append("--trig_file") 

277 default_arguments.append(trigger_file) 

278 

279 cli = executable + " " + " ".join(default_arguments) 

280 logger.info("Running %s" % (cli)) 

281 ess = subprocess.run(cli, shell=True) 

282 

283 

284def _launch_spin_disk_script(): 

285 """Script to run which generates a spin disk using pesummary and a spin 

286 disk using the script used in GWTC1 

287 """ 

288 script = """ 

289 import h5py 

290 from pesummary.gw.fetch import fetch 

291 from pesummary import cli 

292 

293 base = "https://ldas-jobs.ligo.caltech.edu/~charlie.hoy/projects/GWTC1/" 

294 f = fetch( 

295 base + "plot_spin_disks.py", read_file=False, delete_on_exit=True, 

296 outdir=cli.__path__[0] 

297 ) 

298 f = fetch( 

299 base + "bounded_2d_kde.py", read_file=False, delete_on_exit=True, 

300 outdir=cli.__path__[0] 

301 ) 

302 from .plot_spin_disks import plot_spindisk_with_colorbar 

303 path_to_pesummary_file = os.path.join( 

304 webdir, "pesummary", "samples", "posterior_samples.h5" 

305 ) 

306 try: 

307 os.makedirs(os.path.join(webdir, "spin_disk")) 

308 except FileExistsError: 

309 pass 

310 f = read(path_to_pesummary_file) 

311 samples = f.samples_dict["pesummary"] 

312 fig = samples.plot(type="spin_disk", colorbar=True, cmap="Blues") 

313 fig.savefig("{}/spin_disk/pesummary.png".format(webdir)) 

314 fig.close() 

315 f = h5py.File(path_to_results_file, 'r') 

316 keys = list(f["lalinference"].keys()) 

317 samples = f["lalinference"][keys[0]]["posterior_samples"] 

318 if "costilt1" in samples.dtype.names: 

319 pass 

320 else: 

321 samples = SamplesDict({ 

322 "a1": samples["a1"], "a2": samples["a2"], 

323 "costilt1": np.cos(samples["tilt1"]), "costilt2": np.cos(samples["tilt2"]) 

324 }).to_structured_array() 

325 fig = plot_spindisk_with_colorbar( 

326 samples, None, "Blues", plot_event_label=False, Na=25, Nt=25, 

327 return_maxP_no_plot=False, threshold=True 

328 ) 

329 fig.savefig("{}/spin_disk/GWTC1.png".format(webdir)) 

330 f.close() 

331 """ 

332 return "\n".join([line[4:] for line in script.split("\n")]) 

333 

334 

335def launch_spin_disk(webdir, path_to_results_file): 

336 """Generate a spin disk plot using both pesummary and code from GWTC1 

337 """ 

338 exec(_launch_spin_disk_script()) 

339 

340 

341def get_list_of_plots(webdir, lalinference=False, pesummary=False): 

342 """Get a list of plots generated by either lalinference or pesummary 

343 

344 Parameters 

345 ---------- 

346 webdir: str 

347 path to the directory to store the output pages 

348 lalinference: Bool 

349 if True, return the plots generated by LALInference. Default False 

350 pesummary: Bool 

351 if True, return the plots generated by PESummary. Default False 

352 """ 

353 from glob import glob 

354 

355 if lalinference: 

356 histogram_plots = sorted( 

357 glob(webdir + "/lalinference/1Dpdf/*.png")) 

358 params = [ 

359 i.split("/")[-1].split(".png")[0] for i in histogram_plots] 

360 elif pesummary: 

361 histogram_plots = sorted( 

362 glob(webdir + "/pesummary/plots/*_1d_posterior*.png")) 

363 params = [ 

364 i.split("/")[-1].split("_1d_posterior_")[1].split(".png")[0] for i 

365 in histogram_plots] 

366 return histogram_plots, params 

367 

368 

369class WebpageGeneration(_WebpageGeneration): 

370 """Class to handle webpage generation displaying the outcome from the review 

371 

372 Parameters 

373 ---------- 

374 webdir: str 

375 the web directory of the run 

376 path_to_results_file: str 

377 the path to the lalinference h5 file 

378 *args: tuple 

379 all args passed to the _WebpageGeneration class 

380 **kwargs: dict 

381 all kwargs passed to the _WebpageGeneration class 

382 """ 

383 def __init__(self, webdir, path_to_results_file, *args, test="all", **kwargs): 

384 self.path_to_results_file = os.path.abspath(path_to_results_file) 

385 self.test = test 

386 self.lalinference_path = os.path.abspath(os.path.join( 

387 webdir, "lalinference", "posterior_samples.dat" 

388 )) 

389 self.pesummary_path = os.path.abspath(os.path.join( 

390 webdir, "pesummary", "samples", "posterior_samples.h5" 

391 )) 

392 lalinference = np.genfromtxt(self.lalinference_path, names=True) 

393 pesummary_dict = read(self.pesummary_path).samples_dict["pesummary"] 

394 _lalinference_dict = { 

395 param: lalinference[param] for param in lalinference.dtype.names 

396 } 

397 params = _lalinference_dict.keys() 

398 lalinference_dict = {} 

399 for param, data in _lalinference_dict.items(): 

400 if param in standard_names.keys(): 

401 lalinference_dict[standard_names[param]] = data 

402 elif param in [ 

403 _param.lower() for _param in pesummary_dict.keys() 

404 ]: 

405 pp = [ 

406 _param for _param in pesummary_dict.keys() if param == _param.lower() 

407 ][0] 

408 lalinference_dict[pp] = data 

409 else: 

410 lalinference_dict[param] = data 

411 samples = { 

412 "lalinference": SamplesDict(lalinference_dict), 

413 "pesummary": read( 

414 os.path.join(webdir, "pesummary", "samples", "posterior_samples.h5") 

415 ).samples_dict["pesummary"] 

416 } 

417 super(WebpageGeneration, self).__init__( 

418 *args, webdir=webdir, labels=list(samples.keys()), samples=samples, 

419 user=getuser(), **kwargs 

420 ) 

421 self.abswebdir = os.path.abspath(self.webdir) 

422 parameters = [list(self.samples[key].keys()) for key in self.samples.keys()] 

423 params = list(set.intersection(*[set(l) for l in parameters])) 

424 self.same_parameters = params 

425 self.copy_css_and_js_scripts() 

426 

427 def copy_css_and_js_scripts(self): 

428 """Copy css and js scripts from the package to the web directory 

429 """ 

430 from pesummary import core 

431 files_to_copy = [] 

432 path = core.__path__[0] 

433 scripts = glob(os.path.join(path, "js", "*.js")) 

434 for i in scripts: 

435 files_to_copy.append( 

436 [i, os.path.join(self.webdir, "js", os.path.basename(i))] 

437 ) 

438 scripts = glob(os.path.join(path, "css", "*.css")) 

439 for i in scripts: 

440 files_to_copy.append( 

441 [i, os.path.join(self.webdir, "css", os.path.basename(i))] 

442 ) 

443 for _dir in ["js", "css"]: 

444 try: 

445 os.mkdir(os.path.join(self.webdir, _dir)) 

446 except FileExistsError: 

447 pass 

448 for ff in files_to_copy: 

449 shutil.copy(ff[0], ff[1]) 

450 

451 def generate_webpages(self): 

452 """Generate all webpages for all result files passed 

453 """ 

454 self.make_home_pages() 

455 if self.test == "core_plots" or self.test == "all": 

456 self.make_comparison_core_plots() 

457 self.make_comparison_samples() 

458 if self.test == "skymap" or self.test == "all": 

459 self.make_comparison_skymap() 

460 if self.test == "spin_disk" or self.test == "all": 

461 self.make_comparison_spin_disk() 

462 self.generate_specific_javascript() 

463 

464 def make_navbar_for_comparison_page(self): 

465 """Make a navbar for the comparison homepage 

466 """ 

467 links = ["home"] 

468 comparison = ["Comparison"] 

469 sub_comparison = [] 

470 if self.test == "core_plots" or self.test == "all": 

471 sub_comparison.append("core_plots") 

472 sub_comparison.append("samples") 

473 if self.test == "skymap" or self.test == "all": 

474 sub_comparison.append("skymap") 

475 if self.test == "spin_disk" or self.test == "all": 

476 sub_comparison.append("spin_disk") 

477 comparison.append(sub_comparison) 

478 links.append(comparison) 

479 return links 

480 

481 def _make_home_pages(self, pages): 

482 """Make the home pages 

483 

484 Parameters 

485 ---------- 

486 pages: list 

487 list of pages that you wish to create 

488 """ 

489 from pesummary import __version__ 

490 

491 html_file = self.setup_page( 

492 "home", self.navbar["comparison"], title="Summary" 

493 ) 

494 html_file.make_div(indent=2, _class='banner', _style="text-align: center") 

495 html_file.add_content("Review completed with:") 

496 html_file.end_div() 

497 html_file.make_div( 

498 indent=2, _class='banner', _style="text-align: center; color:red" 

499 ) 

500 html_file.add_content("pesummary=={}".format(__version__)) 

501 html_file.end_div() 

502 html_file.make_div(indent=2, _class='banner', _style="font-size: 14px") 

503 html_file.add_content( 

504 "This page compares the output between pesummary and lalinference/" 

505 "ligo.skymap." 

506 ) 

507 html_file.end_div() 

508 html_file.make_banner( 

509 approximant="On the command-line", key="command_line", 

510 _style="font-size: 26px;", link=os.getcwd() 

511 ) 

512 command = "" 

513 for i in sys.argv: 

514 command += " " 

515 if i[0] == "-": 

516 command += "\n" 

517 command += "{}".format(i) 

518 html_file.make_container() 

519 styles = html_file.make_code_block(language="shell", contents=command) 

520 with open('{0:s}/css/home.css'.format(self.webdir), 'w') as g: 

521 g.write(styles) 

522 html_file.end_container() 

523 html_file.export( 

524 "pesummary.sh", csv=False, json=False, shell=True, 

525 margin_top="-4em" 

526 ) 

527 html_file.end_div() 

528 

529 def make_comparison_spin_disk(self): 

530 """Make a page which compares the spin disk produced using code in 

531 pesummary and the spin disk produced using code from the GWTC1 catalog 

532 """ 

533 pages = ["spin_disk"] 

534 self.create_blank_html_pages(pages, stylesheets="spin_disk") 

535 html_file = self.setup_page( 

536 pages[0], self.navbar["comparison"], title="Spin disk comparison" 

537 ) 

538 html_file.make_div(indent=2, _class='banner', _style=None) 

539 html_file.add_content("Spin disk comparison") 

540 html_file.end_div() 

541 html_file.make_div(indent=2, _class='paragraph', _style="max-width:1400px") 

542 html_file.add_content( 

543 "Below we compare the spin disk plot produced using code within pesummary " 

544 "to the spin disk produced using code from the GWTC1 catalog." 

545 ) 

546 html_file.end_div() 

547 html_file.make_container() 

548 styles = html_file.make_code_block( 

549 language="python", contents=_launch_spin_disk_script() 

550 ) 

551 with open('{0:s}/css/spin_disk.css'.format(self.webdir), 'w') as g: 

552 g.write(styles) 

553 html_file.end_container() 

554 contents = [[ 

555 "../spin_disk/pesummary.png", "../spin_disk/GWTC1.png" 

556 ]] 

557 html_file = self.make_modal_carousel(html_file, contents) 

558 

559 def make_comparison_core_plots(self): 

560 """Make a page which compares the core 1d_histogram, autocorrelation 

561 and sample trace plots in pesummary to the ones produced with 

562 `cbcBayesPostProc` 

563 """ 

564 pages = ["core_plots"] 

565 self.create_blank_html_pages(pages) 

566 html_file = self.setup_page( 

567 pages[0], self.navbar["comparison"], title="Core plot comparison" 

568 ) 

569 html_file.make_div(indent=2, _class='banner', _style=None) 

570 html_file.add_content("Core plot comparison") 

571 html_file.end_div() 

572 html_file.make_div(indent=2, _class='paragraph', _style="max-width:1400px") 

573 html_file.add_content( 

574 "Below we compare the 1d histograms, autocorrelation and sample trace " 

575 "plots produced by pesummary and `cbcBayesPostProc`." 

576 ) 

577 html_file.end_div() 

578 cli = "\n".join( 

579 _launch_lalinference_cli( 

580 self.abswebdir, self.path_to_results_file, add_symbol=True 

581 ) 

582 ) 

583 cli += "\n" 

584 cli += "\n".join( 

585 _launch_pesummary_cli( 

586 self.abswebdir, self.path_to_results_file, add_symbol=True 

587 ) 

588 ) 

589 html_file.make_container() 

590 styles = html_file.make_code_block(language="shell", contents=cli) 

591 with open('{0:s}/css/Comparison_core_plots.css'.format(self.webdir), 'w') as g: 

592 g.write(styles) 

593 html_file.end_container() 

594 _reverse_dict = {val: key for key, val in lalinference_map.items()} 

595 _, lal_params = get_list_of_plots(self.webdir, lalinference=True) 

596 not_included = [] 

597 _lalinf_base = "../lalinference" 

598 _pes_base = "../pesummary" 

599 for param in lal_params: 

600 if param in standard_names.keys(): 

601 html_file.make_banner( 

602 approximant=param, _style="font-size: 26px;" 

603 ) 

604 contents = [[ 

605 "{}/1Dpdf/{}.png".format(_lalinf_base, param), 

606 "{}/plots/pesummary_1d_posterior_{}.png".format( 

607 _pes_base, standard_names[param] 

608 ) 

609 ], [ 

610 "{}/1Dsamps/{}_acf.png".format(_lalinf_base, param), 

611 "{}/plots/pesummary_autocorrelation_{}.png".format( 

612 _pes_base, standard_names[param] 

613 ) 

614 ], [ 

615 "{}/1Dsamps/{}_samps.png".format(_lalinf_base, param), 

616 "{}/plots/pesummary_sample_evolution_{}.png".format( 

617 _pes_base, standard_names[param] 

618 ) 

619 ]] 

620 html_file.make_table_of_images(contents=contents, autoscale=True) 

621 try: 

622 _lalinf_samples = self.samples["lalinference"][standard_names[param]] 

623 _pes_samples = self.samples["pesummary"][standard_names[param]] 

624 html_file.make_div( 

625 _class="banner", _style="font-size:26px; color:red" 

626 ) 

627 html_file.add_content( 

628 "max difference in %s samples: %s" % ( 

629 standard_names[param], np.max( 

630 np.abs(_lalinf_samples - _pes_samples) 

631 ) 

632 ) 

633 ) 

634 html_file.end_div() 

635 except Exception as e: 

636 print(e) 

637 else: 

638 not_included.append(param) 

639 html_file.make_div( 

640 indent=2, _class='banner', 

641 _style="font-size: 14px; max-width:1400px; margin-bottom: 2em" 

642 ) 

643 html_file.add_content( 

644 "parameters not included: {}".format(", ".join(not_included)) 

645 ) 

646 html_file.end_div() 

647 html_file.make_footer() 

648 

649 def make_comparison_skymap(self): 

650 """Make a page which compares the skymap produced with `ligo.skymap` 

651 and pesummary. 

652 """ 

653 pages = ["skymap"] 

654 self.create_blank_html_pages(pages) 

655 html_file = self.setup_page( 

656 pages[0], self.navbar["comparison"], title="Skymap comparison", 

657 ) 

658 html_file.make_div(indent=2, _class='banner', _style=None) 

659 html_file.add_content("Skymap comparison") 

660 html_file.end_div() 

661 html_file.make_div(indent=2, _class='paragraph', _style="max-width:1400px") 

662 html_file.add_content( 

663 "Below we compare the skymap produced by ligo.skymap and the skymap " 

664 "produced by pesummary (wrapper for ligo.skymap). We compare the " 

665 "skymap plots and skymap stats." 

666 ) 

667 html_file.end_div() 

668 _webdir = self.abswebdir + "/ligo_skymap" 

669 cli = "\n".join( 

670 _launch_skymap_cli(_webdir, self.path_to_results_file, add_symbol=True) 

671 ) 

672 cli += "\n\n" 

673 cli += "\n".join( 

674 _launch_pesummary_cli(_webdir, self.path_to_results_file, add_symbol=True) 

675 ) 

676 html_file.make_container() 

677 styles = html_file.make_code_block(language="shell", contents=cli) 

678 with open('{0:s}/css/Comparison_skymap.css'.format(self.webdir), 'w') as g: 

679 g.write(styles) 

680 html_file.end_container() 

681 lal_skymap = glob( 

682 os.path.join(self.webdir, "ligo_skymap", "skymap.png") 

683 )[0].replace(self.webdir, "") 

684 pes_skymap = glob( 

685 os.path.join(self.webdir, "pesummary", "plots", "pesummary_skymap.png") 

686 )[0].replace(self.webdir, "") 

687 contents = [ 

688 ["../{}".format(lal_skymap)], ["../{}".format(pes_skymap)] 

689 ] 

690 html_file = self.make_modal_carousel(html_file, contents) 

691 html_file.make_div(indent=2, _class='banner', _style="font-size: 26px") 

692 html_file.add_content("Stat comparison") 

693 html_file.end_div() 

694 lal_stats = np.genfromtxt( 

695 os.path.join(self.webdir, "ligo_skymap", "skymap.txt"), names=True, 

696 skip_header=True 

697 ) 

698 pes_stats = np.genfromtxt( 

699 os.path.join( 

700 self.webdir, "pesummary", "samples", "pesummary_skymap_stats.dat" 

701 ), names=True, skip_header=True 

702 ) 

703 keys = lal_stats.dtype.names 

704 headings = [" ", "ligo.skymap", "pesummary", "difference (%)"] 

705 contents = [] 

706 for key in keys: 

707 row = [key, lal_stats[key], pes_stats[key]] 

708 row += [np.abs(lal_stats[key] - pes_stats[key]) * 100] 

709 contents.append(row) 

710 html_file.make_table( 

711 headings=headings, contents=contents, heading_span=1, 

712 accordian=False, format="table-hover header-fixed", 

713 sticky_header=True 

714 ) 

715 html_file.make_div(_style="margin-bottom: 2em") 

716 html_file.end_div() 

717 html_file.make_footer() 

718 

719 def make_comparison_samples(self): 

720 """Make a page which compares the samples produced by `cbcBayesPostProc` 

721 and pesummary. 

722 """ 

723 pages = ["samples"] 

724 self.create_blank_html_pages(pages) 

725 html_file = self.setup_page( 

726 pages[0], self.navbar["comparison"], title="Sample by sample comparison", 

727 ) 

728 html_file.make_div(indent=2, _class='banner', _style=None) 

729 html_file.add_content("Sample comparison") 

730 html_file.end_div() 

731 html_file.make_div(indent=2, _class='paragraph', _style="max-width:1400px") 

732 html_file.add_content( 

733 "Below we compare the samples stored in the lalinference " 

734 "posterior_samples.dat (produced with `cbcBayesPostProc`) and the " 

735 "samples stored in the `posterior_samples.h5` file (produced with " 

736 "`pesummary`). We compare the medians, 90% confidence intervals." 

737 ) 

738 html_file.end_div() 

739 cli = "\n".join( 

740 _launch_lalinference_cli( 

741 self.abswebdir, self.path_to_results_file, add_symbol=True 

742 ) 

743 ) 

744 cli += "\n" 

745 cli += "\n".join( 

746 _launch_pesummary_cli( 

747 self.abswebdir, self.path_to_results_file, add_symbol=True 

748 ) 

749 ) 

750 cli += "\n\n" 

751 cli += "Files compared: \nlalinference: {}\npesummary: {}".format( 

752 self.lalinference_path, self.pesummary_path 

753 ) 

754 html_file.make_container() 

755 styles = html_file.make_code_block(language="shell", contents=cli) 

756 with open('{0:s}/css/Comparison_samples.css'.format(self.webdir), 'w') as g: 

757 g.write(styles) 

758 html_file.end_container() 

759 headings = [" ", "lalinference", "pesummary", "difference (%)"] 

760 contents = [] 

761 for _type in ["median", "5th percentile", "95th percentile"]: 

762 if _type == "median": 

763 func = np.median 

764 elif _type == "5th percentile": 

765 func = lambda array: np.percentile(array, 5) 

766 elif _type == "95th percentile": 

767 func = lambda array: np.percentile(array, 95) 

768 for param in self.same_parameters: 

769 row = [] 

770 lal = func(self.samples["lalinference"][param]) 

771 pes = func(self.samples["pesummary"][param]) 

772 row = [ 

773 param, lal, pes, np.abs(pes - lal) * 100 

774 ] 

775 contents.append(row) 

776 html_file.make_div( 

777 indent=2, _class='banner', _style="font-size: 26px; margin-top: 1em;" 

778 ) 

779 html_file.add_content(_type) 

780 html_file.end_div() 

781 html_file.make_table( 

782 headings=headings, contents=contents, heading_span=1, 

783 accordian=False, format="table-hover header-fixed", 

784 sticky_header=True 

785 ) 

786 for analysis in ["lalinference", "pesummary"]: 

787 html_file.make_div( 

788 indent=2, _class='banner', 

789 _style="font-size: 14px; max-width:1400px; margin-bottom: 2em" 

790 ) 

791 html_file.add_content( 

792 "{} parameters not included: {}".format( 

793 analysis, ", ".join( 

794 [ 

795 param for param in self.samples[analysis].keys() 

796 if param not in self.same_parameters 

797 ] 

798 ) 

799 ) 

800 ) 

801 html_file.end_div() 

802 html_file.make_footer() 

803 

804 

805def main(args=None): 

806 """Top level interface for `summaryreview` 

807 """ 

808 parser = ArgumentParser(description=__doc__) 

809 parser.add_known_options_to_parser( 

810 ["--webdir", "--samples", "--test", "--multi_process"] 

811 ) 

812 opts = parser.parse_args(args=args) 

813 if opts.test == "core_plots" or opts.test == "all": 

814 logger.info("Starting to generate plots using 'cbcBayesPostProc'") 

815 launch_lalinference(opts.webdir, opts.samples) 

816 logger.info("Starting to generate plots using 'summarypages'") 

817 launch_pesummary(opts.webdir, opts.samples, multi_process=opts.multi_process) 

818 if opts.test == "skymap" or opts.test == "all": 

819 logger.info("Generating skymap with `ligo.skymap`") 

820 launch_skymap(opts.webdir, opts.samples, multi_process=opts.multi_process) 

821 if opts.test == "spin_disk" or opts.test == "all": 

822 logger.info("Starting to make spin disk plots") 

823 launch_spin_disk(opts.webdir, opts.samples) 

824 logger.info("Making webpages to display tests") 

825 try: 

826 w = WebpageGeneration(opts.webdir, opts.samples, test=opts.test) 

827 w.generate_webpages() 

828 except Exception as e: 

829 logger.warning("Unable to generate webpages because {}".format(e)) 

830 

831 

832if __name__ == "__main__": 

833 main()