From 30ac6ffb89ce7d07f7ae2946a147b763a30f9669 Mon Sep 17 00:00:00 2001
From: Naresh Adhikari <naresh.adhikari@ligo.org>
Date: Thu, 13 Apr 2023 12:09:20 -0500
Subject: [PATCH] Prevent external event from switching superevents; fixes #585

---
 CHANGES.rst                        |  2 ++
 gwcelery/tasks/raven.py            |  4 ++++
 gwcelery/tests/test_tasks_raven.py | 28 +++++++++++++++++++---------
 3 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index 26a2256e5..3390e87f6 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -39,6 +39,8 @@ Changelog
     if grabbing a sky map from an external URL such as from Fermi-GBM that
     lacks this field.
 
+-   Prevent external event from switching superevents.
+
 2.0.4 "Skunk Ape" (2023-03-28)
 ------------------------------
 
diff --git a/gwcelery/tasks/raven.py b/gwcelery/tasks/raven.py
index ab2232633..7e0f98310 100644
--- a/gwcelery/tasks/raven.py
+++ b/gwcelery/tasks/raven.py
@@ -217,6 +217,10 @@ def raven_pipeline(raven_search_results, gracedb_id, alert_object, tl, th,
             exttrig_id = gracedb_id
             superevent = result
             ext_event = alert_object
+            # Don't continue if it is a different superevent than previous one.
+            if ext_event['superevent'] is not None \
+                    and ext_event['superevent'] != superevent['superevent_id']:
+                return
 
         canvas = (
             gracedb.add_event_to_superevent.si(superevent_id, exttrig_id)
diff --git a/gwcelery/tests/test_tasks_raven.py b/gwcelery/tests/test_tasks_raven.py
index bebb52b72..ab932cf6d 100644
--- a/gwcelery/tests/test_tasks_raven.py
+++ b/gwcelery/tests/test_tasks_raven.py
@@ -207,7 +207,9 @@ def mock_get_superevent(superevent_id):
      [[{'superevent_id': 'S12', 'far': .001, 'preferred_event': 'G3'}],
         'T4', -10, 10, 'Burst'],
      [[{'superevent_id': 'MS13', 'far': 1, 'preferred_event': 'M3'}],
-        'M15', -1, 5, 'CBC']])
+        'M15', -1, 5, 'CBC'],
+     [[{'superevent_id': 'S13', 'far': 1, 'preferred_event': 'G4'}],
+        'E6', -60, 600, 'Burst']])
 @patch('gwcelery.tasks.raven.trigger_raven_alert.run')
 @patch('gwcelery.tasks.gracedb.get_labels', mock_get_labels)
 @patch('gwcelery.tasks.raven.calculate_coincidence_far.run',
@@ -229,7 +231,8 @@ def test_raven_pipeline(mock_plot_overlap_integral,
     """
     alert_object = {'preferred_event': 'G1', 'pipeline': 'Fermi',
                     'search': 'Supernova' if graceid == 'T4' else 'GRB',
-                    'labels': []}
+                    'labels': [],
+                    'superevent': None if graceid != 'E6' else 'S14'}
     time_coinc_far = mock_coinc_far()['temporal_coinc_far']
     space_coinc_far = mock_coinc_far()['spatiotemporal_coinc_far']
 
@@ -293,13 +296,20 @@ def test_raven_pipeline(mock_plot_overlap_integral,
         alert_calls.append(call(
             mock_coinc_far(),
             result, graceid, alert_object, group))
-    mock_trigger_raven_alert.assert_has_calls(alert_calls, any_order=True)
-
-    mock_calculate_coincidence_far.assert_has_calls(coinc_calls,
-                                                    any_order=True)
-    mock_update_superevent.assert_has_calls(update_calls, any_order=True)
-    mock_create_label.assert_has_calls(label_calls, any_order=True)
-    mock_plot_overlap_integral.assert_has_calls(plot_calls, any_order=True)
+    if graceid != 'E6':
+        mock_trigger_raven_alert.assert_has_calls(alert_calls, any_order=True)
+
+        mock_calculate_coincidence_far.assert_has_calls(coinc_calls,
+                                                        any_order=True)
+        mock_update_superevent.assert_has_calls(update_calls, any_order=True)
+        mock_create_label.assert_has_calls(label_calls, any_order=True)
+        mock_plot_overlap_integral.assert_has_calls(plot_calls, any_order=True)
+    else:
+        mock_trigger_raven_alert.assert_not_called()
+        mock_calculate_coincidence_far.assert_not_called()
+        mock_update_superevent.assert_not_called()
+        mock_create_label.assert_not_called()
+        mock_plot_overlap_integral.assert_not_called()
 
 
 @pytest.mark.parametrize(
-- 
GitLab