docs: def sample_entropy(time_series, sample_length, tolerance = None):
      """Calculates the sample entropy of degree m of a time_series.
  
      This method uses chebychev norm.
      It is quite fast for random data, but can be slower is there is
      structure in the input time series.
  
      Args:
          time_series: numpy array of time series
          sample_length: length of longest template vector
          tolerance: tolerance (defaults to 0.1 * std(time_series)))
      Returns:
          Array of sample entropies:
              SE[k] is ratio "#templates of length k+1" / "#templates of length k"
              where #templates of length 0" = n*(n - 1) / 2, by definition
      Note:
          The parameter 'sample_length' is equal to m + 1 in Ref[1].
  
  
      References:
          [1] http://en.wikipedia.org/wiki/Sample_Entropy
          [2] http://physionet.incor.usp.br/physiotools/sampen/
          [3] Madalena Costa, Ary Goldberger, CK Peng. Multiscale entropy analysis
              of biological signals
      """
      #The code below follows the sample length convention of Ref [1] so:
      M = sample_length - 1;
  
      time_series = np.array(time_series)
      if tolerance is None:
          tolerance = 0.1*np.std(time_series)
  
      n = len(time_series)
  
      #Ntemp is a vector that holds the number of matches. N[k] holds matches templates of length k
      Ntemp = np.zeros(M + 2)
      #Templates of length 0 matches by definition:
      Ntemp[0] = n*(n - 1) / 2
  
  
      for i in range(n - M - 1):
          template = time_series[i:(i+M+1)];#We have 'M+1' elements in the template
          rem_time_series = time_series[i+1:]
  
          searchlist = np.nonzero(np.abs(rem_time_series - template[0]) < tolerance)[0]
  
          go = len(searchlist) > 0;
  
          length = 1;
  
          Ntemp[length] += len(searchlist)
  
          while go:
              length += 1
              nextindxlist = searchlist + 1;
              nextindxlist = nextindxlist[nextindxlist < n - 1 - i]#Remove candidates too close to the end
              nextcandidates = rem_time_series[nextindxlist]
              hitlist = np.abs(nextcandidates - template[length-1]) < tolerance
              searchlist = nextindxlist[hitlist]
  
              Ntemp[length] += np.sum(hitlist)
  
              go = any(hitlist) and length < M + 1
  
  
      sampen =  - np.log(Ntemp[1:] / Ntemp[:-1])
      return sampen