code: def standard_check(
      self, bocpd: BOCPD, test_data: TimeSeries, n: int, name: str
  ):
      # Evaluate trained BOCPD model on the test data & make sure it has perfect precision & recall
      scores = bocpd.get_anomaly_score(test_data)
      alarms = (
          bocpd.get_anomaly_label(test_data).to_pd().iloc[:, 0].abs()
      )
      n_alarms = (alarms != 0).sum()
      logger.info(f"# Alarms fired: {n_alarms}")
      logger.info(f"Alarms fired at:\n{alarms[alarms != 0]}")
      self.assertNotEqual(alarms.iloc[0], 0)
      self.assertNotEqual(alarms.iloc[n], 0)
      self.assertNotEqual(alarms.iloc[2 * n], 0)
      self.assertEqual(n_alarms, 3)
  
      # Make sure we get the same results after saving & loading
      bocpd.save(join(rootdir, "tmp", "bocpd", name))
      loaded = BOCPD.load(join(rootdir, "tmp", "bocpd", name))
      loaded_scores = loaded.get_anomaly_score(test_data)
      self.assertSequenceEqual(list(scores), list(loaded_scores))
  
file_path: merlion/tests/change_point/test_bocpd.py
imports: import logging
  import os
  from os.path import abspath, dirname, join
  import sys
  import unittest
  import numpy
  import pandas
  from merlion.models.anomaly.change_point.bocpd import BOCPD, BOCPDConfig, ChangeKind
  from merlion.utils.time_series import TimeSeries
label_desc: Use image node_id 2 for calling the TestBOCPD obj's underlying member method code with example usage: obj.standard_check(bocpd, test_data, n, name) without return types