import_cluster.py 4.66 KB
#! /usr/bin/python3

from sqlalchemy import func
import numpy as np

from reduce_cluster import reduce_cluster

def get_signatures(signatures_dict):
    return [(fit, ftra) for fit, (_, ftra) in signatures_dict.items()]

def pick_frames(frame_signature, session, TransformationTable):
    # selects ids and returns them
    # max_id = session.query(func.max(Table.column)).scalar()
    frame_id, transformation = frame_signature
    max1 = session.query(func.max(TransformationTable.similarity)).filter_by(frame1=frame_id).filter_by(signature1=transformation).first()
    max1 = max1[0]
    max2 = session.query(func.max(TransformationTable.similarity)).filter_by(frame2=frame_id).filter_by(signature2=transformation).first()
    max2 = max2[0]
    maximum = max(max1, max2)
    treshold = 0.8 * maximum
    signatures_dict = {frame_id: (1.0, transformation)}
    part1 = session.query(TransformationTable).filter(TransformationTable.frame1==frame_id).filter(TransformationTable.signature1==transformation).filter(TransformationTable.similarity>=treshold)
    for entry in part1:
        fid = entry.frame2
        ftra = entry.signature2
        if fid not in signatures_dict:
            signatures_dict[fid] = (entry.similarity, ftra)
        else:
            val, _ = signatures_dict[fid]
            if val < entry.similarity:
                signatures_dict[fid] = (entry.similarity, ftra)
    part2 = session.query(TransformationTable).filter(TransformationTable.frame2==frame_id).filter(TransformationTable.signature2==transformation).filter(TransformationTable.similarity>=treshold)
    for entry in part2:
        fid = entry.frame1
        ftra = entry.signature1
        if fid not in signatures_dict:
            signatures_dict[fid] = (entry.similarity, ftra)
        else:
            val, _ = signatures_dict[fid]
            if val < entry.similarity:
                signatures_dict[fid] = (entry.similarity, ftra)
    return get_signatures(signatures_dict), treshold

def ids_from_signatures(frame_signatures):
    return [i for i, _ in frame_signatures]
    
def import_cluster(frame_signatures, session, TransformationTable):
    ids = ids_from_signatures(frame_signatures)
    return session.query(TransformationTable).filter(TransformationTable.frame1.in_(ids)).filter(TransformationTable.frame2.in_(ids)).all()

def make_enumerator_dict(keys):
    d = {}
    for i, key in enumerate(keys):
        d[key] = i
    return d

def cluster_to_matrix(frame_signatures, cluster_entries, treshold):
    i = len(frame_signatures)
    matrix = np.zeros((i, i))
    signature_dict = make_enumerator_dict(frame_signatures)
    for entry in cluster_entries:
        f1 = (entry.frame1, entry.signature1)
        f2 = (entry.frame2, entry.signature2)
        if f1 in signature_dict and f2 in signature_dict:
            i = signature_dict[f1]
            j = signature_dict[f2]
            matrix[i,j] = entry.similarity
            matrix[j,i] = entry.similarity
    m = np.max(matrix)
    if m > 0.0:
        normalised_matrix = matrix / m
        normalised_treshold = treshold / m
    else:
        normalised_matrix = matrix
        normalised_treshold = treshold
    return np.matrix(frame_signatures), normalised_matrix, normalised_treshold

# frame_id, transformation = frame_signature
def create_cluster(frame_signature, session, TransformationTable):
    frame_signatures, treshold = pick_frames(frame_signature, session, TransformationTable)
    cluster_entries = import_cluster(frame_signatures, session, TransformationTable)
    cluster_matrix_treshold = cluster_to_matrix(frame_signatures, cluster_entries, treshold)
    return cluster_matrix_treshold

def find_cluster(frame_id, session, TT_dict):
    result = np.matrix([[frame_id, '']])
    l = 1
    result_transformation = 'zero'
    for transformation, TransformationTable in TT_dict.items():
        signs = get_frame_signatures(frame_id, session, TransformationTable)
        for sign_tuple in signs:
            (sign,) = sign_tuple
            frame_signature = (frame_id, sign)
            keys, matrix, treshold = create_cluster(frame_signature, session, TransformationTable)
            new_keys = reduce_cluster(matrix, keys, treshold)
            if len(new_keys) > l:
                result = new_keys
                l = len(new_keys)
                result_transformation = transformation
    return result, result_transformation


def get_frame_signatures(frame_id, session, TransformationTable):
    signs  = session.query(TransformationTable.signature1).filter(TransformationTable.frame1==frame_id).distinct().all()
    signs += session.query(TransformationTable.signature2).filter(TransformationTable.frame2==frame_id).distinct().all()
    signs = set(signs)
    return signs