class_docstr: Statistical Power calculations, Base Class
  
  so far this could all be class methods
class_docstr_tok: ["Statistical","Power","calculations",",","Base","Class","so","far","this","could","all","be","class","methods"]
docstr: solve for any one of the parameters of a t-test
  
  for t-test the keywords are:
      effect_size, nobs, alpha, power
  
  exactly one needs to be ``None``, all others need numeric values
  
  *attaches*
  
  cache_fit_res : list
      Cache of the result of the root finding procedure for the latest
      call to ``solve_power``, mainly for debugging purposes.
      The first element is the success indicator, one if successful.
      The remaining elements contain the return information of the up to
      three solvers that have been tried.
docstr_tok: ["solve","for","any","one","of","the","parameters","of","a","t-test","for","t-test","the","keywords","are",":","effect_size",",","nobs",",","alpha",",","power","exactly","one","needs","to","be","``","None","``",",","all","others","need","numeric","values","*","attaches","*","cache_fit_res",":","list","Cache","of","the","result","of","the","root","finding","procedure","for","the","latest","call","to","``","solve_power","``",",","mainly","for","debugging","purposes",".","The","first","element","is","the","success","indicator",",","one","if","successful",".","The","remaining","elements","contain","the","return","information","of","the","up","to","three","solvers","that","have","been","tried","."]
code: def solve_power(self, **kwds):
      """solve for any one of the parameters of a t-test
  
      for t-test the keywords are:
          effect_size, nobs, alpha, power
  
      exactly one needs to be ``None``, all others need numeric values
  
      *attaches*
  
      cache_fit_res : list
          Cache of the result of the root finding procedure for the latest
          call to ``solve_power``, mainly for debugging purposes.
          The first element is the success indicator, one if successful.
          The remaining elements contain the return information of the up to
          three solvers that have been tried.
  
  
      """
      # TODO: maybe use explicit kwds,
      #    nicer but requires inspect? and not generic across tests
      #    I'm duplicating this in the subclass to get informative docstring
      key = [k for k, v in kwds.items() if v is None]
      # print kwds, key
      if len(key) != 1:
          raise ValueError("need exactly one keyword that is None")
      key = key[0]
  
      if key == "power":
          del kwds["power"]
          return self.power(**kwds)
  
      if kwds["effect_size"] == 0:
          import warnings
          from statsmodels.tools.sm_exceptions import (
              HypothesisTestWarning,
          )
  
          warnings.warn(
              "Warning: Effect size of 0 detected",
              HypothesisTestWarning,
          )
          if key == "power":
              return kwds["alpha"]
          if key == "alpha":
              return kwds["power"]
          else:
              raise ValueError(
                  "Cannot detect an effect-size of 0. Try changing your effect-size."
              )
  
      self._counter = 0
  
      def func(x):
          kwds[key] = x
          fval = self._power_identity(**kwds)
          self._counter += 1
          # print self._counter,
          if self._counter > 500:
              raise RuntimeError("possible endless loop (500 NaNs)")
          if np.isnan(fval):
              return np.inf
          else:
              return fval
  
      # TODO: I'm using the following so I get a warning when start_ttp is not defined
      try:
          start_value = self.start_ttp[key]
      except KeyError:
          start_value = 0.9
          import warnings
          from statsmodels.tools.sm_exceptions import ValueWarning
  
          warnings.warn(
              f"Warning: using default start_value for {key}",
              ValueWarning,
          )
  
      fit_kwds = self.start_bqexp[key]
      fit_res = []
      # print vars()
      try:
          val, res = brentq_expanding(
              func, full_output=True, **fit_kwds
          )
          failed = False
          fit_res.append(res)
      except ValueError:
          failed = True
          fit_res.append(None)
  
      success = None
      if (not failed) and res.converged:
          success = 1
      else:
          # try backup
          # TODO: check more cases to make this robust
          if not np.isnan(start_value):
              val, infodict, ier, msg = optimize.fsolve(
                  func, start_value, full_output=True
              )  # scalar
              # val = optimize.newton(func, start_value) #scalar
              fval = infodict["fvec"]
              fit_res.append(infodict)
          else:
              ier = -1
              fval = 1
              fit_res.append([None])
  
          if ier == 1 and np.abs(fval) < 1e-4:
              success = 1
          else:
              # print infodict
              if key in ["alpha", "power", "effect_size"]:
                  val, r = optimize.brentq(
                      func, 1e-8, 1 - 1e-8, full_output=True
                  )  # scalar
                  success = 1 if r.converged else 0
                  fit_res.append(r)
              else:
                  success = 0
  
      if not success == 1:
          import warnings
          from statsmodels.tools.sm_exceptions import (
              ConvergenceWarning,
              convergence_doc,
          )
  
          warnings.warn(convergence_doc, ConvergenceWarning)
  
      # attach fit_res, for reading only, should be needed only for debugging
      fit_res.insert(0, success)
      self.cache_fit_res = fit_res
      return val
  
imports: import warnings
  import numpy
  from scipy import stats, optimize, special
  from statsmodels.tools.rootfinding import brentq_expanding
label_desc: Use image node_id 4 for calling the Power obj's underlying member method code with example usage: obj.solve_power() and returns: val, self, kwds, kwds, np, fval