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
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
26
27
28
29
30
31 -class Null(Constant):
36
37
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
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
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
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
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
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
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
185
186
204
205
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
222
223
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.