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

from sqlalchemy import func
import numpy as np

from reduce_cluster import reduce_cluster
from local_db import FreeFrames

import time

RULES_ORDER = [
    "zero",
    "mnis",
    "msd",
    "mnismsd",
    "itets",    
    "tecs",
    "fs",
    "ft",
    "fit",
    "frc",
    "rst",
    "rct",
    "pct",
    "itetsmnis",
    "tecsmnis",
    "fsmnis",
    "ftmnis",
    "fitmnis",
    "frcmnis",
    "rstmnis",
    "rctmnis",
    "pctmnis",
    "itetsmsd",
    "tecsmsd",
    "fsmsd",
    "ftmsd",
    "fitmsd",
    "frcmsd",
    "rstmsd",
    "rctmsd",
    "pctmsd",
    "itetsmnismsd",
    "tecsmnismsd",
    "fsmnismsd",
    "ftmnismsd",
    "fitmnismsd",
    "frcmnismsd",
    "rstmnismsd",
    "rctmnismsd",
    "pctmnismsd",
    "fsrst",
    "fsrct",
    "fspct",
    "ftrst",
    "ftrct",
    "ftpct",
    "fitrst",
    "fitrct",
    "fitpct",
    "frcrst",
    "frcrct",
    "frcpct",
    "fsrstmnis",
    "fsrctmnis",
    "fspctmnis",
    "ftrstmnis",
    "ftrctmnis",
    "ftpctmnis",
    "fitrstmnis",
    "fitrctmnis",
    "fitpctmnis",
    "frcrstmnis",
    "frcrctmnis",
    "frcpctmnis",
    "fsrstmsd",
    "fsrctmsd",
    "fspctmsd",
    "ftrstmsd",
    "ftrctmsd",
    "ftpctmsd",
    "fitrstmsd",
    "fitrctmsd",
    "fitpctmsd",
    "frcrstmsd",
    "frcrctmsd",
    "frcpctmsd",
    "fsrstmnismsd",
    "fsrctmnismsd",
    "fspctmnismsd",
    "ftrstmnismsd",
    "ftrctmnismsd",
    "ftpctmnismsd",
    "fitrstmnismsd",
    "fitrctmnismsd",
    "fitpctmnismsd",
    "frcrstmnismsd",
    "frcrctmnismsd",
    "frcpctmnismsd",
]

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).join(FreeFrames, TransformationTable.frame2==FreeFrames.frame_id).first()
    max1 = max1[0]
    max2 = session.query(func.max(TransformationTable.similarity)).filter_by(frame2=frame_id).filter_by(signature2=transformation).join(FreeFrames, TransformationTable.frame1==FreeFrames.frame_id).first()
    max2 = max2[0]
    maximum = max(max1, max2)
    if maximum is None:
        maximum = 0.0
    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).join(FreeFrames, TransformationTable.frame2==FreeFrames.frame_id)
    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).join(FreeFrames, TransformationTable.frame1==FreeFrames.frame_id)
    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 in RULES_ORDER:
        TransformationTable = TT_dict[transformation]
        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, l)
            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