#!/usr/bin/env python
# coding: utf-8

# In[1]:


import datasethelper,lewishelper
import copy
import pandas as pd
import sys

cl_type="randomforest"
#predvariable='coke'
predvariable='mushrooms'
#print ("S")
#df=datasethelper.process_adult()
(X_train,y_train,df,pred,model)=datasethelper.process_drug(cl_type,predvariable)

def process(lst):
    final=[]
    for v in lst:
        if v>0:
            final.append(1)
        else:
            final.append(0)
    return final
df[predvariable]=process(pred)




featlst=['Age','Gender','Edu','Country','Ethnicity','Nscore','Escore','Oscore','Ascore','Cscore','impulsive','SS',predvariable]
#df[predvariable]=pred
backdoor={'Age':[],'Gender':[],'Country':['Age','Gender'],'Ethnicity':[],'marital':['Gender','Country','Ethnicity','Age'],'edu':['Age','sex','marital','country'],
              'class':['Age','sex','marital','country','edu'],'occupation':['Age','sex','marital','country','edu'],
              'hours':['Age','sex','marital','country','edu']}
    
featlst=list(df.columns)
if predvariable in featlst:
    featlst.remove(predvariable)


# In[2]:


###LOcal explanations here:  Necessity
df.reset_index()
row=list(df.columns)
value_map={}
for feat in row:
    values=list(set(df[feat]))
    value_map[feat]=values



descendant={'Age':['Edu','Nscore','Escore','Oscore','Ascore','Cscore','SS','impulsive'],'Ethnicity':['Edu','Nscore','Escore','Oscore','Ascore','Cscore','SS','impulsive'],'Country':['Edu','Nscore','Escore','Oscore','Ascore','Cscore','SS','impulsive'],'Gender':['Edu','Nscore','Escore','Oscore','Ascore','Cscore','SS','impulsive'],'country':['marital','edu','class','occupation','hours'],'marital':['edu','class','occupation','hours'],'edu':['class','occupation','hours'],
          'class':[],'occupation':[],'Edu':['Nscore','Escore','Oscore','Ascore','Cscore','SS','impulsive'],
          'Nscore':[],'SS':[],'Oscore':[],'Ascore':[],'Cscore':[],'impulsive':[],'Escore':[]}
#Age	Gender	Edu	Country	Ethnicity	Nscore	Escore	Oscore	Ascore	Cscore	impulsive	SS
#print(row)
curr=df.iloc[0]
#print (value_map)
    
featnames=copy.deepcopy(row)
featnames.remove(predvariable)
orig_row=row
row=copy.deepcopy(orig_row)

def increase_val(row):
    maxscores=[]
    featlst=['Age','Gender','Country','Ethnicity','Edu','Nscore','SS','Escore','Oscore','Ascore','Cscore','impulsive']
    for feat in ['Age','Gender','Country','Ethnicity','Edu','Nscore','SS','Escore','Oscore','Ascore','Cscore','impulsive']:#featnames:
        #print(featnames,feat,"here")
        row.remove(predvariable)
        rowval=[]
        for f in row:
            rowval.append(curr[f])

        curr_feat=feat
        ind=row.index(curr_feat)
        prevval=rowval[ind]
        rowval.pop(ind)
        row.pop(ind)

        descendantlst=descendant[feat]
        for f in descendantlst:
            ind=row.index(f)
            rowval.pop(ind)
            row.pop(ind)

        values=value_map[feat]
        max_suff=-1
        suff_val=-1
        #print("values",values,feat,row,rowval)
        for val in values:
            #if val<=prevval:
            #    continue

            #Decreasing
            #suff=lewishelper.get_scores_regression(df,[curr_feat],[prevval],[val],row,rowval,[],'mushrooms')[0]

            suff=lewishelper.get_scores_regression(df,[curr_feat],[val],[prevval],row,rowval,[],'mushrooms')[0]
            #print(curr_feat,val,prevval,row,rowval,suff,"scores ehre")
            max_suff=max(max_suff,suff)
            if max_suff==suff:
                suff_val=val
        #print (feat,max_suff,suff_val,prevval)
        maxscores.append(max_suff)
        row.append(feat)
        rowval.append(prevval)
        row=copy.deepcopy(orig_row)
    #print (featnames,maxscores)
    return (featlst,maxscores)

def decrease_val(row):
    maxscores=[]
    featlst=['Age','Gender','Country','Ethnicity','Edu','Nscore','SS','Escore','Oscore','Ascore','Cscore','impulsive']
    for feat in ['Age','Gender','Country','Ethnicity','Edu','Nscore','SS','Escore','Oscore','Ascore','Cscore','impulsive']:#featnames:
        #print(featnames,feat,"here")
        row.remove(predvariable)
        rowval=[]
        for f in row:
            rowval.append(curr[f])

        curr_feat=feat
        ind=row.index(curr_feat)
        prevval=rowval[ind]
        rowval.pop(ind)
        row.pop(ind)

        descendantlst=descendant[feat]
        for f in descendantlst:
            ind=row.index(f)
            rowval.pop(ind)
            row.pop(ind)

        values=value_map[feat]
        max_suff=-1
        suff_val=-1
        #print("values",values,feat,row,rowval)
        for val in values:
            #if val<=prevval:
            #    continue

            #Decreasing
            #suff=lewishelper.get_scores_regression(df,[curr_feat],[prevval],[val],row,rowval,[],'mushrooms')[0]

            suff=lewishelper.get_scores_regression(df,[curr_feat],[prevval],[val],row,rowval,[],'mushrooms')[0]
            #print(curr_feat,val,prevval,row,rowval,suff,"scores ehre")
            max_suff=max(max_suff,suff)
            if max_suff==suff:
                suff_val=val
        #print (feat,max_suff,suff_val,prevval)
        maxscores.append(max_suff)
        row.append(feat)
        rowval.append(prevval)
        row=copy.deepcopy(orig_row)
    #print (featnames,maxscores)
    return (featlst,maxscores)

row1=copy.deepcopy(row)
row2=copy.deepcopy(row)
(feat_inc,inc_nec)=increase_val(row1)
(feat_dec,dec_nec)=decrease_val(row2)


# In[3]:


#print (inc_nec)
#print (dec_nec)


# In[4]:





# In[ ]:





# In[15]:


import lime
import numpy as np
import shap
(X_train,y_train,df,pred,model)=datasethelper.process_drug(cl_type,predvariable)

feature_names = list(X_train.columns)
feature_names.remove('mushrooms')
#feature_names.remove('mushrooms')
class_names = np.unique(pred).tolist()
# Lime explanations
limeExplainer = lime.lime_tabular.LimeTabularExplainer(X_train[feature_names].to_numpy(), feature_names=feature_names,
                                                       class_names=class_names)


# Shapley scores
#shap.initjs()
#shapExplainer = shap.TreeExplainer(model)
#shap_values = shapExplainer.shap_values(X_train)


# In[ ]:





# In[27]:


df=df[feature_names]
model.predict_proba([df.iloc[0]]).astype(float)
#df.iloc[0]


# In[28]:


predict_fn = lambda x: model.predict_proba(x).astype(float)
feat=feature_names
limeExp = limeExplainer.explain_instance(df.iloc[0], predict_fn, num_features=12)


# In[29]:


#limeExp.show_in_notebook(show_all=False)


# In[30]:


lime=limeExp.as_list()


# In[31]:


import matplotlib.pyplot as plt


# Shapley scores
#shap.initjs()
shapExplainer = shap.TreeExplainer(model)
shap_values = shapExplainer.shap_values(df[feat])
#shap.force_plot(shapExplainer.expected_value[1], shap_values[1][0], df.iloc[0],show=True,matplotlib=True).savefig('german_shap.pdf')


# In[32]:


curr=0
shap.force_plot(shapExplainer.expected_value[1], shap_values[1][curr], df.iloc[curr][feat],show=True,matplotlib=True)
shap_values[1][curr]


# In[34]:


shapval=shap_values[1][curr]


# In[ ]:





# In[ ]:





# In[1]:





# In[ ]:





# In[6]:


raven=inc_nec
ravenname=feat_inc
ravendec=dec_nec


ravendec = [ele*-1  for ele in ravendec]
raven_sign=[3,4]
for v in raven_sign:
    tmp=raven[v]
    raven[v]=ravendec[v]*-1
    ravendec[v]=tmp

shapname=['Age', 'Gender', 'Edu', 'Country', 'Ethnicity', 'Nscore', 'Escore', 'Oscore', 'Ascore', 'Cscore', 'impulsive', 'SS']


shapval = [ele*-1  for ele in shapval]
ravenmax = max(max([abs(ele) for ele in raven]), max([abs(ele) for ele in ravendec]))


# In[27]:


# raven is ordered 
lime_ordered=[]
limenamevals=[]
limevals=[]
for i in range(len(ravenname)):
    for j in range(len(lime)):
        if ravenname[i] in lime[j][0]:
            lime_ordered.append((lime[j][0], ravenname[i], lime[j][1]))
            limenamevals.append(lime[j][0])
            limevals.append(lime[j][1])
            
shap_ordered=[]
shapvals=[]
for i in range(len(ravenname)):
    for j in range(len(shapname)):
        if ravenname[i] in shapname[j]:
            shap_ordered.append((shapval[j], ravenname[i]))
            shapvals.append(shapval[j])


lime_sign=[1,4,6]
for i in lime_sign:
    limevals[i]=-1*limevals[i]


shap_sign=[0,3,4,9]
for i in shap_sign:
    shapvals[i]=-1*shapvals[i]

normalized_shapley=[]
normalized_lime=[]
normalized_raven=[]
normalized_ravendec=[]
for i in range(len(raven)):
    #print (ravenname[i])
    normalized_shapley.append(shapvals[i]*1.0/max([abs(ele) for ele in shapval]))
    normalized_lime.append(limevals[i]*1.0/max([abs(ele) for ele in limevals]))
    normalized_raven.append(raven[i]*1.0/ravenmax)
    normalized_ravendec.append(ravendec[i]*1.0/ravenmax)
    i+=1


# In[30]:


import scipy.stats as ss
shapley_rank=ss.rankdata([abs(ele) for ele in normalized_shapley])
lime_rank=ss.rankdata([abs(ele) for ele in normalized_lime])
raven_rank=ss.rankdata([abs(ele) for ele in normalized_raven], method='min')
ravendec_rank=ss.rankdata([abs(ele) for ele in normalized_ravendec], method='max')


# In[33]:


# select features to show
featlst=['Age', 'Gender', 'Edu', 'Country', 'Ethnicity','Ascore','SS']
feats=['age:18-24 yrs', 'sex=male', 'edu=left school','country=\nrest of the world', 'ethnicity=White','agreeableness<0','sensation>1']#, 'Nscore=10th', 'class=Private', 'occup=Other', 'hours=30']

# featlst = ravenname
# feats = featlst

shaprank_f=[]
limerank_f=[]
ravenrank_f=[]
ravendecrank_f=[]

raven_f=[]
ravendec_f=[]
lime_f=[]
shapley_f=[]

for feat in featlst:
    idx = ravenname.index(feat)
    shapley_f.append(normalized_shapley[idx])
    lime_f.append(normalized_lime[idx])
    raven_f.append(normalized_raven[idx])
    ravendec_f.append(normalized_ravendec[idx])
    shaprank_f.append(shapley_rank[idx])
    limerank_f.append(lime_rank[idx])
    ravenrank_f.append(raven_rank[idx])
    ravendecrank_f.append(ravendec_rank[idx])


# In[34]:


import matplotlib
import matplotlib.pyplot as plt
import numpy as np

import pylab as plot
fsize=20
params = {'legend.fontsize': fsize/1.1,
          'legend.handlelength': 2,
         'axes.labelsize': fsize,
         'axes.titlesize':fsize,
         'xtick.labelsize':fsize}
plot.rcParams.update(params)
font = {'family' : "sans serif", 'size'   : fsize}
matplotlib.rc('font', **font)
matplotlib.rcParams['hatch.linewidth'] = 0.3

labels=feats
# labels=limenames
x = np.arange(len(labels))  # the label locations
width = 0.25/1.2  # the width of the bars
plt.figure(figsize=(6, 10)) # in inches!

fig, ax = plt.subplots()
rects1 = ax.barh(x - 2 * width, ravendec_f, width, label='Lewis:-ve', color='lightsteelblue', edgecolor='black', hatch="\\")
rects2 = ax.barh(x - width, raven_f, width, label='Lewis:+ve', color='cornflowerblue', edgecolor='black', hatch="\\")
# rects2 = ax.barh(x, ravendec, width, label='Our-Down',color='royalblue', edgecolor='black')
# rects3 = ax.barh(x + width, lime_0, width, label='Lime: O=0',color='lightcoral', edgecolor='black', hatch="/")
# rects3 = ax.barh(x + 2*width, lime_1, width, label='Lime: O=1',color='y', edgecolor='black', hatch="-")
rects3 = ax.barh(x, lime_f, width, label='LIME',color='snow', edgecolor='black', hatch="/")
rects4 = ax.barh(x + width, shapley_f, width, label='SHAP',color='lightcoral', edgecolor='black', hatch="|")

# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_xlabel('Normalized score', fontsize=fsize, labelpad=10)
ax.set_yticks(x)
ax.set_yticklabels(labels, fontsize=fsize)

ax.set_xticks(range(-1, 2, 1))
ax.set_xticklabels([abs(y) for y in range(-1, 2, 1)])
ax.xaxis.set_ticks_position('bottom')
ax.xaxis.set_label_position('bottom')
# ax.legend(loc=0)
ax.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
       ncol=2, mode="expand", borderaxespad=0.)
# ax.invert_yaxis()
plt.xticks(np.arange(-1, 1.2, 1))
matplotlib.pyplot.hlines(labels,-1,1, color='gainsboro', zorder=0, linestyles='dashed')

def autolabel(rects,rank, col):
    """Attach a text label above each bar in *rects*, displaying its height."""
    i=0
    for rect in rects:
        height = rect.get_width()
        offset = 0.07
        if height < 0:
            offset = offset * -1
        val=len(shapley_rank)-int(rank[i])+1
        ax.annotate('{}'.format(val),
                    xy=(height + offset, rect.get_y()),
                    xytext=(0, -5),  # 3 points vertical offset
                    textcoords="offset points",
                    ha='center', va='bottom', fontsize=fsize/1.3, color=col)
        i+=1


autolabel(rects1,ravendecrank_f, 'black')
autolabel(rects2,ravenrank_f, 'black')
autolabel(rects3,limerank_f, 'black')
autolabel(rects4,shaprank_f, 'black')

# handles, labels = ax.get_legend_handles_labels()
# ax.legend(handles[::-1], labels[::-1])

# plt.show()
figure = plt.gcf() # get current figure
figure.set_size_inches(8,12)
fig.tight_layout()
plt.savefig('newplots/drug_local_positive_related.pdf')


# In[ ]:




