Coverage for pesummary/gw/finish.py: 91.1%
56 statements
« prev ^ index » next coverage.py v7.4.4, created at 2026-01-15 17:49 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2026-01-15 17:49 +0000
1# Licensed under an MIT style license -- see LICENSE.md
3import subprocess
4import os
5import time
6import numpy as np
8from pesummary.core.cli.parser import convert_dict_to_namespace
9from pesummary.core.finish import FinishingTouches
10from pesummary.utils.utils import logger
11from pesummary.cli.summarymodify import _main, command_line
13__author__ = ["Charlie Hoy <charlie.hoy@ligo.org>"]
16class GWFinishingTouches(FinishingTouches):
17 """Class to handle the finishing touches
19 Parameters
20 ----------
21 ligo_skymap_PID: dict
22 dictionary containing the process ID for the ligo.skymap subprocess
23 for each analysis
24 """
25 def __init__(self, inputs, ligo_skymap_PID=None):
26 super(GWFinishingTouches, self).__init__(inputs)
27 self.ligo_skymap_PID = ligo_skymap_PID
28 self.generate_ligo_skymap_statistics()
30 def generate_ligo_skymap_statistics(self):
31 """Extract key statistics from the ligo.skymap fits file
32 """
33 FAILURE = False
34 if self.ligo_skymap_PID is None:
35 return
36 samples_dir = os.path.join(self.inputs.webdir, "samples")
37 for label in self.inputs.labels:
38 _path = os.path.join(samples_dir, "{}_skymap.fits".format(label))
39 while not os.path.isfile(_path):
40 # fits file has not been created. Check if the process is still
41 # running
42 try:
43 output = subprocess.check_output(
44 ["ps -p {}".format(self.ligo_skymap_PID[label].pid)],
45 shell=True
46 )
47 cond1 = "summarypages" not in str(output)
48 cond2 = "defunct" in str(output)
49 if cond1 or cond2:
50 if not os.path.isfile(_path):
51 FAILURE = True
52 break
53 except (subprocess.CalledProcessError, KeyError):
54 FAILURE = True
55 break
56 # wait for the process to finish
57 time.sleep(60)
58 if FAILURE:
59 continue
60 ess = subprocess.Popen(
61 "ligo-skymap-stats {} -p 50 90 -o {}".format(
62 os.path.join(samples_dir, "{}_skymap.fits".format(label)),
63 os.path.join(
64 samples_dir, "{}_skymap_stats.dat".format(label)
65 )
66 ), shell=True
67 )
68 ess.wait()
69 self.save_skymap_stats_to_metafile(
70 label, os.path.join(samples_dir, "{}_skymap_stats.dat".format(label))
71 )
72 self.save_skymap_data_to_metafile(
73 label, os.path.join(samples_dir, "{}_skymap.fits".format(label))
74 )
76 def save_skymap_stats_to_metafile(self, label, filename):
77 """Save the skymap statistics to the PESummary metafile
79 Parameters
80 ----------
81 label: str
82 the label of the analysis that the skymap statistics corresponds to
83 filename: str
84 name of the file that contains the skymap statistics for label
85 """
86 logger.info("Adding ligo.skymap statistics to the metafile")
87 try:
88 skymap_data = np.genfromtxt(filename, names=True, skip_header=True)
89 except IndexError:
90 logger.warning(
91 "Failed to open '{}'. Unable to store skymap statistics in "
92 "metafile".format(filename)
93 )
94 return
95 keys = skymap_data.dtype.names
97 _dict = {
98 "webdir": self.inputs.webdir,
99 "samples": [os.path.join(self.inputs.webdir, "samples", "posterior_samples.h5")],
100 "kwargs": {label: ["{}:{}".format(key, float(skymap_data[key])) for key in keys]},
101 "overwrite": True
102 }
103 opts = convert_dict_to_namespace(_dict, add_defaults=command_line())
104 _main(opts)
106 def save_skymap_data_to_metafile(self, label, filename):
107 """Save the skymap data to the PESummary metafile
109 Parameters
110 ----------
111 label: str
112 the label of the analysis that the skymap corresponds to
113 filename: str
114 name of the fits file that contains the skymap for label
115 """
116 logger.info("Adding ligo.skymap data to the metafile")
118 _dict = {
119 "webdir": self.inputs.webdir,
120 "samples": [os.path.join(self.inputs.webdir, "samples", "posterior_samples.h5")],
121 "overwrite": True, "store_skymap": {label: filename}
122 }
123 opts = convert_dict_to_namespace(_dict, add_defaults=command_line())
124 _main(opts)