docs: def EXP(w_F, compute_uncertainty=True, is_timeseries=False):
      """Estimate free energy difference using one-sided (unidirectional) exponential averaging (EXP).
  
      Parameters
      ----------
      w_F : np.ndarray, float
          w_F[t] is the forward work value from snapshot t.  t = 0...(T-1)  Length T is deduced from vector.
      compute_uncertainty : bool, optional, default=True
          if False, will disable computation of the statistical uncertainty (default: True)
      is_timeseries : bool, default=False
          if True, correlation in data is corrected for by estimation of statisitcal inefficiency (default: False)
          Use this option if you are providing correlated timeseries data and have not subsampled the data to produce uncorrelated samples.
  
      Returns
      -------
      result_vals : dictionary
      
      Possible keys in the result_vals dictionary
  
      'Delta_f' : float
          Free energy difference
      'dDelta_f': float
          Estimated standard deviation of free energy difference
  
      Notes
      -----
      If you are prodividing correlated timeseries data, be sure to set the 'timeseries' flag to True
  
      Examples
      --------
  
      Compute the free energy difference given a sample of forward work values.
  
      >>> from pymbar import testsystems
      >>> [w_F, w_R] = testsystems.gaussian_work_example(mu_F=None, DeltaF=1.0, seed=0)
      >>> results = EXP(w_F)
      >>> print('Forward free energy difference is %.3f +- %.3f kT' % (results['Delta_f'], results['dDelta_f']))
      Forward free energy difference is 1.088 +- 0.076 kT
      >>> results = EXP(w_R)
      >>> print('Reverse free energy difference is %.3f +- %.3f kT' % (results['Delta_f'], results['dDelta_f']))
      Reverse free energy difference is -1.073 +- 0.082 kT
  
      """
  
      result_vals = dict()
  
      # Get number of work measurements.
      T = float(np.size(w_F))  # number of work measurements
  
      # Estimate free energy difference by exponential averaging using DeltaF = - log < exp(-w_F) >
      DeltaF = - (logsumexp(- w_F) - np.log(T))
  
      if compute_uncertainty:
          # Compute x_i = np.exp(-w_F_i - max_arg)
          max_arg = np.max(-w_F)  # maximum argument
          x = np.exp(-w_F - max_arg)
  
          # Compute E[x] = <x> and dx
          Ex = x.mean()
  
          # Compute effective number of uncorrelated samples.
          g = 1.0  # statistical inefficiency
          if is_timeseries:
              # Estimate statistical inefficiency of x timeseries.
              import timeseries
              g = timeseries.statisticalInefficiency(x, x)
  
          # Estimate standard error of E[x].
          dx = np.std(x) / np.sqrt(T / g)
  
          # dDeltaF = <x>^-1 dx
          dDeltaF = (dx / Ex)
  
          # Return estimate of free energy difference and uncertainty.
          result_vals['Delta_f'] = DeltaF
          result_vals['dDelta_f'] = dDeltaF 
      else:
          result_vals['Delta_f'] = DeltaF
      return result_vals