Package topo :: Package patterns :: Module basic
[hide private]
[frames] | no frames]

Source Code for Module topo.patterns.basic

  1  """ 
  2  Simple two-dimensional mathematical or geometrical pattern generators. 
  3   
  4  $Id: basic.py 8029 2008-02-19 15:16:24Z ceball $ 
  5  """ 
  6  __version__='$Revision: 8029 $' 
  7   
  8  import numpy 
  9  import topo 
 10  from math import pi, sin, cos, sqrt 
 11  from numpy.oldnumeric import around,bitwise_and,sin,add,Float,bitwise_or 
 12  from numpy import alltrue 
 13   
 14  from topo.base.parameterclasses import Integer, Number, Parameter, Enumeration, ClassSelectorParameter 
 15  from topo.base.parameterclasses import ListParameter 
 16  from topo.base.patterngenerator import PatternGenerator 
 17   
 18  # Imported here so that all PatternGenerators will be in the same package 
 19  from topo.base.patterngenerator import Constant 
 20   
 21  from topo.misc.patternfns import gaussian,gabor,line,disk,ring 
 22  from topo.base.arrayutils import wrap 
 23  from topo.misc.numbergenerators import UniformRandom 
 24   
 25  # Could add a Gradient class, where the brightness varies as a 
 26  # function of an equation for a plane.  This could be useful as a 
 27  # background, or to see how sharp a gradient is needed to get a 
 28  # response. 
 29   
 30   
31 -class Null(Constant):
32 """ 33 A constant pattern of zero activity. 34 """ 35 scale = Number(default=0,constant=True,precedence=-1)
36 37
38 -class Gaussian(PatternGenerator):
39 """ 40 2D Gaussian pattern generator. 41 42 The sigmas of the Gaussian are calculated from the size and 43 aspect_ratio parameters: 44 45 ysigma=size/2 46 xsigma=ysigma*aspect_ratio 47 48 The Gaussian is then computed for the given (x,y) values as: 49 50 exp(-x^2/(2*xsigma^2) - y^2/(2*ysigma^2) 51 """ 52 53 aspect_ratio = Number(default=0.3,bounds=(0.0,None),softbounds=(0.0,2.0), 54 precedence=0.31,doc= 55 """ 56 Ratio of the width to the height. 57 Specifically, xsigma=ysigma*aspect_ratio (see size). 58 """) 59 60 size = Number(default=0.5,doc=""" 61 Overall size of the Gaussian, defined by: 62 exp(-x^2/(2*xsigma^2) - y^2/(2*ysigma^2) 63 where ysigma=size/2 and xsigma=size/2*aspect_ratio. 64 """) 65
66 - def function(self,params):
67 ysigma = params['size']/2.0 68 xsigma = params['aspect_ratio']*ysigma 69 70 return gaussian(self.pattern_x,self.pattern_y,xsigma,ysigma)
71 72
73 -class SineGrating(PatternGenerator):
74 """2D sine grating pattern generator.""" 75 76 frequency = Number(default=2.4,bounds=(0.0,None),softbounds=(0.0,10.0), 77 precedence=0.50, doc="Frequency of the sine grating.") 78 79 phase = Number(default=0.0,bounds=(0.0,None),softbounds=(0.0,2*pi), 80 precedence=0.51,doc="Phase of the sine grating.") 81
82 - def function(self,params):
83 """Return a sine grating pattern (two-dimensional sine wave).""" 84 return 0.5 + 0.5*sin(params['frequency']*2*pi*self.pattern_y + params['phase'])
85 86 87
88 -class Gabor(PatternGenerator):
89 """2D Gabor pattern generator.""" 90 91 frequency = Number(default=2.4,bounds=(0.0,None),softbounds=(0.0,10.0), 92 precedence=0.50,doc="Frequency of the sine grating component.") 93 94 phase = Number(default=0.0,bounds=(0.0,None),softbounds=(0.0,2*pi), 95 precedence=0.51,doc="Phase of the sine grating component.") 96 97 aspect_ratio = Number(default=1.0,bounds=(0.0,None),softbounds=(0.0,2.0), 98 precedence=0.31,doc= 99 """ 100 Ratio of pattern width to height. 101 The width of the Gaussian component is size*aspect_ratio (see Gaussian). 102 """) 103 104 size = Number(default=0.25,doc=""" 105 Determines the height of the Gaussian component (see Gaussian).""") 106
107 - def function(self,params):
108 height = params['size']/2.0 109 width = params['aspect_ratio']*height 110 111 return gabor( self.pattern_x,self.pattern_y,width,height, 112 params['frequency'],params['phase'])
113 114
115 -class Line(PatternGenerator):
116 """2D line pattern generator.""" 117 118 thickness = Number(default=0.006,bounds=(0.0,None),softbounds=(0.0,1.0), 119 precedence=0.60, 120 doc="Thickness (width) of the solid central part of the line.") 121 smoothing = Number(default=0.05,bounds=(0.0,None),softbounds=(0.0,0.5), 122 precedence=0.61, 123 doc="Width of the Gaussian fall-off.") 124
125 - def function(self,params):
126 return line(self.pattern_y,params['thickness'],params['smoothing'])
127 128
129 -class Disk(PatternGenerator):
130 """ 131 2D disk pattern generator. 132 133 An elliptical disk can be obtained by adjusting the aspect_ratio of a circular 134 disk; this transforms a circle into an ellipse by stretching the circle in the 135 y (vertical) direction. 136 137 The Gaussian fall-off at a point P is an approximation for non-circular disks, 138 since the point on the ellipse closest to P is taken to be the same point as 139 the point on the circle before stretching that was closest to P. 140 """ 141 142 aspect_ratio = Number(default=1.0,bounds=(0.0,None),softbounds=(0.0,2.0), 143 precedence=0.31,doc= 144 "Ratio of width to height; size*aspect_ratio gives the width of the disk.") 145 146 size = Number(default=0.5,doc="Top to bottom height of the disk") 147 148 smoothing = Number(default=0.1,bounds=(0.0,None),softbounds=(0.0,0.5), 149 precedence=0.61,doc="Width of the Gaussian fall-off") 150
151 - def function(self,params):
152 height = params['size'] 153 aspect_ratio = params['aspect_ratio'] 154 155 # CEBHACKALERT: this division should handle aspect_ratio=0 156 return disk(self.pattern_x/aspect_ratio,self.pattern_y,height, 157 params['smoothing'])
158 159
160 -class Ring(PatternGenerator):
161 """ 162 2D ring pattern generator. 163 164 See the Disk class for a note about the Gaussian fall-off. 165 """ 166 167 thickness = Number(default=0.015,bounds=(0.0,None),softbounds=(0.0,0.5), 168 precedence=0.60,doc="Thickness (line width) of the ring.") 169 170 smoothing = Number(default=0.1,bounds=(0.0,None),softbounds=(0.0,0.5), 171 precedence=0.61,doc="Width of the Gaussian fall-off inside and outside the ring.") 172 173 aspect_ratio = Number(default=1.0,bounds=(0.0,None),softbounds=(0.0,2.0), 174 precedence=0.31,doc= 175 "Ratio of width to height; size*aspect_ratio gives the overall width.") 176 177 size = Number(default=0.5) 178
179 - def function(self,params):
180 height = params['size'] 181 aspect_ratio = params['aspect_ratio'] 182 183 return ring(self.pattern_x/aspect_ratio,self.pattern_y,height, 184 params['thickness'],params['smoothing'])
185 186
187 -class Rectangle(PatternGenerator):
188 """2D rectangle pattern generator.""" 189 190 aspect_ratio = Number(default=1.0,bounds=(0.0,None),softbounds=(0.0,2.0), 191 precedence=0.31,doc= 192 "Ratio of width to height; size*aspect_ratio gives the width of the rectangle.") 193 194 size = Number(default=0.5,doc="Height of the rectangle.") 195 196 # We will probably want to add Fuzzy-style anti-aliasing to this. 197
198 - def function(self,params):
199 height = params['size'] 200 width = params['aspect_ratio']*height 201 202 return bitwise_and(abs(self.pattern_x)<=width/2.0, 203 abs(self.pattern_y)<=height/2.0)
204 205
206 -class TwoRectangles(Rectangle):
207 """Two 2D rectangle pattern generator.""" 208 209 x1 = Number(default=-0.15,bounds=(-1.0,1.0),softbounds=(-0.5,0.5), 210 doc="X center of rectangle 1.") 211 212 y1 = Number(default=-0.15,bounds=(-1.0,1.0),softbounds=(-0.5,0.5), 213 doc="Y center of rectangle 1.") 214 215 x2 = Number(default=0.15,bounds=(-1.0,1.0),softbounds=(-0.5,0.5), 216 doc="X center of rectangle 2.") 217 218 y2 = Number(default=0.15,bounds=(-1.0,1.0),softbounds=(-0.5,0.5), 219 doc="Y center of rectangle 2.") 220 221 # YC: Maybe this can be implemented much more cleanly by calling 222 # the parent's function() twice, but it's hard to see how to 223 # set the (x,y) offset for the parent.
224 - def function(self,params):
225 height = params['size'] 226 width = params['aspect_ratio']*height 227 228 return bitwise_or( 229 bitwise_and(bitwise_and( 230 (self.pattern_x-self.x1)<=self.x1+width/4.0, 231 (self.pattern_x-self.x1)>=self.x1-width/4.0), 232 bitwise_and( 233 (self.pattern_y-self.y1)<=self.y1+width/4.0, 234 (self.pattern_y-self.y1)>=self.y1-width/4.0)), 235 bitwise_and(bitwise_and( 236 (self.pattern_x-self.x2)<=self.x2+width/4.0, 237 (self.pattern_x-self.x2)>=self.