# -*- coding: utf-8 -*-
"""
    File name:      predict_ecg.py
    Author:         Tetsuro Tatsuoka
    Date created:   04/12/2018
    Last modified:  04/12/2018
    Version:        1.0.0
    Python version: 3.6.3
    Description:    Confirm anomaly detection for ECG

    Revision history:
        1.0.0   04/12/2018  - Initial coding.
"""
import os
import numpy as np
import pandas as pd
import pickle
import matplotlib.pyplot as plt

fpath = 'ecg_data'
INOUT_SIZE = 50
HIDDEN_SIZE = 80

def relu(x):
    """ Calculate ReLU function
    """
    return np.maximum(0, x)
    
def conv_subseq(x, w):
    """ Convert to subsequence time series
    """
    subseq_size = len(x) - w + 1
    subseq = np.zeros((subseq_size, w))
    for i in range(subseq_size):
        start_idx = i
        end_idx = w + i
        subseq[i,:] = x[start_idx:end_idx].flatten()
    return subseq

""" float """
dat = pd.read_csv(os.path.join(fpath, 'wave_data_234_152000_156000_half_norm.csv'), header=None)
seq_dat = conv_subseq(np.array(dat), INOUT_SIZE)
weight = np.array(pickle.load(open("model_weights_ecg.pkl", "rb")))

hid_layer = np.zeros(HIDDEN_SIZE)
out_layer = np.zeros_like(seq_dat)

for k in range(seq_dat.shape[0]):
    for i in range(HIDDEN_SIZE):
        hid_layer[i] = 0.0
        for j in range(INOUT_SIZE):
            hid_layer[i] = hid_layer[i] + seq_dat[k,j] * weight[0][j,i]
        hid_layer[i] = relu(hid_layer[i] + weight[1][i])
        
    for i in range(INOUT_SIZE):
        for j in range(HIDDEN_SIZE):
            out_layer[k,i] = out_layer[k,i] + hid_layer[j] * weight[2][j,i]
        out_layer[k,i] = relu(out_layer[k,i] + weight[3][i])

diff_val = out_layer - seq_dat
score_s = np.power(diff_val, 2)
score_ms = np.sum(score_s, axis=1)
score_rms = np.sqrt(score_ms) 

plt.figure()
plt.plot(score_rms)
plt.show()

plt.figure()
plt.plot(seq_dat[260,:])
plt.plot(out_layer[260,:])
plt.show()

max_idx = np.where(score_rms == np.max(score_rms))[0][0]
plt.figure()
plt.plot(seq_dat[max_idx,:])
plt.plot(out_layer[max_idx,:])
plt.show()


""" int32 """
Q_FMT = 14
dat = pd.read_csv(os.path.join(fpath, 'wave_data_234_152000_156000_half_norm_Q14.csv'), header=None)
seq_dat = conv_subseq(np.array(dat, dtype=np.int32), INOUT_SIZE)
seq_dat = np.int32(seq_dat)
weight = np.array(pickle.load(open("model_weights_ecg.pkl", "rb")))
for i in range(len(weight)):
    weight[i] = np.round(weight[i]*(2**Q_FMT))
    weight[i] = np.int32(weight[i])

hid_layer = np.zeros(HIDDEN_SIZE, dtype=np.int32)
out_layer = np.zeros_like(seq_dat, dtype=np.int32)


for k in range(seq_dat.shape[0]):
    for i in range(HIDDEN_SIZE):
        hid_layer[i] = 0
        for j in range(INOUT_SIZE):
            hid_layer[i] = hid_layer[i] + seq_dat[k,j] * weight[0][j,i] / (2**Q_FMT)
        hid_layer[i] = relu(hid_layer[i] + weight[1][i])
        
    for i in range(INOUT_SIZE):
        for j in range(HIDDEN_SIZE):
            out_layer[k,i] = out_layer[k,i] + hid_layer[j] * weight[2][j,i] / (2**Q_FMT)
        out_layer[k,i] = relu(out_layer[k,i] + weight[3][i])

diff_val = out_layer - seq_dat
score_s = np.power(diff_val, 2)
score_ms = np.sum(score_s, axis=1)
score_rms = np.sqrt(score_ms) 

plt.figure()
plt.plot(score_rms)
plt.show()

plt.figure()
plt.plot(seq_dat[260,:])
plt.plot(out_layer[260,:])
plt.show()

max_idx = np.where(score_rms == np.max(score_rms))[0][0]
plt.figure()
plt.plot(seq_dat[max_idx,:])
plt.plot(out_layer[max_idx,:])
plt.show()



