"""
from "Visualizing and Understanding Convolutional Networks"
http://arxiv.org/abs/1311.2901
"""

import theano
import theano.tensor as T

import treeano
import treeano.nodes as tn
import treeano.sandbox.utils


class _Deconvnet(treeano.sandbox.utils.OverwriteGrad):

    """
    based on Lasagne Recipes on Guided Backpropagation
    """

    def grad(self, inputs, out_grads):
        (inp,) = inputs
        (grd,) = out_grads
        if False:
            # explicitly rectify
            return (grd * (grd > 0).astype(inp.dtype),)
        else:
            # use the given fn
            return (self.fn(grd),)


deconvnet_relu = _Deconvnet(treeano.utils.rectify)


@treeano.register_node("deconvnet_relu")
class DeconvnetReLUNode(tn.BaseActivationNode):

    def activation(self, network, in_vw):
        return deconvnet_relu(in_vw.variable)

@@ -205,16 +205,30 @@
 x.utils%0A
+import canopy%0A
 %0A%0Aclass 
@@ -859,8 +859,559 @@
 riable)%0A
+%0A%0Adef replace_relu_with_deconvnet_transform(network, **kwargs):%0A%0A    def inner(node):%0A        if isinstance(node, tn.ReLUNode):%0A            return DeconvnetReLUNode(node.name)%0A        else:%0A            return node%0A%0A    return canopy.transforms.fns.transform_root_node_postwalk(%0A        network, inner, **kwargs)%0A%0A%0Aclass ReplaceReLUWithDeconvnet(canopy.handlers.NetworkHandlerImpl):%0A%0A    def transform_network(self, network):%0A        return replace_relu_with_deconvnet_transform(network)%0A%0Areplace_relu_with_deconvnet_handler = ReplaceReLUWithDeconvnet%0A

add handler/transform for deconv