1
## Automatically adapted for scipy Oct 31, 2005 by
3
# Copyright (c) 1996, 1997, The Regents of the University of California.
4
# All rights reserved. See Legal.htm for full text and disclaimer.
6
# The following is so I know about arrays:
8
from numpy.core.umath import *
9
from shapetest import *
10
from graftypes import *
11
from gistfuncs import *
16
"""This class is for Gist and possibly other graphics packages;
17
it creates a class consisting of a QuadMesh, which can then
18
be given to and plotted by a graph2d object.
20
q = QuadMesh ( <keyword arguments> ) will create a QuadMesh
21
object. The keyword arguments are:
22
y and x, matching two-dimensional sequences of floating point
23
values. These arguments are required and give the coordinates of
24
the nodes of the mesh.
26
x, y, and z can also be given as one-dimensional and
27
of equal lengths. (In this case, all three arguments are
28
required.) Then this will be assumed to be a random
29
distribution of points (x, y) and values z on those points.
30
In this case, a regular QuadMesh will be created, with nx
31
equally spaced x's and ny equally spaced y's, with an nx
32
by ny array of z's interpolated from the originals by
33
Hardy's multiquadric fit. nx and ny can be specified by
34
keyword values, lacking which they will be determined from
35
ireg (if it is present), otherwise they will be defaulted
36
to 50. xmax, xmin, ymax, and ymin for the new mesh may
37
be specified by the corresponding keywords, or otherwise will
38
by default be created by the maxima and minima of the variables
40
ireg, optional two-dimensional sequence of integer values with
41
the same dimensions as x and y, giving positive region numbers
42
for the cells of the mesh, zero where the mesh does not exist.
43
the first row and column of ireg are always zero, since there
44
are one fewer cells in each direction than there are nodes.
45
boundary = 0/1 0: plot entire mesh; 1: plot only the boundary of
46
the selected region. if ktype and ltype are not "none",
47
then the boundary will be plotted, then the k and l lines
49
boundary_type, boundary_color: these matter only if boundary = 1,
50
and tell how the boundary will be plotted and what its color
52
region = n if n = 0, plot entire mesh; if any other number, plot
53
the region specified (according to the settings in ireg).
54
regions: "all" or a number or a list of numbers. Gives which
55
regions to plot. If absent, defaults to [region], or "all"
56
if region is 0. If present, and region is present also, then
58
inhibit = 0/1/2 1: do not plot the (x [, j], y [, j]) lines;
59
2: do not plot the (x [i, ], y[i, ]) lines.
60
tri, optional two-dimensional sequence of values with
61
the same dimensions as ireg, triangulation array used for
63
z = optional two-dimensional sequence of floating point
64
values. (Unless x and y are one-dimensional, in which case it
65
must be present and match them in size. See above under x and y.)
66
z has the same shape as x and y. If z is present, the
67
contours of z will be plotted (default: 8 contours unless
68
levels specifies otherwise), or a filled mesh will be
69
plotted if filled = 1. In the latter case, z may be one
70
smaller than x and y in each direction, and represents
71
a zone-centered quantity.
72
levels = optional one-dimensional sequence of floating point
73
values. If present, a list of the values of z at which you
75
filled = 0/1 If 1, plot a filled mesh using the values of z.
76
If z is not present, the mesh zones will be filled with the
77
background color, which allows plotting of a wire frame.
78
contours = 0/1 only pertinent when filled = 1; if contours ia
79
also 1, then will draw contours as specified by type, width,
81
edges, if nonzero when filled=1, draw a solid edge around
83
ecolor, ewidth--the color and width of the mesh lines when
84
filled = 1 and adges is nonzero.
85
vx, vy optional two-dimensional sequences of floating point
86
values. Has the same shape as x and y. If present, represents
87
a vector field to be plotted on the mesh.
88
scale = floating point value. When plotting a vector field,
89
a conversion factor from the units of (vx, vy) to the
91
z_scale = specifies "log", "lin", or "normal" for how z is to be plotted.
92
ktype, ltype: can have the same values as type, and allow the
93
k and l mesh lines to be plotted differently.
94
#### eventually, we can add kcolor, lcolor, kwidth, lwidth ####
95
type, color, width, label, hide, marks, marker as for
102
_QuadMeshSpecError = "QuadMeshSpecError"
104
def __init__ ( self , * kwds , ** keywords ) :
107
if not keywords.has_key ("x") or not keywords.has_key ("y") :
108
raise self._QuadMeshSpecError , \
109
"A QuadMesh requires both x and y keywords."
110
self.x = keywords ["x"]
111
self.y = keywords ["y"]
112
if len (self.x.shape) == 2 :
114
if self.x.shape != self.y.shape :
115
raise self._QuadMeshSpecError , \
116
"x and y must have the same shape."
117
self.nx = self.x.shape [0]
118
self.ny = self.x.shape [1]
119
elif len (self.x.shape) == len (self.y.shape) == 1:
121
if len (x) != len (y) :
122
raise self._QuadMeshSpecError , \
123
"If x and y are one dimensional, their lengths must agree."
124
if keywords.has_key ("nx") :
128
if keywords.has_key ("ny") :
132
if keywords.has_key ("xmax") :
133
xmax = keywords ["xmax"]
136
if keywords.has_key ("ymax") :
137
ymax = keywords ["ymax"]
140
if keywords.has_key ("xmin") :
141
xmin = keywords ["xmin"]
144
if keywords.has_key ("ymin") :
145
ymin = keywords ["ymin"]
148
if keywords.has_key ("rsq") :
149
rsq = keywords ["rsq"]
151
rsq = 4. * (xmax - xmin) * (ymax - ymin) / len (x)
153
raise self._QuadMeshSpecError , \
154
"can't handle x (shape " + `self.x.shape` + ") and y " + \
155
"(shape " + `self.y.shape` + "."
156
if keywords.has_key ("boundary") :
157
self.boundary = keywords ["boundary"]
160
if keywords.has_key ("boundary_type") :
161
self.boundary_type = keywords ["boundary_type"]
163
self.boundary_type = "solid"
164
if keywords.has_key ("boundary_color") :
165
self.boundary_color = keywords ["boundary_color"]
167
self.boundary_color = "fg"
168
if keywords.has_key ("inhibit") :
169
self.inhibit = keywords ["inhibit"]
172
if keywords.has_key ("label") :
173
self.label = keywords ["label"]
176
if keywords.has_key ("hide") :
177
self.hide = keywords ["hide"]
180
if self.boundary == 1 :
181
self.ktype = self.ltype = "none"
183
self.ktype = self.ltype = "solid"
184
if keywords.has_key ("type") :
185
self.line_type = keywords ["type"]
187
self.line_type = "solid"
188
if keywords.has_key ("ktype") :
189
self.ktype = keywords ["ktype"]
190
if keywords.has_key ("ltype") :
191
self.ltype = keywords ["ltype"]
192
if keywords.has_key ("width") :
193
self.width = keywords ["width"]
196
if keywords.has_key ("color") :
197
self.color = keywords ["color"]
200
if keywords.has_key ("region") :
201
self.region = keywords ["region"]
204
if keywords.has_key ("tri") :
205
self.tri = keywords ["tri"]
206
if shape (tri) != shape (x) :
207
raise self._QuadMeshSpecError , \
208
"tri, x, and y must have the same shape."
210
n1 = shape (self.x) [0]
211
n2 = shape (self.x) [1]
212
self.tri = zeros ( (n1, n2))
213
if keywords.has_key ("ireg") and keywords ["ireg"] is not None :
214
self.ireg = keywords ["ireg"]
215
if self.dimsofx == 2 :
216
if self.ireg.shape != self.x.shape :
217
raise self._QuadMeshSpecError , \
218
"ireg, x, and y must have the same shape."
219
else: # dimsofx has to be 1
221
self.nx = self.ireg.shape [0]
223
self.ny = self.ireg.shape [1]
224
if self.ireg.shape != (nx, ny) :
225
raise self._QuadMeshSpecError , \
226
"shape of ireg must be nx by ny."
228
if self.dimsofx == 2:
229
self.ireg = array (self.x).astype (Int)
235
self.ireg = array ( (self.nx, self.ny), Int)
236
self.ireg [0:self.nx, 0] = 0
237
self.ireg [0, 0:self.ny] = 0
238
self.ireg [1:self.nx, 1:self.ny] = 1
239
if keywords.has_key ("filled") :
240
self.filled = keywords ["filled"]
243
if keywords.has_key ("edges") :
244
self.edges = keywords ["edges"]
247
if keywords.has_key ("contours") :
248
self.contours = keywords ["contours"]
249
elif self.filled == 0 and self.edges == 0 :
253
if keywords.has_key ("ewidth") :
254
self.ewidth = keywords ["ewidth"]
257
if keywords.has_key ("ecolor") :
258
self.ecolor = keywords ["ecolor"]
261
if keywords.has_key ("levels") :
262
self.levels = keywords ["levels"]
265
if keywords.has_key ("z") :
266
self.z = keywords ["z"]
269
if keywords.has_key ("z_scale") and keywords ["z_scale"] is not None :
270
self.z_scale = keywords ["z_scale"]
273
if self.dimsofx == 1 :
274
if self.z is None or len (self.z.shape) != 1 \
275
or len (self.z) != len (self.x) :
276
raise self._QuadMeshSpecError , \
277
"If x and y are one-dimensional, " + \
278
"then z must be too, and must be the same length."
279
# Compute regular mesh and interpolated values
280
dx = (xmax - xmin) / nx
281
dy = (ymax - ymin) / ny
282
xcplot = span (xmin, xmax - dx, nx)
283
ycplot = span (ymin, ymax - dy, ny)
284
del xmin, xmax, ymin, ymax, dx, dy
285
xt = subtract.outer (self.x, self.x)
286
yt = subtract.outer (self.y, self.y)
287
aa = sqrt (xt * xt + yt * yt + rsq)
289
alpha = array (self.z, copy = 1)
290
alpha = solve_linear_equations (aa, alpha)
291
self.z = mfit (alpha, self.x, xcplot, self.y,
294
# Expand coordinates to 2d arrays to match zcplot
295
self.x = multiply.outer (xcplot, ones (ny, Float))
296
self.y = multiply.outer (ones (nx, Float), ycplot)
297
del xcplot, ycplot, nx, ny
298
if self.dimsofx == 2 and self.z is not None : # check for shape
299
if self.filled == 0 :
300
if self.z.shape != self.x.shape :
301
raise self._QuadMeshSpecError , \
302
"z, x, and y must be the same shape."
304
n1 = self.z.shape [0]
305
n2 = self.z.shape [1]
306
m1 = self.x.shape [0]
307
m2 = self.x.shape [1]
308
if n1 == m1 and n2 == m2 or n1 == m1 - 1 and n2 == m2 - 1 :
311
raise self._QuadMeshSpecError , \
312
"z, x, and y must be the same shape, or z one smaller" + \
313
" in each dimension."
314
if keywords.has_key ("vx") and not is_scalar (keywords ["vx"]) and \
315
len (keywords ["vx"]) > 0 :
316
if not keywords.has_key ("vy") :
317
raise self._QuadMeshSpecError , \
318
"vx and vy must both be present."
319
self.vx = keywords ["vx"]
320
self.vy = keywords ["vy"]
324
if keywords.has_key ("scale") :
325
self.scale = keywords ["scale"]
328
if keywords.has_key ("marks") :
329
self.marks = keywords ["marks"]
332
if keywords.has_key ( "marker" ) :
333
self.marker = keywords [ "marker" ]
335
self.marker = "unspecified"
336
if keywords.has_key ( "regions" ) :
337
self.regions = keywords ["regions"]
338
if is_scalar (self.regions) and self.regions != "all" :
339
self.regions = [self.regions]
341
if self.region == 0 :
344
self.regions = [self.region]
346
def new ( self, ** keywords ) :
347
""" new (...keyword arguments...) allows you to reuse a
348
previously existing quadmesh.
350
self.__init__ ( keywords )
352
def set ( self , ** keywords ) :
353
""" set (...keyword arguments...) allows you to set individual
354
quadmesh characteristics. Very little error checking is done.
356
# The following allopws vx and vy to be cleared by sending in []
357
if keywords.has_key ("vx") :
358
self.vx = keywords ["vx"]
360
if keywords.has_key ("vy") :
361
self.vy = keywords ["vy"]
363
for k in keywords.keys ():
365
self.line_type = keywords ["type"]
367
setattr (self, k, keywords [k])