# -*- coding: utf-8 -*-
# @Author: Aliaksei Halachkin
# @Date:   2016-10-23 12:15:36
# @Last Modified by:   Aliaksei Halachkin
# @Last Modified time: 2017-04-22 18:48:34

"""
Train kmeans and assign profile clusters for each class
"""

import json
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.cluster import KMeans

with open('..\\configs\\feature_headers.json', 'r') as f:
    feature_headers = json.load(f)

with open('..\\configs\\class_n_clusters.json', 'r') as f:
    clusters_conf = json.load(f)

n_clusters_by_class = clusters_conf['n_clusters_by_class']
exclude_classes = clusters_conf['exclude_classes']


def get_df():
    #load the data
    df = pd.read_csv("..\\..\\training_data\\trainset_v3.csv", sep=';')
    df = df[~df.class_name.isin(exclude_classes)]

    # df.class_name = df.class_name.apply(lambda s : int(s.split('-')[0]))

    #prepare the data
    for f in feature_headers['feature_names']:
        try:
            if df[f].dtype == object:
                df[f] = df[f].apply(lambda x: x.replace(',', '.'))
        except:
            pass
        try:
            if df[f].dtype != pd.types.dtypes.np.int64:
                df[f] = df[f].apply(lambda x: float(x))
        except:
            pass
        
    return df


df = get_df()

classes = df.class_name.unique()
X = df[feature_headers['profile_features']].as_matrix()  #use only profile values!!
X = MinMaxScaler().fit_transform(X)
y = df.class_name.as_matrix()

#train kmeans for each class
kmeans_by_class = dict()
for cl, n_clusters in n_clusters_by_class.items():
    if n_clusters > 1:
        print "computing clusters for " + cl
        kmeans = KMeans(n_clusters = n_clusters, n_init=100, max_iter=1000)
        kmeans.fit(X[y==cl])
        kmeans_by_class[cl] = kmeans
        
#set profile clusters column

df['PCluster'] = 0
for index, row in df.iterrows():
    if (row.class_name in n_clusters_by_class) and (row.class_name in kmeans_by_class):
        ind = kmeans_by_class[row.class_name].predict([row[feature_headers['profile_features']]])
        df.set_value(index, 'PCluster', ind[0])
 
#save 
df.to_csv(path_or_buf='..\\..\\training_data\\trainset_v3_profile_clusters.csv',
       sep=';', columns=df.columns, header=True, index=False)
