# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Features
# - Distribution of LOS
# - Distribution of LOS in ICU
# - Number of events in one hour

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import os
import math
import numpy as np
import random
from scipy.stats import norm
sns.set(color_codes=True)

# +
# connect database
import psycopg2
import psycopg2.extras
import pandas as pd
def execute_query(query):
    try:
        params = {
            'database': 'mimic',
            'user': 'mimicuser',
            'password': '<PASSWORD>',
            'host': 'localhost'
        }
        # use our connection values to establish a connection
        conn = psycopg2.connect(**params)
        # create a psycopg2 cursor that can execute queries
        cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        cursor.execute('set search_path to mimiciii')

        return fetch(cursor, query)

    except Exception as e:
        raise e


def fetch(cursor, query):
    """Summary

    Args:
        cursor (TYPE): Description
        query (str): query instance

    Returns:
        list: list of DictRow
    """
    rows = []
    cursor.execute(query)
    for row in cursor:
        rows.append(row)
    return rows

def execute_query_to_df(query):
    rows = execute_query(query)
    df = pd.DataFrame.from_dict([i.copy() for i in rows])
    return df


# -

def plot_dist(values, upper_bound=None, axlabel=None, fname=None):
    values = [round(v) for v in values if v is not None and v != np.nan]
    min_percentile = 5
    max_percentile = 95
    
    min_value = math.floor(np.percentile(values, min_percentile) * 10) / 10
    max_value = math.floor(np.percentile(values, max_percentile) * 10) / 10
    print('min value (5-percentile):', min_value)
    print('max value (95-percentile):', max_value)
    dist_values = values
    if upper_bound is not None:
        dist_values = [v for v in values if v <= upper_bound]
    sns_plot = sns.distplot(dist_values, kde=False, axlabel=axlabel)
    fig = sns_plot.get_figure()
    fig.show()
    if fname is not None:
        fig.savefig(fname)
#     fig.clear()


def define_los_group(values):
    values = [int(v) for v in values if v is not None and v != np.nan]
    min_percentile = 5
    max_percentile = 95
    step = 10
    los_groups = list()
    for p in range(min_percentile, max_percentile + step, step):
        p_value = math.floor(np.percentile(values, p) * 10) / 10
#         print('%s-percentile: %s' % (p, p_value))
        los_groups.append(p_value)
    # remove duplicates and sort lists ascending
    return sorted(list(set(los_groups)))


adult_df = pd.read_csv('../data/los/view_adult_admission.csv')

heart_df = pd.read_csv('../data/los/view_first_heart_admissions.csv')

# ## 1. Distribution of LOS

# distribution LOS of all admission
plot_dist(adult_df['los_hospital'].tolist(), upper_bound=100, axlabel='day',
          fname='../backup/dist_los_all_admission.png')

los_groups = define_los_group(adult_df['los_hospital'].tolist())
los_groups

# Distribution LOS hospital of all first heart admission
heart_los_values = heart_df['los_hospital'].tolist()
plot_dist(heart_los_values, upper_bound=100, axlabel='day', fname='../backup/dist_los_1st_heart_admission.png')

# ### 1.1 Compare LOS distribution between test & train data

random.seed()
random.shuffle(heart_los_values)
splitter = int(len(heart_los_values) * 0.7)
print('70% data')
plot_dist(heart_los_values[:splitter], upper_bound=100, axlabel='day', fname=None)

print('30% data')
plot_dist(heart_los_values[splitter:], upper_bound=100, 
          axlabel='day', fname=None)

heart_los_groups = define_los_group(heart_los_values)
heart_los_groups_train = define_los_group(heart_los_values[:splitter])
heart_los_groups_test = define_los_group(heart_los_values[splitter:])

print('group of all data:', heart_los_groups)
print('group of train data:', heart_los_groups_train)
print('group of test data:', heart_los_groups_test)

# +
# load train/test data
file_train = '../data/los/cvd_los_data.train'
file_test = '../data/los/cvd_los_data.test'
print('loading LOS data from', file_train, 'and', file_test)

train_df = pd.read_csv(file_train)
test_df = pd.read_csv(file_test)
# -

# ## 2. Distribution ICU LOS

# distribution ICU LOS of all admission
plot_dist(adult_df['los_icu_h'].dropna().tolist(), upper_bound=30*24, axlabel='hour', fname=None)

# distribution ICU LOS of heart admission
plot_dist(heart_df['los_icu_h'].dropna().tolist(), upper_bound=30*24, axlabel='hour', fname=None)

# ## 3. Number of events in one hour

freq_chartevents = execute_query_to_df('SELECT * FROM v_freq_chartevents')

freq_chartevents.columns

hours_ago = freq_chartevents['hours_ago'].tolist()
numevents = freq_chartevents['numevents'].tolist()

print('min # events per hour:', min(numevents))
print('max # events per hour:', max(numevents))
plot_dist(numevents, upper_bound=200, axlabel='# events per hour', 
          fname='../backup/dist_nb_events_per_hour.png')

freq_chartevents_filter = execute_query_to_df(
    'SELECT * FROM v_freq_chartevents WHERE hours_ago <= 240 AND numevents <= 200')

freq_chartevents_filter.shape

hours_ago_x = freq_chartevents_filter['hours_ago'].tolist()
numevents_y = freq_chartevents_filter['numevents'].tolist()

sns.set(style="ticks")
sns_plot = sns.jointplot(x=hours_ago_x, y=numevents_y, 
                         kind="hex", # scatter” | “reg” | “resid” | “kde” | “hex”,
                         )
sns_plot.set_axis_labels('# hours after admitted', '# events per hour')
sns_plot.savefig('../backup/dist_freq_events_per_hours_in_10days.png')

from sklearn import metrics

metrics.adjusted_rand_score([0, 0, 0, 1, 1, 1], [0, 0, 1, 1, 2, 2])

StarcoderdataJupyterScriptsDedupFiltered