code: def bayesian_blocks(
      t, x=None, sigma=None, fitness="events", **kwargs
  ):
      """Bayesian Blocks Implementation
  
      This is a flexible implementation of the Bayesian Blocks algorithm
      described in Scargle 2012 [1]_
  
      Parameters
      ----------
      t : array_like
          data times (one dimensional, length N)
      x : array_like (optional)
          data values
      sigma : array_like or float (optional)
          data errors
      fitness : str or object
          the fitness function to use.
          If a string, the following options are supported:
  
          - 'events' : binned or unbinned event data
              extra arguments are `p0`, which gives the false alarm probability
              to compute the prior, or `gamma` which gives the slope of the
              prior on the number of bins.
          - 'regular_events' : non-overlapping events measured at multiples
              of a fundamental tick rate, `dt`, which must be specified as an
              additional argument.  The prior can be specified through `gamma`,
              which gives the slope of the prior on the number of bins.
          - 'measures' : fitness for a measured sequence with Gaussian errors
              The prior can be specified using `gamma`, which gives the slope
              of the prior on the number of bins.  If `gamma` is not specified,
              then a simulation-derived prior will be used.
  
          Alternatively, the fitness can be a user-specified object of
          type derived from the FitnessFunc class.
  
      Returns
      -------
      edges : ndarray
          array containing the (N+1) bin edges
  
      Examples
      --------
      Event data:
  
      >>> t = np.random.normal(size=100)
      >>> bins = bayesian_blocks(t, fitness='events', p0=0.01)
  
      Event data with repeats:
  
      >>> t = np.random.normal(size=100)
      >>> t[80:] = t[:20]
      >>> bins = bayesian_blocks(t, fitness='events', p0=0.01)
  
      Regular event data:
  
      >>> dt = 0.01
      >>> t = dt * np.arange(1000)
      >>> x = np.zeros(len(t))
      >>> x[np.random.randint(0, len(t), int(len(t) / 10))] = 1
      >>> bins = bayesian_blocks(t, x, fitness='regular_events', dt=dt, gamma=0.9)
  
      Measured point data with errors:
  
      >>> t = 100 * np.random.random(100)
      >>> x = np.exp(-0.5 * (t - 50) ** 2)
      >>> sigma = 0.1
      >>> x_obs = np.random.normal(x, sigma)
      >>> bins = bayesian_blocks(t, x=x_obs, fitness='measures')
  
      References
      ----------
      .. [1] Scargle, J `et al.` (2012)
             http://adsabs.harvard.edu/abs/2012arXiv1207.5578S
  
      See Also
      --------
      astroML.plotting.hist : histogram plotting function which can make use
                              of bayesian blocks.
      """
      # validate array input
      t = np.asarray(t, dtype=float)
      if x is not None:
          x = np.asarray(x)
      if sigma is not None:
          sigma = np.asarray(sigma)
  
      # verify the fitness function
      if fitness == "events":
          if x is not None and np.any(x % 1 > 0):
              raise ValueError(
                  "x must be integer counts for fitness='events'"
              )
          fitfunc = Events(**kwargs)
      elif fitness == "regular_events":
          if x is not None and (np.any(x % 1 > 0) or np.any(x > 1)):
              raise ValueError(
                  "x must be 0 or 1 for fitness='regular_events'"
              )
          fitfunc = RegularEvents(**kwargs)
      elif fitness == "measures":
          if x is None:
              raise ValueError(
                  "x must be specified for fitness='measures'"
              )
          fitfunc = PointMeasures(**kwargs)
      else:
          if not (
              hasattr(fitness, "args")
              and hasattr(fitness, "fitness")
              and hasattr(fitness, "prior")
          ):
              raise ValueError("fitness not understood")
          fitfunc = fitness
  
      # find unique values of t
      t = np.array(t, dtype=float)
      assert t.ndim == 1
      unq_t, unq_ind, unq_inv = np.unique(
          t, return_index=True, return_inverse=True
      )
  
      # if x is not specified, x will be counts at each time
      if x is None:
          if sigma is not None:
              raise ValueError(
                  "If sigma is specified, x must be specified"
              )
  
          if len(unq_t) == len(t):
              x = np.ones_like(t)
          else:
              x = np.bincount(unq_inv)
  
          t = unq_t
          sigma = 1
  
      # if x is specified, then we need to sort t and x together
      else:
          x = np.asarray(x)
  
          if len(t) != len(x):
              raise ValueError("Size of t and x does not match")
  
          if len(unq_t) != len(t):
              raise ValueError(
                  "Repeated values in t not supported when "
                  "x is specified"
              )
          t = unq_t
          x = x[unq_ind]
  
      # verify the given sigma value
      N = t.size
      if sigma is not None:
          sigma = np.asarray(sigma)
          if sigma.shape not in [(), (1,), (N,)]:
              raise ValueError("sigma does not match the shape of x")
      else:
          sigma = 1
  
      # validate the input
      fitfunc.validate_input(t, x, sigma)
  
      # compute values needed for computation, below
      if "a_k" in fitfunc.args:
          ak_raw = np.ones_like(x) / sigma / sigma
      if "b_k" in fitfunc.args:
          bk_raw = x / sigma / sigma
      if "c_k" in fitfunc.args:
          ck_raw = x * x / sigma / sigma
  
      # create length-(N + 1) array of cell edges
      edges = np.concatenate([t[:1], 0.5 * (t[1:] + t[:-1]), t[-1:]])
      block_length = t[-1] - edges
  
      # arrays to store the best configuration
      best = np.zeros(N, dtype=float)
      last = np.zeros(N, dtype=int)
  
      # -----------------------------------------------------------------
      #  Start with first data cell; add one cell at each iteration
      # -----------------------------------------------------------------
      for R in range(N):
          # Compute fit_vec : fitness of putative last block (end at R)
          kwds = {}
  
          # T_k: width/duration of each block
          if "T_k" in fitfunc.args:
              kwds["T_k"] = block_length[: R + 1] - block_length[R + 1]
  
          # N_k: number of elements in each block
          if "N_k" in fitfunc.args:
              kwds["N_k"] = np.cumsum(x[: R + 1][::-1])[::-1]
  
          # a_k: eq. 31
          if "a_k" in fitfunc.args:
              kwds["a_k"] = 0.5 * np.cumsum(ak_raw[: R + 1][::-1])[::-1]
  
          # b_k: eq. 32
          if "b_k" in fitfunc.args:
              kwds["b_k"] = -np.cumsum(bk_raw[: R + 1][::-1])[::-1]
  
          # c_k: eq. 33
          if "c_k" in fitfunc.args:
              kwds["c_k"] = 0.5 * np.cumsum(ck_raw[: R + 1][::-1])[::-1]
  
          # evaluate fitness function
          fit_vec = fitfunc.fitness(**kwds)
  
          A_R = fit_vec - fitfunc.prior(R + 1, N)
          A_R[1:] += best[:R]
  
          i_max = np.argmax(A_R)
          last[R] = i_max
          best[R] = A_R[i_max]
  
      # -----------------------------------------------------------------
      #  Now find changepoints by iteratively peeling off the last block
      # -----------------------------------------------------------------
      change_points = np.zeros(N, dtype=int)
      i_cp = N
      ind = N
      while True:
          i_cp -= 1
          change_points[i_cp] = ind
          if ind == 0:
              break
          ind = last[ind - 1]
      change_points = change_points[i_cp:]
  
      return edges[change_points]
  
imports: import numpy
  from astroML.utils import deprecated
  from astroML.utils.exceptions import AstroMLDeprecationWarning
label_desc: Use image node_id 1 for calling a global function with example usage: bayesian_blocks(t, x, sigma, fitness) and returns: edges