Repository: scipy/scipy

Issue:
surfit_smth computes too small lwrk2 (Trac #1003)
_Original ticket http://projects.scipy.org/scipy/ticket/1003 on 2009-09-25 by trac user nicoletti, assigned to unknown._

Dear all,

I have tried to use the class SmoothBivariateSpline, but it seems to me that it returns always zeros. I attach the output and the script file.

```
>python -u "bspline.py"    
/usr/lib/python2.5/site-packages/scipy/interpolate/fitpack.py:763: DeprecationWarning: integer argument expected, got float
  tx,ty,nxest,nyest,wrk,lwrk1,lwrk2)
/usr/lib/python2.5/site-packages/scipy/interpolate/fitpack2.py:439: UserWarning: ier=1368
  warnings.warn(message)
[[-2.89772727 -2.86668909 -2.83510787 ...,  0.65215576  0.67305161
   0.69318182]
 [-2.87406809 -2.84319518 -2.81177699 ...,  0.67025301  0.69120171
   0.71138701]
 [-2.85038278 -2.81967401 -2.78841772 ...,  0.68848547  0.70948813
   0.72972964]
 ..., 
 [-0.72972964 -0.70948813 -0.68848547 ...,  2.78841772  2.81967401
   2.85038278]
 [-0.71138701 -0.69120171 -0.67025301 ...,  2.81177699  2.84319518
   2.87406809]
 [-0.69318182 -0.67305161 -0.65215576 ...,  2.83510787  2.86668909
   2.89772727]] [[ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]
 ..., 
 [ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]]
>Exit code: 1    Time: 1,221
```



Discussion:
Attachment added by trac user nicoletti on 2009-09-25: [bspline.py](http://projects.scipy.org/scipy/attachment/ticket/1003/bspline.py)

_@pv wrote on 2009-09-26_

First, note that you are trying to extrapolate values in 2D, based on a set points all residing along a single line. This is probably an ill-posed problem for computing the smoothing spline approximation on a whole rectangle.

The real problem and the reason for getting zeros here seems to be that for me, a warning is emitted:

```
/usr/lib/python2.6/dist-packages/scipy/interpolate/fitpack2.py:439: UserWarning: ier=1368
```

Reading fitpack/surfit.f indicates that this is a sign of too small `lwrk2`.

Title changed from `SmoothBivariateSpline returns always zeros!` to `surfit_smth computes too small lwrk2` by @pv on 2009-09-26

`SmoothBivariateSpline` currently always calls `surfit_smth` with `lwrk2=1`. As a consequence, `lwrk2` is not computed by `calc_surfit_lwrk2`, ever. If we want to avoid _always_ spending the extra memory for `lwrk2`, one could once call `surfit_smth` with `lwrk2=1`, and then check for the return value of `ier`. If `ier>10`, we could automaticall call `surfit_smth` again, this time with `lwrk2=None`.

What do you think?

Yes, trying again with a larger lwrk2 based on the ier return value would be better. This is what the other FITPACK wrapper code (the C wrapper) does.


Resolving patch:
diff --git a/scipy/interpolate/fitpack2.py b/scipy/interpolate/fitpack2.py
--- a/scipy/interpolate/fitpack2.py
+++ b/scipy/interpolate/fitpack2.py
@@ -753,6 +753,11 @@ def __init__(self, x, y, z, w=None, bbox=[None] * 4, kx=3, ky=3, s=None,
                                                          xb,xe,yb,ye,
                                                          kx,ky,s=s,
                                                          eps=eps,lwrk2=1)
+        if ier > 10:          # lwrk2 was to small, re-run
+            nx,tx,ny,ty,c,fp,wrk1,ier = dfitpack.surfit_smth(x,y,z,w,
+                                                         xb,xe,yb,ye,
+                                                         kx,ky,s=s,
+                                                         eps=eps,lwrk2=ier)
         if ier in [0,-1,-2]:  # normal return
             pass
         else:


Test patch:
diff --git a/scipy/interpolate/tests/test_fitpack2.py b/scipy/interpolate/tests/test_fitpack2.py
--- a/scipy/interpolate/tests/test_fitpack2.py
+++ b/scipy/interpolate/tests/test_fitpack2.py
@@ -9,6 +9,7 @@
         assert_array_almost_equal, assert_allclose, TestCase, run_module_suite
 from numpy.testing.utils import WarningManager
 from numpy import array, diff, linspace, meshgrid, ones, pi, roll, shape
+from scipy.interpolate.fitpack import bisplrep, bisplev
 from scipy.interpolate.fitpack2 import UnivariateSpline, \
     LSQBivariateSpline, SmoothBivariateSpline, RectBivariateSpline, \
     LSQSphereBivariateSpline, SmoothSphereBivariateSpline, \
@@ -217,6 +218,21 @@ def test_integral(self):
                     * (tz[:-1,:-1]+tz[1:,:-1]+tz[:-1,1:]+tz[1:,1:])).sum()
         assert_almost_equal(lut.integral(tx[0], tx[-2], ty[0], ty[-2]), trpz)
 
+    def test_rerun_lwrk2_too_small(self):
+        # in this setting, lwrk2 is too small in the default run. Here we
+        # check for equality with the bisplrep/bisplev output because there,
+        # an automatic re-run of the spline representation is done if ier>10.
+        x = np.linspace(-2, 2, 80)
+        y = np.linspace(-2, 2, 80)
+        z = x + y
+        xi = np.linspace(-1, 1, 100)
+        yi = np.linspace(-2, 2, 100)
+        tck = bisplrep(x, y, z)
+        res1 = bisplev(xi, yi, tck)
+        interp_ = SmoothBivariateSpline(x, y, z)
+        res2 = interp_(xi, yi)
+        assert_almost_equal(res1, res2)
+
 
 class TestLSQSphereBivariateSpline(TestCase):
     def setUp(self):