class_docstr: In this algorithm, a sign test is performed by comparing data points to the baseline.
  The baseline can be adjusted with an offset and a percent gain. How it works:
  The data is compared within a fixed window and if the results differ significantly from random
  then all points in that window are considered to be an anomaly.
  
  A confidence is used for the statistical null test, 0.01 is the default p_value
  
  The entire time series is scanned with a sliding window and all points are scored.
  
  Either upper or lower threshold can be requested, but not both.
  The lower threshold should be negative if the intent is to measure a drop below baseline.
  For example, a lower threshold of -20 will detect a 20 percent decrease when compared against baseline.
  
  This algorithm assumes that time_series and baseline_time_series are perfectly aligned, meaning that:
   a) every timestamp that exists in time_series also exists in baseline_time_series
   b) lengths of both time series are same
   c) the test window must not be larger than the time series
docstr: Merge ranges which are closer than max_gap
  :param ranges: assumed to be sorted on start
  :param max_gap: allowed gap between ranges
  :return: new ranges
docstr_tok: ["Merge","ranges","which","are","closer","than","max_gap",":","param","ranges",":","assumed","to","be","sorted","on","start",":","param","max_gap",":","allowed","gap","between","ranges",":","return",":","new","ranges"]
code: def _merge_ranges(ranges, max_gap):
      """
      Merge ranges which are closer than max_gap
      :param ranges: assumed to be sorted on start
      :param max_gap: allowed gap between ranges
      :return: new ranges
      """
      merged_ranges = []
      for range in ranges:
          if merged_ranges:
              curr_start, curr_end = range
              # compare against last interval in merged_ranges
              pre_start, pre_end = merged_ranges[-1]
              if curr_start - pre_end < max_gap:
                  # merge current range with the last range in the list
                  merged_ranges[-1] = (
                      pre_start,
                      max(curr_end, pre_end),
                  )
              else:
                  # append the new range to current one
                  merged_ranges.append(range)
          else:
              # no merged ranges - just add this one
              merged_ranges.append(range)
  
      return merged_ranges
  
file_path: luminol/src/luminol/algorithms/anomaly_detector_algorithms/sign_test.py
imports: import numpy
  from luminol import exceptions
  from luminol.algorithms.anomaly_detector_algorithms import AnomalyDetectorAlgorithm
  from luminol.utils import qbinom, pbinom
  from luminol.modules.time_series import TimeSeries
label_desc: Use image node_id 3 for calling the SignTest obj's underlying member method code with example usage: obj._merge_ranges(ranges, max_gap) and returns: merged_ranges