Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1"""Qualitative source properties for CBC events.""" 

2import io 

3import json 

4from matplotlib import pyplot as plt 

5 

6from ligo import computeDiskMass, em_bright 

7 

8from celery.utils.log import get_task_logger 

9 

10from ..import app 

11from . import gracedb, lvalert 

12from .p_astro import _format_prob 

13from ..util import NamedTemporaryFile, PromiseProxy, read_pickle 

14 

15NS_CLASSIFIER = PromiseProxy( 

16 read_pickle, ('ligo.data', 'knn_ns_classifier.pkl')) 

17EM_CLASSIFIER = PromiseProxy( 

18 read_pickle, ('ligo.data', 'knn_em_classifier.pkl')) 

19 

20log = get_task_logger(__name__) 

21 

22 

23@lvalert.handler('superevent', 

24 'mdc_superevent', 

25 shared=False) 

26def handle(alert): 

27 """LVAlert handler to plot and upload a visualization 

28 of every ``em_bright.json``. 

29 """ 

30 filename = 'em_bright.json' 

31 graceid = alert['uid'] 

32 if alert['alert_type'] == 'log' and alert['data']['filename'] == filename: 

33 ( 

34 gracedb.download.si(filename, graceid) 

35 | 

36 plot.s() 

37 | 

38 gracedb.upload.s( 

39 filename.replace('.json', '.png'), 

40 graceid, 

41 message=( 

42 'Source properties visualization from ' 

43 '<a href="/api/superevents/{graceid}/files/{filename}">' 

44 '{filename}</a>').format( 

45 graceid=graceid, filename=filename), 

46 tags=['em_follow', 'em_bright', 'public'] 

47 ) 

48 ).delay() 

49 

50 

51@app.task(shared=False) 

52def plot(contents): 

53 """Make a visualization of the source properties. 

54 

55 Examples 

56 -------- 

57 .. plot:: 

58 :include-source: 

59 

60 >>> from gwcelery.tasks import em_bright 

61 >>> contents = '{"HasNS": 0.9137, "HasRemnant": 0.0}' 

62 >>> em_bright.plot(contents) 

63 """ 

64 properties = json.loads(contents) 

65 outfile = io.BytesIO() 

66 

67 properties = dict(sorted(properties.items(), reverse=True)) 

68 probs, names = list(properties.values()), list(properties.keys()) 

69 

70 with plt.style.context('seaborn-white'): 

71 fig, ax = plt.subplots(figsize=(3, 1)) 

72 ax.barh(names, probs) 

73 ax.barh(names, [1.0 - p for p in probs], 

74 color='lightgray', left=probs) 

75 for i, prob in enumerate(probs): 

76 ax.annotate(_format_prob(prob), (0, i), (4, 0), 

77 textcoords='offset points', ha='left', va='center') 

78 ax.set_xlim(0, 1) 

79 ax.set_xticks([]) 

80 ax.tick_params(left=False) 

81 for side in ['top', 'bottom', 'right']: 

82 ax.spines[side].set_visible(False) 

83 fig.tight_layout() 

84 fig.savefig(outfile, format='png') 

85 return outfile.getvalue() 

86 

87 

88@app.task(shared=False) 

89def em_bright_posterior_samples(posterior_file_content): 

90 """Returns the probability of having a NS component and remnant 

91 using LALInference posterior samples. 

92 

93 Parameters 

94 ---------- 

95 posterior_file_content : hdf5 posterior file content 

96 

97 Returns 

98 ------- 

99 str 

100 JSON formatted string storing ``HasNS`` and ``HasRemnant`` 

101 probabilities 

102 

103 Examples 

104 -------- 

105 >>> em_bright_posterior_samples(GraceDb().files('S190930s', 

106 ... 'LALInference.posterior_samples.hdf5').read()) 

107 {"HasNS": 0.014904901243599122, "HasRemnant": 0.0} 

108 

109 """ 

110 with NamedTemporaryFile(content=posterior_file_content) as samplefile: 

111 filename = samplefile.name 

112 has_ns, has_remnant = em_bright.source_classification_pe(filename) 

113 data = json.dumps({ 

114 'HasNS': has_ns, 

115 'HasRemnant': has_remnant 

116 }) 

117 return data 

118 

119 

120def _em_bright(m1, m2, c1, c2, threshold=3.0): 

121 """This is the place-holder function for the source classfication pipeline. 

122 This placeholder code will only act upon the mass2 point estimate value and 

123 classify the systems as whether they have a neutron or not. 

124 """ 

125 disk_mass = computeDiskMass.computeDiskMass(m1, m2, c1, c2) 

126 p_ns = 1.0 if m2 <= threshold else 0.0 

127 p_emb = 1.0 if disk_mass > 0.0 or m1 < threshold else 0.0 

128 return p_ns, p_emb 

129 

130 

131@app.task(shared=False) 

132def classifier_other(mass1, mass2, spin1z, spin2z, snr): 

133 """Returns the boolean probability of having a NS component and the 

134 probability of having non-zero disk mass. This method is used for pipelines 

135 that do not provide the data products necessary for computation of the 

136 source properties probabilities. 

137 

138 Parameters 

139 ---------- 

140 mass1 : float 

141 Primary mass in solar masses 

142 mass2 : float 

143 Secondary mass in solar masses 

144 spin1z : float 

145 Dimensionless primary aligned spin component 

146 spin2z : float 

147 Dimensionless secondary aligned spin component 

148 snr : float 

149 Signal to noise ratio 

150 

151 Returns 

152 ------- 

153 str 

154 JSON formatted string storing ``HasNS`` and ``HasRemnant`` 

155 probabilities 

156 

157 Examples 

158 -------- 

159 >>> em_bright.classifier_other(2.0, 1.0, 0.0, 0.0, 10.) 

160 '{"HasNS": 1.0, "HasRemnant": 1.0}' 

161 """ 

162 p_ns, p_em = _em_bright(mass1, mass2, spin1z, spin2z) 

163 

164 data = json.dumps({ 

165 'HasNS': p_ns, 

166 'HasRemnant': p_em 

167 }) 

168 return data 

169 

170 

171@app.task(shared=False) 

172def classifier_gstlal(mass1, mass2, spin1z, spin2z, snr): 

173 """Returns the probability of having a NS component and the probability of 

174 having non-zero disk mass in the detected event. This method will be using 

175 the data products obtained from the weekly supervised learning runs for 

176 injections campaigns. The data products are in pickle formatted 

177 RandomForestClassifier objects. The method predict_proba of these objects 

178 provides us the probabilities of the coalesence being EM-Bright and 

179 existence of neutron star in the binary. 

180 

181 Parameters 

182 ---------- 

183 mass1 : float 

184 Primary mass in solar masses 

185 mass2 : float 

186 Secondary mass in solar masses 

187 spin1z : float 

188 Dimensionless primary aligned spin component 

189 spin2z : float 

190 Dimensionless secondary aligned spin component 

191 snr : float 

192 Signal to noise ratio 

193 

194 Returns 

195 ------- 

196 str 

197 JSON formatted string storing ``HasNS`` and ``HasRemnant`` 

198 probabilities 

199 

200 Examples 

201 -------- 

202 >>> em_bright.classifier_gstlal(2.0, 1.0, 0.0, 0.0, 10.) 

203 '{"HasNS": 1.0, "HasRemnant": 1.0}' 

204 """ 

205 p_ns, p_em = em_bright.source_classification( 

206 mass1, mass2, spin1z, spin2z, snr, 

207 ns_classifier=NS_CLASSIFIER, 

208 emb_classifier=EM_CLASSIFIER) 

209 

210 data = json.dumps({ 

211 'HasNS': p_ns, 

212 'HasRemnant': p_em 

213 }) 

214 return data