# -*- coding: utf-8 -*-
"""
    File name:      generate_code_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:    Generate C source code of ECG data and weights data

    Revision history:
        1.0.0   04/12/2018  - Initial coding.
"""
import os
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from read_weights import read_weights

Q_FMT = 14

def conv_norm(x):
    """ Convert to normalized data
    """
    ms = MinMaxScaler()
    return ms.fit_transform(pd.DataFrame(x))
    
def export_c_source_dat(file_name, dat, dtype='double', n_col=100):
    """
        Export C source code of input data
    
        Parameters:
            file_name   save file name
            dat         input data
            dtype       data type
            n_col       number of data in a line
    """
    with open(file_name, 'w')  as f:
        len_str = str(len(dat))
        dat = np.array(dat).reshape(-1,n_col)
        if dtype == 'int32':
            f.write('// Q' + str(Q_FMT) + ' format\n\n')
            dat = np.int32(np.round(dat*(2**Q_FMT)))
        else:
            dtype = 'double'            

        f.write('// ' + len_str + ' points\n')
        f.write('const ' + dtype + ' ECG_DAT[' + len_str + '] = {\n')
        for i in range(dat.shape[0]):
            f.write(', '.join(map(str, dat[i,:])))
            if i == (dat.shape[0]-1):
                f.write('\n')
            else:
                f.write(',\n')                        
        f.write('};\n')
        f.write('\n')
            
def export_c_source_weights(file_name, weights, dtype='double'):
    """
        Export C source code of weight data
    
        Parameters:
            file_name   save file name
            weights     weight data
            dtype       data type
    """
    with open(file_name, 'w')  as f:
        n_b = 1
        n_w = 1
        if dtype == 'int32':
            f.write('// Q' + str(Q_FMT) + ' format\n\n')
        else:
            dtype = 'double'            

        for w in weights:
            if dtype == 'int32':
                w = np.int32(np.round(w*(2**Q_FMT)))
                
            if len(w.shape) == 1:
                len_str = str(w.shape[0])
                f.write('// ' + len_str + ' weights\n')
                f.write('const ' + dtype + ' B' + str(n_b) + '[' + len_str + '] = {\n')
                f.write(', '.join(map(str, w)))
                f.write('\n};\n')
                n_b = n_b + 1
            else:
                w = w.T
                len_str = str(w.shape[0] * w.shape[1])
                f.write('// ' + str(w.shape[0]) + ' x ' + str(w.shape[1]) + ' weights\n')
                f.write('const ' + dtype + ' W' + str(n_w) + '[' + len_str + '] = {\n')
                for i in range(w.shape[0]):
                    f.write(', '.join(map(str, w[i,:])))
                    if i == (w.shape[0]-1):
                        f.write('\n')
                    else:
                        f.write(',\n')                        
                f.write('};\n')
                n_w = n_w + 1
            f.write('\n')

if __name__ == "__main__" :

    """ ECG test data """
    fpath = 'ecg_data'

    # Read ECG data    
    dat = pd.read_csv(os.path.join(fpath, 'wave_data_234_152000_156000.csv'))
    dat = dat.iloc[:,0] # Only Ch1
    
    # Preprocessing
    dat_half = pd.Series(np.array(dat[::2]) + np.array(dat[1::2])) / 2.0
    dat_norm = conv_norm(dat_half)
    dat_norm_Q14 = np.array(np.round(dat_norm * (2**14)), dtype=np.int32)
    
    dat_half = pd.DataFrame(dat_half)
    dat_norm = pd.DataFrame(dat_norm)
    dat_norm_Q14 = pd.DataFrame(dat_norm_Q14)

    # float    
    fname = os.path.join(fpath, 'wave_data_234_152000_156000_half_norm.csv')
    dat_norm.to_csv(fname, header=None, index=None)
    export_c_source_dat('test_data_ecg.c', dat_norm)
    
    # int32
    fname = os.path.join(fpath, 'wave_data_234_152000_156000_half_norm_Q14.csv')
    dat_norm_Q14.to_csv(fname, header=None, index=None)
    export_c_source_dat('test_data_ecg_i.c', dat_norm, dtype='int32')
    
    """ ECG weights """    
    path, weight = read_weights(os.path.join('.', 'model_weights_ecg.h5'))
    
    # float
    export_c_source_weights('weights_ecg.c', weight)
    
    # int32
    export_c_source_weights('weights_ecg_i.c', weight, 'int32')
