
# coding: utf-8

# In[7]:

import pandas as pd
import numpy as np
from bokeh.io import output_file, show, curdoc,set_curdoc
from bokeh.layouts import widgetbox,layout,row,gridplot
from bokeh.models import MultiSelect,Select,ColumnDataSource,Slider,TextInput,Dropdown
from bokeh.models import Button as bb
from bokeh.plotting import figure
import sklearn.metrics as fs
from os import listdir
from os.path import isfile, join


# In[8]:

#code to insert logo in the plot
logo = figure(x_range=(0,3), y_range=(0,1),tools="",toolbar_location=None,
              x_axis_location=None, y_axis_location=None,height=100)
logo.xgrid.grid_line_color = None
logo.ygrid.grid_line_color = None
logo.outline_line_color = None
logo.image_url(url=["C:\\Users\\dgurram\\Desktop\\ASF\\Work on\\referrence\\Amsted Rail Logo.png"]
               ,x=0,y=1,w=3,h=0.8)

#Initialization
Default = "C:\\Users\dgurram\Desktop\ASF\Work On"
data = pd.DataFrame()
featurevalues = list()
fs_methods = dict({'Mutual Information':'mutual_info_score',
                   'Adjusted Mutual Information':'adjusted_mutual_info_score',
                  'Normalized Mutual Information':'normalized_mutual_info_score'})
fsl = list(fs_methods.keys())[0]
numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
discrete_options = ['Default','Equal width binning','Equal percentile binning']

mypath = Default
files = [f for f in (listdir(mypath))if ((f.endswith)('.xlsx') or f.endswith('.xls'))]
menu = list(zip(*[iter(files)]*1,*[iter(files)]*1))


# In[9]:

#Get dataset from user system
def updatedata(attr, old, new):
    global featurevalues
    global data
    global Default
    #clear the existing values if any while changing datasets
    target.options = list()
    features.options = list()
    source.data.update(emptysrc.data) 
    #File selection window
    name = mypath + "\\" + selectdata.value
    #Set the selected file as a pandas dataframe
    #Update the feature and target options based on the chosen data
    data = pd.read_excel(name)
    selectdata.label = str(name) #To indicate which file has beeen selected
    featurevalues = list(data)
    target.options = featurevalues
    features.options = featurevalues

def get_data(t,f,fsl,dm,e,p):
    #Discritize continuous data based on selection
    all_data = data[f]
    if list(all_data.select_dtypes(include=numerics)):
        num_vars = list(all_data.select_dtypes(include=numerics))
        if dm != discrete_options[0]: #Discretization is done only upon selection
            if dm == discrete_options[1]:
                num_bins = e
                for i in range(0,len(num_vars)):
                    bins = np.arange(min(data[num_vars[i]]),
                                     max(data[num_vars[i]]),
                                     (max(data[num_vars[i]])-min(data[num_vars[i]]))/num_bins)
                    #Replacing the selected continuous columns in dataset with discretized data.
                    data[num_vars[i]] = np.digitize(data[num_vars[i]],bins)                     
            elif dm == discrete_options[2]:
                pct = p
                for i in range(0,len(num_vars)):
                    bins = np.arange(min(data[num_vars[i]]),
                                     max(data[num_vars[i]]),
                                     np.percentile(data[num_vars[i]],pct))
                    #Replacing the selected continuous columns in dataset with discretized data.
                    data[num_vars[i]] = np.digitize(data[num_vars[i]],bins)
    #Feature selection score calculation
    res = lambda x:getattr(fs,fs_methods[fsl])(data[x],data[t])    
    score = list()
    for i in range(0,len(f)):score.append(res(f[i]))
    plot_data = pd.DataFrame({'feature' : list(f), 'mutual_info' : score}).sort_values(by='mutual_info',ascending=False)
    return ColumnDataSource(data = plot_data)

#Initilizing the plot
def make_plot(source):
    plot = figure(title = "Feature Selection",width = 800)
    plot.vbar(x='feature', width=0.5, bottom=0,top='mutual_info',source=source,color="firebrick")
    return plot

#function to update plot on callback
def update_plot(attr, old, new): 
    tn = target.value
    fn = features.value
    fsn = feature_sel.value    
    dmn = discrete_method.value
    en = Ebinning.value
    pn = Pbinning.value
    if (tn and fn) :
        src = get_data(tn,fn,fsn,dmn,en,pn)
        source.data.update(src.data)
        plot.x_range.factors = fn
        #plot.x_range.factors = source.data['feature']
    layout.children = [widgets,plot]
    if discrete_method.value == discrete_options[1] :
        layout.children.append(Ebinning)
    elif discrete_method.value == discrete_options[2]:
        layout.children.append(Pbinning)   


# In[10]:

#data = pd.read_excel('C:\\Users\\dgurram\\Desktop\\ASF\\Work on\\New Sand Trial.xlsx')
#text = TextInput(value="Default")


#Initial widgets and plots declaration
selectdata = Dropdown(label="Dropdown button", button_type="success", menu=menu)
target = Select(title="Select Target")
t = target.value
features =  MultiSelect(title="Select Features")
f = features.value
discrete_method = Select(title="Select Discretization Method",
                        value = discrete_options[0],
                        options = discrete_options)
dm = discrete_method.value
Ebinning = Slider(title="Select num of bins", value=5, start=1, end=20, step=1)
Pbinning = Slider(title="Select Percentile", value=5, start=1, end=100, step=5)
feature_sel = Select(title="Select Feature Selection Method",value = fsl, options = list(fs_methods.keys()))
emptysrc = ColumnDataSource(pd.DataFrame({'feature' : [''], 'mutual_info' : ['']}))
source = ColumnDataSource(pd.DataFrame({'feature' : [''], 'mutual_info' : ['']}))
plot = make_plot(source) 


# In[11]:

#callback
selectdata.on_change('value',updatedata)
controls = [target, features,feature_sel,discrete_method,Ebinning,Pbinning] 
for control in controls:
    control.on_change('value',update_plot)


# In[12]:

#printing on web page
widgets = widgetbox(selectdata,features,target,feature_sel,discrete_method)
layout = row(widgets,plot)
curdoc().add_root(layout)
curdoc().title = "FSapp"
    #[gridplot(logo,ncols=2)],

