Let SquareGrating be asymmetric

Dear,

I am Joël Chavas from the neuroinformatics lab of Andrew Davison. I am using imagen to generate visual stimuli for illusory contours. A key point for these illusory contour stimuli is the generation of asymmetric square wave gratings.

Motivation behind the changes
--------------------------------------
A priori, you can generate an asymmetric square grating by making a Composite (operator multiply) of two shifted symmetric SquareGrating. However, if the desired duty_cycle and the pixel density are small, then we visually observe some misses (lines are cut at some points). These are misses in the sense that they are not present by making a direct discretization of the desired analytic operator. It doesn't look like a programmation bug. It is expected and is due to the multiply operator and to the discrete nature of the operands: indeed, multiplying the two pixellized version of two analytic functions doesn't give the same result as the pixellization of the product of these same two analytic functions.
That's why I propose to modify directly the SquareGrating pattern generator to make it asymmetric at will.

Names of the parameter and description of the change
---------------------------------------------------------------------
I propose to add the parameter duty_cycle: it describes the ratio between the pulse duration (width of the bright bar) and the period. This term is the accepted term to describe the asymmetry in a square wave or in a periodic pulse. It is bounded by [0.0,1.0]. As it has no meaning outside of this range, I have put these bounds as bounds, not softbounds.
To achieve the goal, I have reduced the change to a minimum by keeping the around over a sinusoid. I shift the sinuoid on the y-direction by 0.5*sin(pi*(p.duty_cycle-0.5)).

Test
-----
I test it with the following python code. I have tested it particularly for the limit values of the duty_cycle (0.0,1.0),  and for different orientations. It looks fine

import matplotlib.pyplot as plt
import matplotlib.cm as cm
from numpy import pi

import imagen
from dataviews.sheetviews.boundingregion import BoundingBox

bounds=BoundingBox(radius = 6)
xdensity = 20
ydensity = 20

def plot(image):
  print image
  im = plt.imshow(image,cmap=cm.Greys, interpolation='none', aspect='auto', extent=[-6,6,-6,6])
  plt.colorbar()
  
def asymmetric_square_grating(phase=0, orientation=0, duty_cycle=0.5):
  square = imagen.SquareGrating(frequency=0.2, duty_cycle=duty_cycle, orientation=orientation,phase=phase,bounds=bounds,xdensity=xdensity,ydensity=ydensity)
  return square()

plot(asymmetric_square_grating(orientation=pi/4,duty_cycle=0.1))

plt.show()

Last comment
------------------
I think it is useful.

thanks for releasing imagen,

best,

Joël.