class_docstr: Estimate a Gaussian distribution for the null Z-scores.
  
  The observed Z-scores consist of both null and non-null values.
  The fitted distribution of null Z-scores is Gaussian, but may have
  non-zero mean and/or non-unit scale.
  
  Parameters
  ----------
  zscores : array_like
      The observed Z-scores.
  null_lb : float
      Z-scores between `null_lb` and `null_ub` are all considered to be
      true null hypotheses.
  null_ub : float
      See `null_lb`.
  estimate_mean : bool
      If True, estimate the mean of the distribution.  If False, the
      mean is fixed at zero.
  estimate_scale : bool
      If True, estimate the scale of the distribution.  If False, the
      scale parameter is fixed at 1.
  estimate_null_proportion : bool
      If True, estimate the proportion of true null hypotheses (i.e.
      the proportion of z-scores with expected value zero).  If False,
      this parameter is fixed at 1.
  
  Attributes
  ----------
  mean : float
      The estimated mean of the empirical null distribution
  sd : float
      The estimated standard deviation of the empirical null distribution
  null_proportion : float
      The estimated proportion of true null hypotheses among all hypotheses
  
  References
  ----------
  B Efron (2008).  Microarrays, Empirical Bayes, and the Two-Groups
  Model.  Statistical Science 23:1, 1-22.
  
  Notes
  -----
  See also:
  
  http://nipy.org/nipy/labs/enn.html#nipy.algorithms.statistics.empirical_pvalue.NormalEmpiricalNull.fdr
code: def __init__(
      self,
      zscores,
      null_lb=-1,
      null_ub=1,
      estimate_mean=True,
      estimate_scale=True,
      estimate_null_proportion=False,
  ):
      # Extract the null z-scores
      ii = np.flatnonzero((zscores >= null_lb) & (zscores <= null_ub))
      if len(ii) == 0:
          raise RuntimeError(
              "No Z-scores fall between null_lb and null_ub"
          )
      zscores0 = zscores[ii]
  
      # Number of Z-scores, and null Z-scores
      n_zs, n_zs0 = len(zscores), len(zscores0)
  
      # Unpack and transform the parameters to the natural scale, hold
      # parameters fixed as specified.
      def xform(params):
          mean = 0.0
          sd = 1.0
          prob = 1.0
  
          ii = 0
          if estimate_mean:
              mean = params[ii]
              ii += 1
          if estimate_scale:
              sd = np.exp(params[ii])
              ii += 1
          if estimate_null_proportion:
              prob = 1 / (1 + np.exp(-params[ii]))
  
          return mean, sd, prob
  
      from scipy.stats.distributions import norm
  
      def fun(params):
          """
          Negative log-likelihood of z-scores.
  
          The function has three arguments, packed into a vector:
  
          mean : location parameter
          logscale : log of the scale parameter
          logitprop : logit of the proportion of true nulls
  
          The implementation follows section 4 from Efron 2008.
          """
  
          d, s, p = xform(params)
  
          # Mass within the central region
          central_mass = norm.cdf((null_ub - d) / s) - norm.cdf(
              (null_lb - d) / s
          )
  
          # Probability that a Z-score is null and is in the central region
          cp = p * central_mass
  
          # Binomial term
          rval = n_zs0 * np.log(cp) + (n_zs - n_zs0) * np.log(1 - cp)
  
          # Truncated Gaussian term for null Z-scores
          zv = (zscores0 - d) / s
          rval += np.sum(-(zv**2) / 2) - n_zs0 * np.log(s)
          rval -= n_zs0 * np.log(central_mass)
  
          return -rval
  
      # Estimate the parameters
      from scipy.optimize import minimize
  
      # starting values are mean = 0, scale = 1, p0 ~ 1
      mz = minimize(fun, np.r_[0.0, 0, 3], method="Nelder-Mead")
      mean, sd, prob = xform(mz["x"])
  
      self.mean = mean
      self.sd = sd
      self.null_proportion = prob
  
file_path: statsmodels/statsmodels/stats/multitest.py
imports: import numpy
  from statsmodels.stats._knockoff import RegressionFDR
label_desc: Use image node_id 1 to create a new NullDistribution object  with example: obj = NullDistribution(zscores, null_lb, null_ub, estimate_mean, estimate_scale, estimate_null_proportion)