def _get_error_threshold_function(error_threshold, simulator):
    """ Returns a boolean-valued function that indicates whether a particular (x,y) pair is
    outside a specified threshold

    :param error_threshold: can be None or a string; if this is a string, the first character MAY be '+' or '-', to
        indicate whether values above or below the threshold (respectively) are considered "bad".  If nothing is
        specified, this defaults to '+'.  The remainder of the string MUST either be a constant value convertible to a
        float, or the name of a piecewise constant function in the simulator.  In the former case, any value above/below
        the constant is considered "bad", and in the latter, any value above/below the value of the piecewise constant
        function at that point in time is considered "bad".

        Examples:
          * '100', '+100' => values greater than 100 exceed the threshold
          * '-0' => values below 0 exceed the threshold
          * 'cost_per_hour' => values above the simulator's cost_per_hour function exceed the threshold
          * '-cpus' => values below the simulator's cpu function exceed the threshold
    :param simulator: a Simulator object
    :returns: a boolean-valued threshold function
    """
    if not error_threshold:
        return lambda x, y: False

    reverse = False
    if error_threshold[0] in ("-", "+"):
        reverse = error_threshold[0] == "-"
        error_threshold = error_threshold[1:]
    try:
        constant = float(error_threshold)
        return lambda x, y: ((y > constant) if not reverse else (y < constant))
    except ValueError:
        piecewise = getattr(simulator, error_threshold)
        return lambda x, y: ((y > piecewise.call(x)) if not reverse else (y < piecewise.call(x)))