from pylab import *
import theano
from theano.tensor.nnet import conv
from scipy.signal import *
from time import*

'''' This is a comparison of the different techniques available for convolution '''

def compare(imagesize, kernelsize, iterations=3, span=(0,100), byscipy=True, byscipyfft=True, bytheano=True):

    timescipy, timefft, timetheano = [], [], []

    if bytheano:
	 x = theano.tensor.tensor4()
         y = theano.tensor.tensor4()
         result = conv.conv2d(x, y, border_mode='valid')
         theano_conv2d = theano.function([x, y], result)


    for i in xrange(iterations):
	print 'Generating image and kernel ...'
	image = randint(span[0], span[1], imagesize)
	kernel = randint(span[0], span[1], kernelsize)

        #Convolution 2D with scipy
        if byscipy:
	    print 'Convolution with scipy ...'
            t = time()
	    convscipy = convolve2d(image, kernel, mode='valid')
	    timescipy.append( time() - t )
#	    print 'Time with scipy convolution:', timescipy
	#FFT based Convolution with scipy
	if byscipyfft:
	    print 'convolution with fft scipy ...'
	    t = time()
	    convfft = fftconvolve(image, kernel, mode='valid')
	    timefft.append( time() - t )
#	    print 'Time with scipy fft convolution;', timefft
	#Convolution 2D with theano
	if bytheano:
	    print 'Convolution with theano ...'
            t = time()
            convtheano = theano_conv2d([[image]], [[kernel]])[0][0]
            timetheano.append( time() - t )
#	    print 'Time with theano:', timetheano

    print 'Time with scipy convolution:', array(timescipy).mean(), 'std:', array(timescipy).std()
    print 'Time with scipy fft convolution:', array(timefft).mean(), 'std:', array(timefft).std()
    print 'Time with theano:', array(timetheano).mean(), 'std:', array(timetheano).std()

if __name__ == '__main__':
    print asctime()
    compare((10000,1000),(10,10))
