Repository: scikit-image/scikit-image

Issue:
skimage.transform.rescale does not support multidimensional scaling for multichannel images
## Description
When using an array for the scale argument of the rescale function an error is raised whenever the image being rescaled is multichannel. 

## Traceback
```
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-61-27f3cec9c67e> in <module>()
----> 1 dat['img'].apply(rescale, scale=(.5, .5)).iloc[0].shape

~/anaconda3/lib/python3.6/site-packages/pandas/core/series.py in apply(self, func, convert_dtype, args, **kwds)
   2549             else:
   2550                 values = self.asobject
-> 2551                 mapped = lib.map_infer(values, f, convert=convert_dtype)
   2552 
   2553         if len(mapped) and isinstance(mapped[0], Series):

pandas/_libs/src/inference.pyx in pandas._libs.lib.map_infer()

~/anaconda3/lib/python3.6/site-packages/pandas/core/series.py in <lambda>(x)
   2536         # handle ufuncs and lambdas
   2537         if kwds or args and not isinstance(func, np.ufunc):
-> 2538             f = lambda x: func(x, *args, **kwds)
   2539         else:
   2540             f = func

[deleted]/skimage/transform/_warps.py in rescale(image, scale, order, mode, cval, clip, preserve_range, multichannel, anti_aliasing, anti_aliasing_sigma)
    267     if len(scale) > 1 and (len(scale) != image.ndim or
    268                            (multichannel and len(scale) != image.ndim - 1)):
--> 269         raise ValueError("must supply a single scale or one value per axis")
    270     orig_shape = np.asarray(image.shape)
    271     output_shape = np.round(scale * orig_shape)

ValueError: must supply a single scale or one value per axis
```

## What seems to be the cause
The problem seems to be this if statement:
```
if len(scale) > 1 and (len(scale) != image.ndim or (multichannel and len(scale) != image.ndim - 1)):
```
The statement after the first `and` always evaluates to True if `multichannel` is True. Seems like a simple fix, but there could be more bugs hiding under there. 


Discussion:

Resolving patch:
diff --git a/skimage/transform/_warps.py b/skimage/transform/_warps.py
--- a/skimage/transform/_warps.py
+++ b/skimage/transform/_warps.py
@@ -264,9 +264,13 @@ def rescale(image, scale, order=1, mode=None, cval=0, clip=True,
     """
     multichannel = _multichannel_default(multichannel, image.ndim)
     scale = np.atleast_1d(scale)
-    if len(scale) > 1 and (len(scale) != image.ndim or
-                           (multichannel and len(scale) != image.ndim - 1)):
-        raise ValueError("must supply a single scale or one value per axis")
+    if len(scale) > 1:
+        if ((not multichannel and len(scale) != image.ndim) or
+                (multichannel and len(scale) != image.ndim - 1)):
+            raise ValueError("Supply a single scale, or one value per spatial "
+                             "axis")
+        if multichannel:
+            scale = np.concatenate((scale, [1]))
     orig_shape = np.asarray(image.shape)
     output_shape = np.round(scale * orig_shape)
     if multichannel:  # don't scale channel dimension


Test patch:
diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py
--- a/skimage/transform/tests/test_warps.py
+++ b/skimage/transform/tests/test_warps.py
@@ -214,6 +214,13 @@ def test_rescale_multichannel():
     assert_equal(scaled.shape, (16, 16, 16, 6))
 
 
+def test_rescale_multichannel_multiscale():
+    x = np.zeros((5, 5, 3), dtype=np.double)
+    scaled = rescale(x, (2, 1), order=0, multichannel=True,
+                     anti_aliasing=False)
+    assert_equal(scaled.shape, (10, 5, 3))
+
+
 def test_rescale_multichannel_defaults():
     # ensure multichannel=None matches the previous default behaviour