From 48649ffc0e0371fd590010478196250aa2ef5636 Mon Sep 17 00:00:00 2001 From: Yun-Jing Huang <yun-jing.huang@ligo.org> Date: Tue, 26 Jul 2022 17:21:28 +0000 Subject: [PATCH] gstlal_ll_inspiral_event_uploader: make composite events --- .../bin/gstlal_ll_inspiral_event_uploader | 103 +++++++++++++----- 1 file changed, 73 insertions(+), 30 deletions(-) diff --git a/gstlal-inspiral/bin/gstlal_ll_inspiral_event_uploader b/gstlal-inspiral/bin/gstlal_ll_inspiral_event_uploader index 4c4d125872..e9cf33e173 100755 --- a/gstlal-inspiral/bin/gstlal_ll_inspiral_event_uploader +++ b/gstlal-inspiral/bin/gstlal_ll_inspiral_event_uploader @@ -311,56 +311,99 @@ class EventUploader(events.EventProcessor): def process_candidates(self, event): """ - process candidates and update the favored event + process candidates and update the favored (maxsnr) event if needed - returns event and whether the favored event was updated + returns event and whether the favored (maxsnr) event was updated """ - favored = self.select_favored_event(event['candidates']) + if event['favored']: + event['candidates'].append(event['favored']) + + ### get overall max SNR + maxsnr_candidate = self.select_maxsnr_candidate(event['candidates']) + maxsnr = maxsnr_candidate['snr'] + + ### get overall min FAR + minfar_candidate = self.select_minfar_candidate(event['candidates']) + minfar = minfar_candidate['far'] + event['candidates'].clear() - ### no favored event yet - if not event['favored']: + ### not a better candidate + if event['favored'] and maxsnr <= event['favored']['snr'] and minfar >= event['favored']['far']: + + return False, event + + ### found a new or better candidate + else: logging.info( 'found candidate with FAR: {:.3E}, ' - 'SNR: {:2.1f}'.format(favored['far'], favored['snr']) + 'SNR: {:2.3f}'.format(maxsnr_candidate['far'], maxsnr_candidate['snr']) ) - event['favored'] = favored - return True, event - ### favored event is more significant - elif self.rank_candidate(favored) > self.rank_candidate(event['favored']): - logging.info( - 'found new favored candidate with FAR: {:.3E}, ' - 'SNR: {:2.1f}'.format(favored['far'], favored['snr']) - ) - event['favored'] = favored - return True, event + ### composite event + if maxsnr_candidate['far'] != minfar: + logging.info( + 'construct new composite event with FAR: {:.3E}, ' + 'SNR: {:2.3f}'.format(minfar, maxsnr_candidate['snr']) + ) + maxsnr_candidate = self.composite_event(maxsnr_candidate, minfar_candidate, minfar) - ### previous favored is better - else: - return False, event + if event['favored']: + assert maxsnr_candidate['far'] <= event['favored']['far'], "far should be smaller" + assert maxsnr_candidate['snr'] >= event['favored']['snr'], "snr should be larger" + + event['favored'] = maxsnr_candidate + + return True, event - def select_favored_event(self, candidates): + def composite_event(self, maxsnr_candidate, minfar_candidate, minfar): """ - select the best event out of the candidates + Consturct composite event. + + Replace far, likelihood in maxsnr candidate with those in the minfar candidate. """ - return max(candidates, key=self.rank_candidate) + ### replace far + maxsnr_candidate['far'] = minfar + + ### load coinc file + maxsnr_candidate_coinc = self.load_xmlobj(maxsnr_candidate["coinc"]) + minfar_candidate_coinc = self.load_xmlobj(minfar_candidate["coinc"]) + + ### update likelihood in coinc file + lsctables.CoincTable.get_table(maxsnr_candidate_coinc).getColumnByName("likelihood")[0] = lsctables.CoincTable.get_table(minfar_candidate_coinc).getColumnByName("likelihood")[0] + + ### update combined_far in coinc file + lsctables.CoincInspiralTable.get_table(maxsnr_candidate_coinc).getColumnByName("combined_far")[0] = minfar + + ### save coinc file + coinc_obj = BytesIO() + ligolw_utils.write_fileobj(maxsnr_candidate_coinc, coinc_obj) + maxsnr_candidate["coinc"] = coinc_obj.getvalue().decode("utf-8") + + return maxsnr_candidate - def rank_candidate(self, candidate): + + def select_maxsnr_candidate(self, candidates): + """ + select the max snr candidate out of the candidates """ - rank a candidate based on the following criterion: + return max(candidates, key=self.rank_snr) - * FAR > public threshold, choose lowest FAR - * FAR <= public threshold, choose highest SNR + def select_minfar_candidate(self, candidates): """ - if candidate['far'] <= self.public_far_threshold: - return True, candidate['snr'], 1. / candidate['far'] - else: - return False, 1. / candidate['far'], candidate['snr'] + select the min far candidate out of the candidates + """ + return min(candidates, key=self.rank_far) + + + def rank_snr(self, candidate): + return candidate['snr'] + def rank_far(self, candidate): + return candidate['far'] def send_favored_event(self, event, event_window): """ -- GitLab