ó
àÆ÷Xc           @` s´   d  Z  d d l m Z m Z m Z d d l Z d d l Z d d l m Z m Z d d l	 j
 Z d d l m Z d d l m Z d e f d „  ƒ  YZ e d	 d
 „ Z d	 d „ Z d S(   s5   
TODO: implement Images2Neibs.infer_shape() methods

i    (   t   absolute_importt   print_functiont   divisionN(   t   Opt   Apply(   t   grad_not_implemented(   t   grad_undefinedt   Images2Neibsc           B` sk   e  Z d  Z d Z d d „ Z d „  Z d „  Z d d „ Z d „  Z	 d „  Z
 d	 „  Z d
 „  Z d „  Z RS(   s
  
    Reshapes the input as a 2D tensor where each row is an pooling
    example.

    Parameters
    ----------
    mode : {'valid', 'ignore_borders', 'wrap_centered'}
        - 'valid' :
            Requires an input that is a multiple of the pooling factor
            (in each direction).
        - 'ignore_borders' :
            Same as valid, but will ignore the borders if the shape(s)
            of the input is not a multiple of the pooling factor(s).
        - 'wrap_centered' :
            ?? TODO comment

    t   modet   validc         C` s(   | d k r t  d ƒ ‚ n  | |  _ d  S(   NR	   t   wrap_centeredt   ignore_borderssc   Only the mode valid, ignore_borders and wrap_centered have been implemented for the op Images2Neibs(   R	   R
   R   (   t   NotImplementedErrorR   (   t   selfR   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   __init__%   s    c         C` s   |  j  j d |  j S(   Ns   {%s}(   t	   __class__t   __name__R   (   R   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   __str__,   s    c         C` s/   |  j  j | ƒ t |  d ƒ s+ d |  _ n  d  S(   NR   R	   (   t   __dict__t   updatet   hasattrR   (   R   t   d(    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   __setstate__/   s    c         C` s¯   t  j | ƒ } t  j | ƒ } | d k r3 | } n t  j | ƒ } | j d k sW t ‚ | j d k sl t ‚ | j d k s t ‚ t |  | | | g t  j d | j j ƒ g ƒ S(   sÄ  
        Parameters
        ----------
        ten4 : a list of lists of images
            ten4 is of shape (list 1 dim, list 2 dim, row, col).
        neib_shape
            (r,c) where r is the height of the neighborhood in rows and c is
            the width of the neighborhood in columns.
        neib_step
            (dr,dc) where dr is the number of rows to skip between patch and dc
            is the number of columns. When None, this is the same as neib_shape
            (patch are disjoint).

        Returns
        -------
        matrix
            A 2D matrix, written using the following pattern::

                idx = 0
                for i in xrange(list 1 dim)
                    for j in xrange(list 2 dim)
                        for k in <image column coordinates>
                            for l in <image row coordinates>
                                output[idx,:]
                                     = flattened version of ten4[i,j,l:l+r,k:k+c]
                                idx += 1

            .. note:: The op isn't necessarily implemented internally with these
                for loops, they're just the easiest way to describe the output
                pattern.

        i   i   t   dtypeN(	   t   Tt   as_tensor_variablet   Nonet   ndimt   AssertionErrorR   t   matrixt   typeR   (   R   t   ten4t
   neib_shapet	   neib_step(    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt	   make_node4   s    !	c      
   C` s  | \ } } } | \ } |  j  d k r | | k s] | | k s] t | d ƒ r | j | ƒ r t | | | j d |  j  ƒt |  d | ƒ t |  d | ƒ g Sn  |  j  d k rPd „  } t j | d | d ƒ } | j d ƒ }	 t	 j
 d	 | d
 | |	 g d t j | j ƒ d | | g ƒ \ }
 } |
 d } | t |  d | ƒ t |  d | ƒ g St |  d | ƒ t |  d | ƒ t |  d | ƒ g S(   NR	   R   t   equalsR   i   i   c         S` sÜ   | \ } } | \ } } | j  \ }	 }
 } } |  | } |  | | } | d d … d d … | | | | d | … | | | | d | … f } |	 |
 f | | | d f | | | d f } t j | | j | ƒ ƒ S(   sÞ  
                Helper function that adds gradient contribution from a single
                neighborhood position i,j.
                pidx = Index of position within neighborhood.
                pgz  = Gradient of shape (batch_size*num_channels*neibs)
                prior_result  = Shape (batch_size, num_channnels, rows, cols)
                neib_shape = Number of rows, cols in a neighborhood.
                neib_step  = Step sizes from image2neibs.
                Ni   (   t   shapeR   t   inc_subtensort   reshape(   t   pidxt   pgzt   prior_resultR    R!   t   nrowst   ncolst   rstept   cstept
   batch_sizet   num_channelst   rowst   colst   it   jt   result_indicest   newshape(    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   pos2mapt   s    

i    t   fnt	   sequencest   outputs_infot   non_sequencesiÿÿÿÿ(   s   valids   ignore_borders(   s   valid(   i   i    (   R   R   R#   t   neibs2imagesR$   R   R   t   aranget
   dimshufflet   theanot   scant   zerosR   (   R   t   inpt   gradst   xR    R!   t   gzR6   t   indicest   pgzst   resultt   _t
   grad_input(    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   gradc   s2    		
c         C` s   d S(   Ni   (   i   (    (   R   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   c_code_cache_versionš   s    c   "      C` sd  | \ } } } | \ } t  |  ƒ t k r? t j j j ƒ  ‚ n  d „  } d }	 d }
 | j d k si t ‚ | j d k s~ t ‚ | j d d k s— t ‚ | j d k s¬ t ‚ | j d d k sÅ t ‚ | \ } } | \ } } |  j	 } | d k sþ | d k rt
 d t | ƒ ƒ ‚ n  | d k s/| d k rHt
 d t | ƒ ƒ ‚ n  | d	 k r| d d k st| d d k rƒt d
 ƒ ‚ n  | j d | k  s©| j d | k  rÖt d | | | j d | j d f ƒ ‚ n  | | j d | ƒ }	 | | j d | ƒ }
 n4| d k rè| j d | k  s?| j d | | d k rbt d | | | j d f ƒ ‚ n  | j d | k  s| j d | | d k r³t d | | | j d f ƒ ‚ n  d | j d | | }	 d | j d | | }
 nQ | d k r)d | j d | | }	 d | j d | | }
 n t d | ƒ ‚ |	 |
 | j d | j d } | | } t j | | f d | j d j ƒ| d <| j d } | j d } | j d } | j d } | d } | d } x‰t | ƒ D]{} xrt | ƒ D]d} x[t |	 ƒ D]M} xDt |
 ƒ D]6} | |
 | |	 | | | } xt | ƒ D]} | | | } | d	 k rª| | 8} | d k  rŽ| | 7} qª| | k rª| | 8} qªn  xŸ t | ƒ D]‘ } | | | }  | d	 k r|  | 8}  |  d k  rú|  | 7}  q|  | k r|  | 8}  qn  | | | }! | | | | |  f | d | |! f <q·WqKWqWqWqôWqáWd  S(   Nc         S` s"   |  | r |  | d S|  | Sd  S(   Ni   (    (   t   at   b(    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   CEIL_INTDIV¤   s    
iÿÿÿÿi   i   i    i   s(   neib_step wrong step ; values <= 0. Got s   neib_shape values <=0. Got R
   s>   Images2Neibs: in mode wrap_centered need patch with odd shapesi   sƒ   Images2Neibs: in wrap_centered mode, don't support image shapes smaller then the patch shapes: neib_shape=(%d,%d), ten4[2:]=[%d,%d]R	   sE   neib_shape[0]=%d, neib_step[0]=%d and ten4.shape[2]=%d not consistentsE   neib_shape[1]=%d, neib_step[1]=%d and ten4.shape[3]=%d not consistentR   s   Images2Neibs: unknow mode '%s'R   (   R   R   R>   t   goft   utilst   MethodNotDefinedR   R   R$   R   t
   ValueErrort   strt	   TypeErrort   numpyt   emptyt   outputsR   t   range("   R   t   nodeRA   t   out_R   R    R!   t   zRN   t   grid_ct   grid_dt   cR   t   step_xt   step_yR   t   z_dim0t   z_dim1t   nb_batcht   nb_stackt   heightt   widtht   wrap_centered_idx_shift_xt   wrap_centered_idx_shift_yt   nt   sRL   RM   t   z_rowR2   t   ten4_2R3   t   ten4_3t   z_col(    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   perform   sœ    			 &'.. 
)



c         C` s  | d } | j  d \ } } | j  d \ } } |  j d k rn t j | d | ƒ } t j | d | ƒ }	 n| |  j d k r¬ d | d | | } d | d | | }	 n> |  j d k rê d | d | | } d | d | | }	 n  | |	 | d | d }
 | | } |
 | f g S(   Ni    i   i   R
   i   R	   R   (   t   inputsR   R   t   ceil_intdiv(   R   RY   t   input_shapet   in_shapeR^   R   R_   R`   R\   R]   Ra   Rb   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   infer_shape  s    

c         C` s6   | \ } } } | \ }	 | d }
 |  j  } d t ƒ  S(   Nt   failsA!  
#ifndef CEIL_INTDIV
#define CEIL_INTDIV(a, b) ((a/b) + ((a %% b) ? 1: 0))
#endif

        int grid_c = -1; //number of patch in height
        int grid_d = -1; //number of patch in width
        {
        if (PyArray_NDIM(%(ten4)s) != 4)
        {
            PyErr_Format(PyExc_TypeError, "ten4 wrong rank");
            %(fail)s;
        }
        if (PyArray_NDIM(%(neib_shape)s) != 1)
        {
            PyErr_Format(PyExc_TypeError, "neib_shape wrong rank");
            %(fail)s;
        }
        if ( (PyArray_DIMS(%(neib_shape)s))[0] != 2)
        {
            PyErr_Format(PyExc_TypeError, "neib_shape wrong shape ; has to"
                                          " contain 2 elements");
            %(fail)s;
        }
        if (PyArray_NDIM(%(neib_step)s) != 1)
        {
            PyErr_Format(PyExc_TypeError, "neib_step wrong rank");
            %(fail)s;
        }
        if ( (PyArray_DIMS(%(neib_step)s))[0] != 2)
        {
            PyErr_Format(PyExc_TypeError,
                         "neib_step wrong step ; has to contain 2 elements");
            %(fail)s;
        }

        // (c,d) = neib_shape
        const npy_intp c = (npy_intp) *(dtype_%(neib_shape)s*) PyArray_GETPTR1(%(neib_shape)s, 0);
        const npy_intp d = (npy_intp) *(dtype_%(neib_shape)s*) PyArray_GETPTR1(%(neib_shape)s, 1);
        // (step_x,step_y) = neib_step
        const dtype_%(neib_step)s step_x = *(dtype_%(neib_step)s*) PyArray_GETPTR1(%(neib_step)s, 0);
        const dtype_%(neib_step)s step_y = *(dtype_%(neib_step)s*) PyArray_GETPTR1(%(neib_step)s, 1);

        if (step_x <=0 || step_y <=0)
        {
            PyErr_Format(PyExc_ValueError,
                         "neib_step wrong step ; values <= 0. Got %%lld %%lld.",
                         (long long) step_x, (long long) step_y);
            %(fail)s;
        }

        if (c <=0 || d <=0)
        {
            PyErr_Format(PyExc_ValueError,
                         "neib_shape values <= 0. Got %%lld %%lld.",
                         (long long)c, (long long)d);
            %(fail)s;
        }

        if ( "%(mode)s" == "wrap_centered") {
            if (c%%2!=1 || d%%2!=1){
                PyErr_Format(PyExc_TypeError,
                             "Images2Neibs: in mode wrap_centered"
                             " need patch with odd shapes");
                %(fail)s;
            }
            if ( (PyArray_DIMS(%(ten4)s))[2] < c ||
                 (PyArray_DIMS(%(ten4)s))[3] < d)
            {
                PyErr_Format(PyExc_TypeError,
                    "Images2Neibs: in wrap_centered mode, don't support image"
                    " shapes smaller then the patch shapes:"
                    " neib_shape=(%%ld,%%ld), ten4[2:]=[%%ld,%%ld]",
                    (long int)c, (long int)d,
                    (long int)(PyArray_DIMS(%(ten4)s)[2]),
                    (long int)(PyArray_DIMS(%(ten4)s)[3]));
                %(fail)s;
            }
            grid_c = CEIL_INTDIV(((PyArray_DIMS(%(ten4)s))[2]),step_x);
            grid_d = CEIL_INTDIV(((PyArray_DIMS(%(ten4)s))[3]),step_y);

        }else if ( "%(mode)s" == "valid") {
            if ( ((PyArray_DIMS(%(ten4)s))[2] < c) ||
                 ( (((PyArray_DIMS(%(ten4)s))[2]-c) %% step_x)!=0))
            {
                PyErr_Format(PyExc_TypeError,
                             "neib_shape[0]=%%ld, neib_step[0]=%%ld and"
                             " ten4.shape[2]=%%ld not consistent",
                             (long int)c, (long int)step_x,
                             (long int)(PyArray_DIMS(%(ten4)s)[2]));
                %(fail)s;
            }
            if ( ((PyArray_DIMS(%(ten4)s))[3] < d) ||
                 ( (((PyArray_DIMS(%(ten4)s))[3]-d) %% step_y)!=0))
            {
                PyErr_Format(PyExc_TypeError,
                             "neib_shape[1]=%%ld, neib_step[1]=%%ld and"
                             " ten4.shape[3]=%%ld not consistent",
                             (long int)d, (long int)step_y,
                             (long int)(PyArray_DIMS(%(ten4)s)[3]));
                %(fail)s;
            }
            //number of patch in height
            grid_c = 1+(((PyArray_DIMS(%(ten4)s))[2]-c)/step_x);
            //number of patch in width
            grid_d = 1+(((PyArray_DIMS(%(ten4)s))[3]-d)/step_y);
        }else if ( "%(mode)s" == "ignore_borders") {
            //number of patch in height
            grid_c = 1+(((PyArray_DIMS(%(ten4)s))[2]-c)/step_x);
            //number of patch in width
            grid_d = 1+(((PyArray_DIMS(%(ten4)s))[3]-d)/step_y);
        }else{
            PyErr_Format(PyExc_TypeError,
                         "Images2Neibs: unknow mode '%(mode)s'");
            %(fail)s;
        }

        // new dimensions for z
        const npy_intp z_dim1 = c * d;
        const npy_intp z_dim0 =  grid_c
                            * grid_d
                            * (PyArray_DIMS(%(ten4)s))[1]
                            * (PyArray_DIMS(%(ten4)s))[0];

        if ((NULL == %(z)s)
            || ((PyArray_DIMS(%(z)s))[0] != z_dim0 )
            || ((PyArray_DIMS(%(z)s))[1] != z_dim1 )
        )
        {
            Py_XDECREF(%(z)s);
            npy_intp dims[2];
            dims[0] = z_dim0;
            dims[1] = z_dim1;

            %(z)s = (PyArrayObject*) PyArray_EMPTY(2,
                dims,
                PyArray_TYPE((PyArrayObject*) py_%(ten4)s),
                0);

            if (!%(z)s)
            {
                PyErr_SetString(PyExc_MemoryError, "failed to alloc z output");
                %(fail)s;
            }
        }
        }

        { // NESTED SCOPE

        const int nb_batch = (PyArray_DIMS(%(ten4)s))[0];
        const int nb_stack = (PyArray_DIMS(%(ten4)s))[1];
        const int height = (PyArray_DIMS(%(ten4)s))[2];
        const int width = (PyArray_DIMS(%(ten4)s))[3];

        // (c,d) = neib_shape
        const npy_intp c = (npy_intp) *(dtype_%(neib_shape)s*) PyArray_GETPTR1(%(neib_shape)s, 0);
        const npy_intp d = (npy_intp) *(dtype_%(neib_shape)s*) PyArray_GETPTR1(%(neib_shape)s, 1);
        // (step_x,step_y) = neib_step
        const npy_intp step_x = (npy_intp) *(dtype_%(neib_step)s*) PyArray_GETPTR1(%(neib_step)s, 0);
        const npy_intp step_y = (npy_intp) *(dtype_%(neib_step)s*) PyArray_GETPTR1(%(neib_step)s, 1);

        const int wrap_centered_idx_shift_x = c/2;
        const int wrap_centered_idx_shift_y = d/2;
        // Oh this is messed up...
        for (int n = 0; n < nb_batch; n++)              // loop over batches
            for (int s = 0; s < nb_stack; s++)          // loop over stacks
                for (int a = 0; a < grid_c; a++)        // loop over the number of patch in height
                    for (int b = 0; b < grid_d; b++)    // loop over the number of patch in width
                    {
                        int z_row = b + grid_d*(a + grid_c*(s + nb_stack*n));
                        for (int i = 0; i < c; i++)     // loop over c
                        {
                            int ten4_2 = i + a * step_x;
                            if ( "%(mode)s" == "wrap_centered" ){
                                ten4_2 -= wrap_centered_idx_shift_x;
                                if ( ten4_2 < 0 ) ten4_2 += height;
                                else if (ten4_2 >= height) ten4_2 -= height;
                            }
                            for (int j = 0; j < d; j++)  // loop over d
                            {

                                int ten4_3 = j + b * step_y;
                                if ( "%(mode)s" == "wrap_centered" ){
                                    ten4_3 -= wrap_centered_idx_shift_y;
                                    if ( ten4_3 < 0 ) ten4_3 += width;
                                    else if (ten4_3 >= width) ten4_3 -= width;
                                }
                                int z_col = j + d * i;

                                dtype_%(z)s* curr_z = (dtype_%(z)s*) PyArray_GETPTR2(%(z)s, z_row, z_col);
                                *curr_z = *( (dtype_%(ten4)s*) PyArray_GETPTR4(%(ten4)s, n, s, ten4_2, ten4_3));

                                //printf("\n(%%i,%%i,%%i,%%i) --> (%%i,%%i)",
                                //       n, s, ten4_2, ten4_3, z_row, z_col);
                                //printf("%%f ", *curr_z);
                            }
                        }
                    }
        } // END NESTED SCOPE
        (   R   t   locals(   R   RY   t   nameRA   t   outt   subR   R    R!   R[   Ru   R   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   c_code  s
    	
	È(   s   modeN(   R   t
   __module__t   __doc__t	   __props__R   R   R   R   R"   RJ   RK   Ro   Rt   Rz   (    (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyR      s   		/	7		j	R	   c         C` s   t  | ƒ |  | | ƒ S(   s  
    Function :func:`images2neibs <theano.tensor.nnet.neighbours.images2neibs>`
    allows to apply a sliding window operation to a tensor containing
    images or other two-dimensional objects.
    The sliding window operation loops over points in input data and stores
    a rectangular neighbourhood of each point.
    It is possible to assign a step of selecting patches (parameter `neib_step`).

    Parameters
    ----------
    ten4 : A 4d tensor-like
        A 4-dimensional tensor which represents a list of lists of images.
        It should have shape (list 1 dim, list 2 dim, row, col). The first
        two dimensions can be useful to store different channels and batches.
    neib_shape : A 1d tensor-like of 2 values
        A tuple containing two values: height and width of the neighbourhood.
        It should have shape (r,c) where r is the height of the neighborhood
        in rows and c is the width of the neighborhood in columns.
    neib_step : A 1d tensor-like of 2 values
        (dr,dc) where dr is the number of rows to skip between patch and dc is
        the number of columns. The parameter should be a tuple of two elements:
        number of rows and number of columns to skip each iteration.
        Basically, when the step is 1, the neighbourhood of every first element
        is taken and every possible rectangular subset is returned.
        By default it is equal to `neib_shape` in other words, the patches are
        disjoint. When the step is greater than `neib_shape`, some elements are
        omitted. When None, this is the same as neib_shape (patch are disjoint).
    mode : {'valid', 'ignore_borders', 'wrap_centered'}
        ``valid``
            Requires an input that is a multiple of the
            pooling factor (in each direction).
        ``ignore_borders``
            Same as valid, but will ignore the borders if the shape(s) of
            the input is not a multiple of the pooling factor(s).
        ``wrap_centered``
            ?? TODO comment

    Returns
    -------
    object
        Reshapes the input as a 2D tensor where each row is an
        pooling example. Pseudo-code of the output:

          .. code-block:: python

             idx = 0
             for i in xrange(list 1 dim):
                 for j in xrange(list 2 dim):
                     for k in <image column coordinates>:
                         for l in <image row coordinates>:
                             output[idx,:]
                                  = flattened version of ten4[i,j,l:l+r,k:k+c]
                             idx += 1

          .. note:: The operation isn't necessarily implemented internally with
             these for loops, they're just the easiest way to describe the
             output pattern.

    Notes
    -----
    .. note::
        Currently the step size should be chosen in the way that the
        corresponding dimension :math:`i` (width or height) is equal
        to :math:`n * step\_size_i + neib\_shape_i` for some :math:`n`.

    Examples
    --------

    .. code-block:: python

        # Defining variables
        images = T.tensor4('images')
        neibs = images2neibs(images, neib_shape=(5, 5))

        # Constructing theano function
        window_function = theano.function([images], neibs)

        # Input tensor (one image 10x10)
        im_val = np.arange(100.).reshape((1, 1, 10, 10))

        # Function application
        neibs_val = window_function(im_val)

    .. note:: The underlying code will construct a 2D tensor of disjoint
       patches 5x5. The output has shape 4x25.

    (   R   (   R   R    R!   R   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   images2neibsè  s    Xc   
      C` s  t  j |  ƒ }  t  j | ƒ } t  j | ƒ } t  j | d | d | d g ƒ } t |  j d d d d ƒ | d | ƒ} | d k rW| } t  j | d | d | d | d ƒ } t  j | d | d | d | d ƒ } | j | d	 d
 ƒ} x” d d g D]O } t | j ƒ }	 | | | | |	 | <t  j	 | t  j
 |	 ƒ g d | ƒ} qWn4 | d k r{| j | d	 d
 ƒ} n t d | ƒ ‚ | S(   s  
    Function :func:`neibs2images <theano.sandbox.neighbours.neibs2images>`
    performs the inverse operation of
    :func:`images2neibs <theano.sandbox.neigbours.neibs2images>`. It inputs
    the output of :func:`images2neibs <theano.sandbox.neigbours.neibs2images>`
    and reconstructs its input.

    Parameters
    ----------
    neibs : 2d tensor
        Like the one obtained by
        :func:`images2neibs <theano.sandbox.neigbours.neibs2images>`.
    neib_shape
        `neib_shape` that was used in
        :func:`images2neibs <theano.sandbox.neigbours.neibs2images>`.
    original_shape
        Original shape of the 4d tensor given to
        :func:`images2neibs <theano.sandbox.neigbours.neibs2images>`

    Returns
    -------
    object
        Reconstructs the input of
        :func:`images2neibs <theano.sandbox.neigbours.neibs2images>`,
        a 4d tensor of shape `original_shape`.

    Notes
    -----
    Currently, the function doesn't support tensors created with
    `neib_step` different from default value. This means that it may be
    impossible to compute the gradient of a variable gained by
    :func:`images2neibs <theano.sandbox.neigbours.neibs2images>` w.r.t.
    its inputs in this case, because it uses
    :func:`images2neibs <theano.sandbox.neigbours.neibs2images>` for
    gradient computation.

    Examples
    --------
    Example, which uses a tensor gained in example for
    :func:`images2neibs <theano.sandbox.neigbours.neibs2images>`:

    .. code-block:: python

        im_new = neibs2images(neibs, (5, 5), im_val.shape)
        # Theano function definition
        inv_window = theano.function([neibs], im_new)
        # Function application
        im_new_val = inv_window(neibs_val)

    .. note:: The code will output the initial image array.

    iÿÿÿÿi   RC   i    R   R   i   i   R   i   t   axisR	   s#   neibs2images do not support mode=%s(   R   R   t   stackR~   R=   t   set_subtensorR&   t   listR$   t   concatenateR@   R   (
   t   neibsR    t   original_shapeR   t   new_neib_shapet	   output_2dt   valid_shapet	   output_4dR   t	   pad_shape(    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyR;   C  s0    5+(   R|   t
   __future__R    R   R   RU   R>   R   R   t   theano.tensort   tensorR   t   theano.gradientR   R   R   R   R~   R;   (    (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/neighbours.pyt   <module>   s   ÿ Ù[