def reduce_evaluation_to_metalevel()

in mapillary_vistas/evaluation/confusion_matrix.py [0:0]


def reduce_evaluation_to_metalevel(labels, confusion_matrix, instance_specific_information, level):
    """
    Combine and add up rows/cols in common meta categories.
    Level specifies how many levels should be left (1 or 2)
    """

    max_depth = 0
    for label in labels:
        depth = len(label['name'].split('--'))
        if depth > max_depth:
            max_depth = depth

    if max_depth < level:
        return (labels, confusion_matrix)

    new_labels = []
    new_instance_specific_information = {}
    mapping = {}
    labels_by_name = {}
    ids_by_name = {}
    for index, label in enumerate(labels):
        old_name = label['name']
        labels_by_name[old_name] = label
        ids_by_name[old_name] = index
        levels = old_name.split('--')
        new_name = "--".join(levels[:level])

        if new_name not in mapping:
            mapping[new_name] = []

        mapping[new_name] += [old_name]

    id_mapping = []
    for new_name, old_names in sorted(mapping.items(), key=lambda entry: entry[0]):
        evaluate = True
        instances = True
        color = None
        readable = None

        new_instance_specific_information[new_name] = {
            'raw_true_positives': 0,
            'weighted_true_positives': 0,
            'raw_false_negatives': 0,
            'weighted_false_negatives': 0,
        }

        current_ids = []
        for old_name in old_names:
            current_ids += [ids_by_name[old_name]]
            old_label = labels_by_name[old_name]
            if not old_label['evaluate']:
                evaluate = False
            if not old_label['instances']:
                instances = False
            if color is None:
                color = old_label['color']
            if readable is None:
                readable = old_label['readable']

            # skip if no instance specific information is available
            if old_name in instance_specific_information:
                new_instance_specific_information[new_name]['raw_true_positives'] += instance_specific_information[old_name]['raw_true_positives']
                new_instance_specific_information[new_name]['weighted_true_positives'] += instance_specific_information[old_name]['weighted_true_positives']
                new_instance_specific_information[new_name]['raw_false_negatives'] += instance_specific_information[old_name]['raw_false_negatives']
                new_instance_specific_information[new_name]['weighted_false_negatives'] += instance_specific_information[old_name]['weighted_false_negatives']

        id_mapping += [current_ids]

        new_labels.append({
            'name': new_name,
            'readable': readable,
            'evaluate': evaluate,
            'color': color,
            'instances': instances,
        })

    nr_labels = len(new_labels)
    reduced_confusion_matrix = np.zeros((nr_labels, nr_labels), dtype=np.uint64)
    for i, j in itertools.product(range(nr_labels), range(nr_labels)):
        reduced_confusion_matrix[i, j] = confusion_matrix[id_mapping[i], :][:, id_mapping[j]].sum()

    return (new_labels, reduced_confusion_matrix, new_instance_specific_information)