docs: def _computeWeights(self, logform=False, include_nonzero=False, recalc_denom=True, return_f_k=False):
          """Compute the normalized weights corresponding to samples for the given reduced potential.
  
          Compute the normalized weights corresponding to samples for the given reduced potential.
          Also stores the all_log_denom array for reuse.
  
          Parameters
          ----------
          logform : bool, optional
              Whether the output is in logarithmic form, which is better for stability, though sometimes
              the exponential form is requires.
          include_nonzero : bool, optional
              whether to compute weights for states with nonzero states.  Not necessary
              when performing self-consistent iteration.
          recalc_denom : bool, optional
              recalculate the denominator, must be done if the free energies change.
              default is to do it, so that errors are not made.  But can be turned
              off if it is known the free energies have not changed.
          return_f_k : bool, optional
              return the self-consistent f_k values
  
          Returns
          -------
  
          if logform==True:
            Log_W_nk (double) - Log_W_nk[n,k] is the normalized log weight of sample n from state k.
          else:
            W_nk (double) - W_nk[n,k] is the log weight of sample n from state k.
          if return_f_k==True:
            optionally return the self-consistent free energy from these weights.
  
         """
          if (include_nonzero):
              f_k = self.f_k
              K = self.K
          else:
              f_k = self.f_k[self.states_with_samples]
              K = len(self.states_with_samples)
  
          # array of either weights or normalized log weights
          Warray_nk = np.zeros([self.N, K], dtype=np.float64)
          if (return_f_k):
              f_k_out = np.zeros([K], dtype=np.float64)
  
          if (recalc_denom):
              self.log_weight_denom = self._computeUnnormalizedLogWeights(
                  np.zeros([self.N], dtype=np.float64))
  
          for k in range(K):
              if (include_nonzero):
                  index = k
              else:
                  index = self.states_with_samples[k]
              log_w_n = -self.u_kn[index, :] + self.log_weight_denom + f_k[k]
  
              if (return_f_k):
                  f_k_out[k] = f_k[k] - _logsum(log_w_n)
                  if (include_nonzero):
                      # renormalize the weights, needed for nonzero states.
                      log_w_n += (f_k_out[k] - f_k[k])
  
              if (logform):
                  Warray_nk[:, k] = log_w_n
              else:
                  Warray_nk[:, k] = np.exp(log_w_n)
  
          # Return weights (or log weights)
          if (return_f_k):
              f_k_out[:] = f_k_out[:] - f_k_out[0]
              return Warray_nk, f_k_out
          else:
              return Warray_nk