r"""Find the threshold level that accomplishes the desired specificity
    Call indicated function repeatedly to find answer to the inverse function evaluation
    Arguments:
      fun (function): function to be calculate an inverse for
      y (float): desired output of fun
      x0 (float): initial guess at input to fun, the fun arg that will be adjusted
      args (list or tuple): constants arguments to fun which will not be adjusted
      constraints (tuple): dictionary of optimizer constraints (see scipy.optimize.minimize)
      disp (bool): whether to display incremental results during optimization
      method (str): one of the scipy.optimize.minimize methods
      additional kwargs are passed along to the minimize function
    fun_inverse can be used to calculate a trivial square root:
    >>> round(fun_inverse(fun=lambda x: x**2, y=9, x0=0), 6)
    3.0

def fun_inverse(fun=None, y=0, x0=None, args=(), disp=False, method='Nelder-Mead', **kwargs):
    r"""Find the threshold level that accomplishes the desired specificity
    Call indicated function repeatedly to find answer to the inverse function evaluation
    Arguments:
      fun (function): function to be calculate an inverse for
      y (float): desired output of fun
      x0 (float): initial guess at input to fun, the fun arg that will be adjusted
      args (list or tuple): constants arguments to fun which will not be adjusted
      constraints (tuple): dictionary of optimizer constraints (see scipy.optimize.minimize)
      disp (bool): whether to display incremental results during optimization
      method (str): one of the scipy.optimize.minimize methods
      additional kwargs are passed along to the minimize function
    fun_inverse can be used to calculate a trivial square root:
    >>> round(fun_inverse(fun=lambda x: x**2, y=9, x0=0), 6)
    3.0
    """
    fun_inverse.fun = cost_fun.fun = fun if fun is not None else getattr(fun_inverse, 'fun', lambda x: x)
    fun_inverse.target = cost_fun.target = y or 0
    fun_inverse.verbose = verbose = cost_fun.verbose = kwargs.pop(
        'verbose', getattr(cost_fun, 'verbose', getattr(fun_inverse, 'verbose', False)))
    fun_inverse.x0 = x0 = x0 if x0 is not None else getattr(fun_inverse, 'x0', 0) or 0

    if verbose:
        print('    x0: {}\ntarget: {}\n'.format(fun_inverse.x0, fun_inverse.target))

    res = minimize(cost_fun,
                   x0=x0,
                   args=args,
                   options=kwargs.pop('options', {}),
                   method=method,
                   **kwargs
                   )
    if isinstance(x0, NUMERIC_TYPES):
        return res.x[0]
    return res.x