@@ -1304,181 +1304,6 @@ def splitfunc(x):
13041304 else : return X
13051305
13061306
1307- def slopes (x ,y ):
1308- """
1309- SLOPES calculate the slope y'(x) Given data vectors X and Y SLOPES
1310- calculates Y'(X), i.e the slope of a curve Y(X). The slope is
1311- estimated using the slope obtained from that of a parabola through
1312- any three consecutive points.
1313-
1314- This method should be superior to that described in the appendix
1315- of A CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russel
1316- W. Stineman (Creative Computing July 1980) in at least one aspect:
1317-
1318- Circles for interpolation demand a known aspect ratio between x-
1319- and y-values. For many functions, however, the abscissa are given
1320- in different dimensions, so an aspect ratio is completely
1321- arbitrary.
1322-
1323- The parabola method gives very similar results to the circle
1324- method for most regular cases but behaves much better in special
1325- cases
1326-
1327- Norbert Nemec, Institute of Theoretical Physics, University or
1328- Regensburg, April 2006 Norbert.Nemec at physik.uni-regensburg.de
1329-
1330- (inspired by a original implementation by Halldor Bjornsson,
1331- Icelandic Meteorological Office, March 2006 halldor at vedur.is)
1332- """
1333- # Cast key variables as float.
1334- x = np .asarray (x , np .float_ )
1335- y = np .asarray (y , np .float_ )
1336-
1337- yp = np .zeros (y .shape , np .float_ )
1338-
1339- dx = x [1 :] - x [:- 1 ]
1340- dy = y [1 :] - y [:- 1 ]
1341- dydx = dy / dx
1342- yp [1 :- 1 ] = (dydx [:- 1 ] * dx [1 :] + dydx [1 :] * dx [:- 1 ])/ (dx [1 :] + dx [:- 1 ])
1343- yp [0 ] = 2.0 * dy [0 ]/ dx [0 ] - yp [1 ]
1344- yp [- 1 ] = 2.0 * dy [- 1 ]/ dx [- 1 ] - yp [- 2 ]
1345- return yp
1346-
1347-
1348- def stineman_interp (xi ,x ,y ,yp = None ):
1349- """
1350- STINEMAN_INTERP Well behaved data interpolation. Given data
1351- vectors X and Y, the slope vector YP and a new abscissa vector XI
1352- the function stineman_interp(xi,x,y,yp) uses Stineman
1353- interpolation to calculate a vector YI corresponding to XI.
1354-
1355- Here's an example that generates a coarse sine curve, then
1356- interpolates over a finer abscissa:
1357-
1358- x = linspace(0,2*pi,20); y = sin(x); yp = cos(x)
1359- xi = linspace(0,2*pi,40);
1360- yi = stineman_interp(xi,x,y,yp);
1361- plot(x,y,'o',xi,yi)
1362-
1363- The interpolation method is described in the article A
1364- CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russell
1365- W. Stineman. The article appeared in the July 1980 issue of
1366- Creative Computing with a note from the editor stating that while
1367- they were
1368-
1369- not an academic journal but once in a while something serious
1370- and original comes in adding that this was
1371- "apparently a real solution" to a well known problem.
1372-
1373- For yp=None, the routine automatically determines the slopes using
1374- the "slopes" routine.
1375-
1376- X is assumed to be sorted in increasing order
1377-
1378- For values xi[j] < x[0] or xi[j] > x[-1], the routine tries a
1379- extrapolation. The relevance of the data obtained from this, of
1380- course, questionable...
1381-
1382- original implementation by Halldor Bjornsson, Icelandic
1383- Meteorolocial Office, March 2006 halldor at vedur.is
1384-
1385- completely reworked and optimized for Python by Norbert Nemec,
1386- Institute of Theoretical Physics, University or Regensburg, April
1387- 2006 Norbert.Nemec at physik.uni-regensburg.de
1388-
1389- """
1390-
1391- # Cast key variables as float.
1392- x = np .asarray (x , np .float_ )
1393- y = np .asarray (y , np .float_ )
1394- assert x .shape == y .shape
1395- N = len (y )
1396-
1397- if yp is None :
1398- yp = slopes (x ,y )
1399- else :
1400- yp = np .asarray (yp , np .float_ )
1401-
1402- xi = np .asarray (xi , np .float_ )
1403- yi = np .zeros (xi .shape , np .float_ )
1404-
1405- # calculate linear slopes
1406- dx = x [1 :] - x [:- 1 ]
1407- dy = y [1 :] - y [:- 1 ]
1408- s = dy / dx #note length of s is N-1 so last element is #N-2
1409-
1410- # find the segment each xi is in
1411- # this line actually is the key to the efficiency of this implementation
1412- idx = np .searchsorted (x [1 :- 1 ], xi )
1413-
1414- # now we have generally: x[idx[j]] <= xi[j] <= x[idx[j]+1]
1415- # except at the boundaries, where it may be that xi[j] < x[0] or xi[j] > x[-1]
1416-
1417- # the y-values that would come out from a linear interpolation:
1418- sidx = s .take (idx )
1419- xidx = x .take (idx )
1420- yidx = y .take (idx )
1421- xidxp1 = x .take (idx + 1 )
1422- yo = yidx + sidx * (xi - xidx )
1423-
1424- # the difference that comes when using the slopes given in yp
1425- dy1 = (yp .take (idx )- sidx ) * (xi - xidx ) # using the yp slope of the left point
1426- dy2 = (yp .take (idx + 1 )- sidx ) * (xi - xidxp1 ) # using the yp slope of the right point
1427-
1428- dy1dy2 = dy1 * dy2
1429- # The following is optimized for Python. The solution actually
1430- # does more calculations than necessary but exploiting the power
1431- # of numpy, this is far more efficient than coding a loop by hand
1432- # in Python
1433- yi = yo + dy1dy2 * np .choose (np .array (np .sign (dy1dy2 ), np .int32 )+ 1 ,
1434- ((2 * xi - xidx - xidxp1 )/ ((dy1 - dy2 )* (xidxp1 - xidx )),
1435- 0.0 ,
1436- 1 / (dy1 + dy2 ),))
1437- return yi
1438-
1439- def inside_poly (points , verts ):
1440- """
1441- points is a sequence of x,y points
1442- verts is a sequence of x,y vertices of a poygon
1443-
1444- return value is a sequence of indices into points for the points
1445- that are inside the polygon
1446- """
1447- res , = np .nonzero (nxutils .points_inside_poly (points , verts ))
1448- return res
1449-
1450- def poly_below (ymin , xs , ys ):
1451- """
1452- given a arrays *xs* and *ys*, return the vertices of a polygon
1453- that has a scalar lower bound *ymin* and an upper bound at the *ys*.
1454-
1455- intended for use with Axes.fill, eg::
1456-
1457- xv, yv = poly_below(0, x, y)
1458- ax.fill(xv, yv)
1459- """
1460- return poly_between (xs , ys , xmin )
1461-
1462-
1463- def poly_between (x , ylower , yupper ):
1464- """
1465- given a sequence of x, ylower and yupper, return the polygon that
1466- fills the regions between them. ylower or yupper can be scalar or
1467- iterable. If they are iterable, they must be equal in length to x
1468-
1469- return value is x, y arrays for use with Axes.fill
1470- """
1471- Nx = len (x )
1472- if not cbook .iterable (ylower ):
1473- ylower = ylower * np .ones (Nx )
1474-
1475- if not cbook .iterable (yupper ):
1476- yupper = yupper * np .ones (Nx )
1477-
1478- x = np .concatenate ( (x , x [::- 1 ]) )
1479- y = np .concatenate ( (yupper , ylower [::- 1 ]) )
1480- return x ,y
1481-
14821307### the following code was written and submitted by Fernando Perez
14831308### from the ipython numutils package under a BSD license
14841309# begin fperez functions
0 commit comments