//  [python]
def find_extreme_examples(
        class_labels, event_probabilities, num_examples_per_set):
    """Finds extreme examples.

    There are four sets of examples:

    - best hits
    - worst false alarms
    - worst misses
    - best correct nulls

    E = total number of examples
    e = number of examples per set

    :param class_labels: length-E numpy array of class labels (1 for event, 0
        for non-event).
    :param event_probabilities: length-E numpy array of event probabilities.
    :param num_examples_per_set: Number of examples in each set.

    :return: extreme_dict: Dictionary with the following keys.
    extreme_dict['hit_indices']: length-e numpy array with indices of best hits.
    extreme_dict['miss_indices']: length-e numpy array with indices of worst
        misses.
    extreme_dict['false_alarm_indices']: length-e numpy array with indices of
        worst false alarms.
    extreme_dict['correct_null_indices']: length-e numpy array with indices of
        best correct nulls.
    """

    # Check input args.
    class_labels = numpy.round(class_labels).astype(int)
    assert numpy.all(class_labels >= 0)
    assert numpy.all(class_labels <= 1)
    assert len(class_labels.shape) == 1

    num_examples_total = len(class_labels)

    assert numpy.all(event_probabilities >= 0.)
    assert numpy.all(event_probabilities <= 1.)
    assert len(event_probabilities.shape) == 1
    assert len(event_probabilities) == num_examples_total

    num_examples_per_set = int(numpy.round(num_examples_per_set))
    assert num_examples_per_set > 0

    positive_indices = numpy.where(class_labels == 1)[0]
    negative_indices = numpy.where(class_labels == 0)[0]

    num_hits = min([
        num_examples_per_set, len(positive_indices)
    ])
    num_misses = min([
        num_examples_per_set, len(positive_indices)
    ])
    num_false_alarms = min([
        num_examples_per_set, len(negative_indices)
    ])
    num_correct_nulls = min([
        num_examples_per_set, len(negative_indices)
    ])

    these_indices = numpy.argsort(-1 * event_probabilities[positive_indices])
    hit_indices = positive_indices[these_indices][:num_hits]
    print('Average event probability for {0:d} best hits = {1:.4f}'.format(
        num_hits, numpy.mean(event_probabilities[hit_indices])
    ))

    these_indices = numpy.argsort(event_probabilities[positive_indices])
    miss_indices = positive_indices[these_indices][:num_misses]
    print('Average event probability for {0:d} worst misses = {1:.4f}'.format(
        num_misses, numpy.mean(event_probabilities[miss_indices])
    ))

    these_indices = numpy.argsort(-1 * event_probabilities[negative_indices])
    false_alarm_indices = negative_indices[these_indices][:num_false_alarms]
    print((
        'Average event probability for {0:d} worst false alarms = {1:.4f}'
    ).format(
        num_false_alarms, numpy.mean(event_probabilities[false_alarm_indices])
    ))

    these_indices = numpy.argsort(event_probabilities[negative_indices])
    correct_null_indices = negative_indices[these_indices][:num_correct_nulls]
    print((
        'Average event probability for {0:d} best correct nulls = {1:.4f}'
    ).format(
        num_correct_nulls, numpy.mean(event_probabilities[correct_null_indices])
    ))

    return {
        HIT_INDICES_KEY: hit_indices,
        MISS_INDICES_KEY: miss_indices,
        FALSE_ALARM_INDICES_KEY: false_alarm_indices,
        CORRECT_NULL_INDICES_KEY: correct_null_indices
    }