import numpy as np
import tensorflow as tf
import os

from scipy.io import savemat
from scipy.io import loadmat
from scipy.misc import imread
from scipy.misc import imsave

from alexnet_face_classifier import *
import matplotlib.pyplot as plt
plt.switch_backend('agg')


class backprop_graph:
    def __init__(self, num_classes, nhid, cnn):
        self.num_classes = num_classes
        self.inputs = tf.placeholder(tf.float32, shape = [None, 227, 227, 3], name='input')
        self.labels_1hot = tf.placeholder(tf.float32, shape=[None, self.num_classes])
        self.cnn = cnn(self.inputs, None, self.num_classes)
        self.cnn.preprocess()
        self.cnn.convlayers() 
        self.cnn.fc_layers(transfer_learning=False, nhid=nhid) 
    
    def classifier_graph(self, temp=3.0):
        self.probabilities = tf.nn.softmax(self.cnn.fc2/temp)
        self.probability = tf.tensordot(self.probabilities, self.labels_1hot, axes=[[1],[1]])
        self.log_probability = tf.log(self.probability)
    
    def guided_backprop_graph(self):
        self.grad_fc2 = tf.nn.relu(tf.gradients(self.probability, self.cnn.fc2)[0])
        self.grad_fc1 = tf.nn.relu(tf.gradients(self.cnn.fc2, self.cnn.fc1, grad_ys=self.grad_fc2)[0])
        self.grad_conv5 = tf.nn.relu(tf.gradients(self.cnn.fc1, self.cnn.conv5, grad_ys=self.grad_fc1)[0])
        self.grad_conv4 = tf.nn.relu(tf.gradients(self.cnn.conv5, self.cnn.conv4, grad_ys=self.grad_conv5)[0])
        self.grad_conv3 = tf.nn.relu(tf.gradients(self.cnn.conv4, self.cnn.conv3, grad_ys=self.grad_conv4)[0])
        self.grad_conv2 = tf.nn.relu(tf.gradients(self.cnn.conv3, self.cnn.conv2, grad_ys=self.grad_conv3)[0])
        self.grad_conv1 = tf.nn.relu(tf.gradients(self.cnn.conv2, self.cnn.conv1, grad_ys=self.grad_conv2)[0])
        self.grad_image = tf.nn.relu(tf.gradients(self.cnn.conv1, self.inputs, grad_ys=self.grad_conv1)[0])
        

###

def guided_backprop(graph, image, one_hot, sess):
    image = np.expand_dims(image, 0)
    one_hot = np.expand_dims(one_hot, 0)    
    saliency_map = sess.run(graph.grad_image, feed_dict={graph.inputs:image, graph.labels_1hot:one_hot})[0]
    scaling_adjustment = 1E-20
    saliency_map_scaled = saliency_map/(np.max(saliency_map)+scaling_adjustment)
    return saliency_map_scaled

    
    
    
    
    
    
    
    
    




[((243, 268), 'matplotlib.pyplot.switch_backend', 'plt.switch_backend', (['"""agg"""'], {}), "('agg')\n", (261, 268), True, 'import matplotlib.pyplot as plt\n'), ((1967, 1991), 'numpy.expand_dims', 'np.expand_dims', (['image', '(0)'], {}), '(image, 0)\n', (1981, 1991), True, 'import numpy as np\n'), ((2006, 2032), 'numpy.expand_dims', 'np.expand_dims', (['one_hot', '(0)'], {}), '(one_hot, 0)\n', (2020, 2032), True, 'import numpy as np\n'), ((402, 469), 'tensorflow.placeholder', 'tf.placeholder', (['tf.float32'], {'shape': '[None, 227, 227, 3]', 'name': '"""input"""'}), "(tf.float32, shape=[None, 227, 227, 3], name='input')\n", (416, 469), True, 'import tensorflow as tf\n'), ((499, 557), 'tensorflow.placeholder', 'tf.placeholder', (['tf.float32'], {'shape': '[None, self.num_classes]'}), '(tf.float32, shape=[None, self.num_classes])\n', (513, 557), True, 'import tensorflow as tf\n'), ((819, 853), 'tensorflow.nn.softmax', 'tf.nn.softmax', (['(self.cnn.fc2 / temp)'], {}), '(self.cnn.fc2 / temp)\n', (832, 853), True, 'import tensorflow as tf\n'), ((879, 946), 'tensorflow.tensordot', 'tf.tensordot', (['self.probabilities', 'self.labels_1hot'], {'axes': '[[1], [1]]'}), '(self.probabilities, self.labels_1hot, axes=[[1], [1]])\n', (891, 946), True, 'import tensorflow as tf\n'), ((977, 1001), 'tensorflow.log', 'tf.log', (['self.probability'], {}), '(self.probability)\n', (983, 1001), True, 'import tensorflow as tf\n'), ((2216, 2236), 'numpy.max', 'np.max', (['saliency_map'], {}), '(saliency_map)\n', (2222, 2236), True, 'import numpy as np\n'), ((1079, 1123), 'tensorflow.gradients', 'tf.gradients', (['self.probability', 'self.cnn.fc2'], {}), '(self.probability, self.cnn.fc2)\n', (1091, 1123), True, 'import tensorflow as tf\n'), ((1163, 1226), 'tensorflow.gradients', 'tf.gradients', (['self.cnn.fc2', 'self.cnn.fc1'], {'grad_ys': 'self.grad_fc2'}), '(self.cnn.fc2, self.cnn.fc1, grad_ys=self.grad_fc2)\n', (1175, 1226), True, 'import tensorflow as tf\n'), ((1268, 1333), 'tensorflow.gradients', 'tf.gradients', (['self.cnn.fc1', 'self.cnn.conv5'], {'grad_ys': 'self.grad_fc1'}), '(self.cnn.fc1, self.cnn.conv5, grad_ys=self.grad_fc1)\n', (1280, 1333), True, 'import tensorflow as tf\n'), ((1375, 1444), 'tensorflow.gradients', 'tf.gradients', (['self.cnn.conv5', 'self.cnn.conv4'], {'grad_ys': 'self.grad_conv5'}), '(self.cnn.conv5, self.cnn.conv4, grad_ys=self.grad_conv5)\n', (1387, 1444), True, 'import tensorflow as tf\n'), ((1486, 1555), 'tensorflow.gradients', 'tf.gradients', (['self.cnn.conv4', 'self.cnn.conv3'], {'grad_ys': 'self.grad_conv4'}), '(self.cnn.conv4, self.cnn.conv3, grad_ys=self.grad_conv4)\n', (1498, 1555), True, 'import tensorflow as tf\n'), ((1597, 1666), 'tensorflow.gradients', 'tf.gradients', (['self.cnn.conv3', 'self.cnn.conv2'], {'grad_ys': 'self.grad_conv3'}), '(self.cnn.conv3, self.cnn.conv2, grad_ys=self.grad_conv3)\n', (1609, 1666), True, 'import tensorflow as tf\n'), ((1708, 1777), 'tensorflow.gradients', 'tf.gradients', (['self.cnn.conv2', 'self.cnn.conv1'], {'grad_ys': 'self.grad_conv2'}), '(self.cnn.conv2, self.cnn.conv1, grad_ys=self.grad_conv2)\n', (1720, 1777), True, 'import tensorflow as tf\n'), ((1819, 1885), 'tensorflow.gradients', 'tf.gradients', (['self.cnn.conv1', 'self.inputs'], {'grad_ys': 'self.grad_conv1'}), '(self.cnn.conv1, self.inputs, grad_ys=self.grad_conv1)\n', (1831, 1885), True, 'import tensorflow as tf\n')]