internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: scikit-image/scikit-image

Issue:
Add Airspeed Velocity monitoring
I just watched Michael Droettboom's talk on his excellent and excellently named project, Airspeed Velocity, which tracks a project's benchmarks over time to ensure that benchmarks don't degrade. It seems pretty bloody awesome and I definitely think we should use it, though the logistics will be a bit tricky.

Talk link:
http://youtu.be/OsxJ5O6h8s0

Once we figure out where to run this, we can run 0.7 - 0.10 and then run master or each PR. (As Michael mentions in his talk, the PR stuff needs to be manual after code vetting or it will be a security risk. Running on a VM messes with the benchmarks.) (Obviously it will be a security risk even after vetting, but a much smaller one. =)



Discussion:

Resolving patch:
diff --git a/benchmarks/benchmarks.py b/benchmarks/benchmarks.py
new file mode 100644
--- /dev/null
+++ b/benchmarks/benchmarks.py
@@ -0,0 +1,18 @@
+# See "Writing benchmarks" in the asv docs for more information.
+import numpy as np
+from skimage import segmentation
+
+
+class SegmentationSuite:
+    """Benchmark for segmentation routines in scikit-image."""
+    def setup(self):
+        self.image = np.random.random((400, 400, 100))
+        self.image[:200, :200, :] += 1
+        self.image[300:, 300:, :] += 0.5
+
+    def time_slic_basic(self):
+        result = segmentation.slic(self.image, enforce_connectivity=False)
+
+    def mem_slic_basic(self):
+        result = segmentation.slic(self.image, enforce_connectivity=False)
+
diff --git a/tools/check_sdist.py b/tools/check_sdist.py
--- a/tools/check_sdist.py
+++ b/tools/check_sdist.py
@@ -17,13 +17,13 @@
 data = [l.replace('hard linking ', '') for l in data]
 data = ['./' + l.split(' ->')[0] for l in data]
 
-ignore_exts = ['.pyc', '.so', '.o', '#', '~', '.gitignore']
+ignore_exts = ['.pyc', '.so', '.o', '#', '~', '.gitignore', '.o.d']
 ignore_dirs = ['./dist', './tools', './doc', './viewer_examples',
-               './downloads', './scikit_image.egg-info']
+               './downloads', './scikit_image.egg-info', './benchmarks']
 ignore_files = ['./TODO.md', './README.md', './MANIFEST',
                 './.gitignore', './.travis.yml', './.gitmodules',
                 './.mailmap', './.coveragerc', './.appveyor.yml',
-                './.pep8speaks.yml',
+                './.pep8speaks.yml', './asv.conf.json',
                 './skimage/filters/rank/README.rst']
 
 


Test patch:
Repository: scikit-image/scikit-image

Issue:
Rescale intensity returns only a float given an array
## Description

I start with a numpy `array` that has `array.shape == (1, 1)` and `array.dtype == np.float64`. Let's define an example `array = np.array([[0]], dtype=np.float64)`.

If I then pass this float64 array as the first argument of `exposure.rescale_intensity`, the function gives `np.float64(0.0)` as an output instead of the expected `np.array([[0.0]], dtype=np.float64)`.

This is caused by [line 298 of exposure.py](https://github.com/scikit-image/scikit-image/blob/b02e2ce7014f245ff20d692519f2c36ed4bf8269/skimage/exposure/exposure.py#L298)

We should replace this line's `dtype(image * (omax - omin) + omin)` with this line:

```python
np.array(image * (omax - omin) + omin, dtype=dtype)
```

When called as a function, `np.float64` has the unexpected behavior that this is true: 

```python
np.float64(np.array([[0]])) == np.float64(0.0)
```

Therefore, contrary to expected behavior, this is false:

```python
type(np.float64(np.array([[0]]))) == np.ndarray
```

I've raised an [issue at numpy/numpy](https://github.com/numpy/numpy/issues/10995), but it appears this behavior will not be corrected given that the `np.float64(array)` syntax is undocumented. I believe all code that depends on numpy should move away from using `np.float64(*)` as an array constructor. It is always safer to use `np.array(*, dtype=np.float64)`.

## Way to reproduce

```python
import numpy as np
import skimage.exposure

array = np.array([[0]], dtype=np.float64)
output = skimage.exposure.rescale_intensity(array, (0, 1))
assert type(output) == np.ndarray #assertion fails
```
Iff `dtype == np.float64`, instead of `[[0.0]]`, rescale_intensity returns`0.0`

- ubuntu 16.04 LTS
- python 3.6.4
- scikit-image 0.13.1




Discussion:
@thejohnhoffer Thank you for reporting this! There is definitely a consistency issue in `numpy`, but this specific case we handle by re-writing https://github.com/scikit-image/scikit-image/blob/b02e2ce7014f245ff20d692519f2c36ed4bf8269/skimage/exposure/exposure.py#L298 without using `dtype()` call. Would you like to sumbit a PR?

Resolving patch:
diff --git a/skimage/exposure/exposure.py b/skimage/exposure/exposure.py
--- a/skimage/exposure/exposure.py
+++ b/skimage/exposure/exposure.py
@@ -294,7 +294,7 @@ def rescale_intensity(image, in_range='image', out_range='dtype'):
     image = np.clip(image, imin, imax)
 
     image = (image - imin) / float(imax - imin)
-    return dtype(image * (omax - omin) + omin)
+    return np.array(image * (omax - omin) + omin, dtype=dtype)
 
 
 def _assert_non_negative(image):


Test patch:
Repository: scikit-image/scikit-image

Issue:
label2rgb index error when using average and background color
When using averaged label2rgb with bg_label the out image indexing fails with error:

```
Traceback (most recent call last):
  File "file.py", line 222, in generate
    overlay = color.label2rgb(domain, image=img, bg_label=0, bg_color=1.0, kind="avg")
  File "[...]/python3.6/site-packages/skimage/color/colorlabel.py", line 116, in label2rgb
    return _label2rgb_avg(label, image, bg_label, bg_color)
  File "[...]/python3.6/site-packages/skimage/color/colorlabel.py", line 225, in _label2rgb_avg
    out[bg] = bg_color
IndexError: boolean index did not match indexed array along dimension 0; dimension is 100 but corresponding boolean dimension is 2
```


Discussion:

Resolving patch:
diff --git a/skimage/color/colorlabel.py b/skimage/color/colorlabel.py
--- a/skimage/color/colorlabel.py
+++ b/skimage/color/colorlabel.py
@@ -219,7 +219,8 @@ def _label2rgb_avg(label_field, image, bg_label=0, bg_color=(0, 0, 0)):
     bg = (labels == bg_label)
     if bg.any():
         labels = labels[labels != bg_label]
-        out[bg] = bg_color
+        mask = (label_field == bg_label).nonzero()
+        out[mask] = bg_color
     for label in labels:
         mask = (label_field == label).nonzero()
         color = image[mask].mean(axis=0)


Test patch:
diff --git a/skimage/color/tests/test_colorlabel.py b/skimage/color/tests/test_colorlabel.py
--- a/skimage/color/tests/test_colorlabel.py
+++ b/skimage/color/tests/test_colorlabel.py
@@ -113,7 +113,7 @@ def test_avg():
     # label image
     label_field = np.array([[1, 1, 1, 2],
                             [1, 2, 2, 2],
-                            [3, 3, 3, 3]], dtype=np.uint8)
+                            [3, 3, 4, 4]], dtype=np.uint8)
 
     # color image
     r = np.array([[1., 1., 0., 0.],
@@ -136,7 +136,7 @@ def test_avg():
                      [0.  , 0.  , 0.  , 0.  ]])
     bout = np.array([[0. , 0. , 0. , 1. ],
                      [0. , 1. , 1. , 1. ],
-                     [0.5, 0.5, 0.5, 0.5]])
+                     [0.0, 0.0, 1.0, 1.0]])
     expected_out = np.dstack((rout, gout, bout))
 
     # test standard averaging
Repository: scikit-image/scikit-image

Issue:
Performance improvement for `scikit-image/skimage/feature/_texture.pyx`
## Description
When calculating GLCM using the _glcm_loop, the offset pixel calculation can be optimized slightly.
In lines 68-69 the pixel offset value is calculated per each element, those offset values are constant and require both the calculation of a trigonometric function and casting to a different variable type.
By calculating the rowOffset and columnOffset ouside of the loop those executions need only happen once.
                        row = r + <int>round(sin(angle) * distance)
                        col = c + <int>round(cos(angle) * distance)

Some further optimization can be done by using the offset size(s) to reduce the number of iterations by changing the range of the for loops in lines 63 and 64.
In my opinion it would be wiser to change the convention from distance and angle to  rowOffset and columnOffset, but that does not conform with the standard notations.






Discussion:
@abTest-123 sure! Feel free to submit a Pull Request with the proposed changes. I guess you might need to also measure the performance benefit in order to convince the other team members.
Thank you for suggesting that @soupault. I tried to test it locally and got stuck when needed to compile the .pyx code, this is out of my pythonic comfort zone. 
If you want to expand your comfort zone, try giving this a read:

http://scikit-image.org/docs/dev/contribute.html

You might need a c compiler on windows. Visually studio 2015 or 2017 is fine

Resolving patch:
diff --git a/benchmarks/benchmark_feature.py b/benchmarks/benchmark_feature.py
--- a/benchmarks/benchmark_feature.py
+++ b/benchmarks/benchmark_feature.py
@@ -2,7 +2,7 @@
 # http://asv.readthedocs.io/en/latest/writing_benchmarks.html
 import numpy as np
 from scipy import ndimage as ndi
-from skimage import feature
+from skimage import feature, util
 
 
 class FeatureSuite:
@@ -15,5 +15,12 @@ def setup(self):
         self.image = ndi.gaussian_filter(self.image, 4)
         self.image += 0.2 * np.random.random(self.image.shape)
 
+        self.image_ubyte = util.img_as_ubyte(np.clip(self.image, 0, 1))
+
     def time_canny(self):
         result = feature.canny(self.image)
+
+    def time_glcm(self):
+        pi = np.pi
+        result = feature.greycomatrix(self.image_ubyte, distances=[1, 2],
+                                      angles=[0, pi/4, pi/2, 3*pi/4])


Test patch:
diff --git a/requirements/test.txt b/requirements/test.txt
--- a/requirements/test.txt
+++ b/requirements/test.txt
@@ -1,4 +1,6 @@
-pytest
+# pytest 3.7.3 is broken on macOS, see:
+# https://github.com/pytest-dev/pytest/issues/3888
+pytest!=3.7.3
 pytest-cov
 flake8
 codecov
Repository: scikit-image/scikit-image

Issue:
DOC: Broken link to Gabor tutorial
## Description
On this page:

http://scikit-image.org/docs/dev/api/skimage.filters.html#skimage.filters.gabor_kernel

the link to the Gabor tutorial:

http://mplab.ucsd.edu/tutorials/gabor.pdf

is broken.



Discussion:
It is still visible on the internet archive: https://web.archive.org/web/20180127125930/http://mplab.ucsd.edu/tutorials/gabor.pdf
Maybe we need to mirror it?
@hmaarrfk It's something I wondered myself but regarding the copyright, I don't know if we want to do that...
Yeah....
It looks like the author (Javier Movellan) has made it publicly available on ResearchGate:
https://www.researchgate.net/publication/265064863_Tutorial_on_Gabor_Filters

Resolving patch:
diff --git a/skimage/filters/_frangi.py b/skimage/filters/_frangi.py
--- a/skimage/filters/_frangi.py
+++ b/skimage/filters/_frangi.py
@@ -114,7 +114,7 @@ def frangi(image, scale_range=(1, 10), scale_step=2, beta1=0.5, beta2=15,
            vessel enhancement filtering," In LNCS, vol. 1496, pages 130-137,
            Germany, 1998. Springer-Verlag.
     .. [2] Kroon, D.J.: Hessian based Frangi vesselness filter.
-    .. [3] http://mplab.ucsd.edu/tutorials/gabor.pdf.
+    .. [3] https://web.archive.org/web/20180127125930/http://mplab.ucsd.edu/tutorials/gabor.pdf
     """
     filtered, lambdas = _frangi_hessian_common_filter(image,
                                                       scale_range, scale_step,
diff --git a/skimage/filters/_gabor.py b/skimage/filters/_gabor.py
--- a/skimage/filters/_gabor.py
+++ b/skimage/filters/_gabor.py
@@ -52,7 +52,7 @@ def gabor_kernel(frequency, theta=0, bandwidth=1, sigma_x=None, sigma_y=None,
     References
     ----------
     .. [1] https://en.wikipedia.org/wiki/Gabor_filter
-    .. [2] http://mplab.ucsd.edu/tutorials/gabor.pdf
+    .. [2] https://web.archive.org/web/20180127125930/http://mplab.ucsd.edu/tutorials/gabor.pdf
 
     Examples
     --------
@@ -144,7 +144,7 @@ def gabor(image, frequency, theta=0, bandwidth=1, sigma_x=None,
     References
     ----------
     .. [1] https://en.wikipedia.org/wiki/Gabor_filter
-    .. [2] http://mplab.ucsd.edu/tutorials/gabor.pdf
+    .. [2] https://web.archive.org/web/20180127125930/http://mplab.ucsd.edu/tutorials/gabor.pdf
 
     Examples
     --------


Test patch:
Repository: scikit-image/scikit-image

Issue:
Orphan code in filters
I noticed that https://github.com/scikit-image/scikit-image/blob/master/skimage/filters/_ctmf.pyx is not imported in the ``__init__.py`` of ``filters`` or elsewhere in this submodule. I have the feeling that this code, which was originally taken from CellProfiler, is now orphan. Should we remove it?


Discussion:
Yes from me
If you remove it, and Travis-CI is happy, trash it!


Resolving patch:
diff --git a/skimage/filters/setup.py b/skimage/filters/setup.py
--- a/skimage/filters/setup.py
+++ b/skimage/filters/setup.py
@@ -13,14 +13,11 @@ def configuration(parent_package='', top_path=None):
     config.add_data_dir('tests')
     config.add_data_dir('rank/tests')
 
-    cython(['_ctmf.pyx',
-            'rank/core_cy.pyx',
+    cython(['rank/core_cy.pyx',
             'rank/generic_cy.pyx',
             'rank/percentile_cy.pyx',
             'rank/bilateral_cy.pyx'], working_path=base_path)
 
-    config.add_extension('_ctmf', sources=['_ctmf.c'],
-                         include_dirs=[get_numpy_include_dirs()])
     config.add_extension('rank.core_cy', sources=['rank/core_cy.c'],
         include_dirs=[get_numpy_include_dirs()])
     config.add_extension('rank.generic_cy', sources=['rank/generic_cy.c'],


Test patch:
Repository: scikit-image/scikit-image

Issue:
Clarify difference between filled_area, area, and convex_area in regionprops
Update the regionprops docstring to clarify the above.



Discussion:
Please provide the link to the particular file where I can make changes.
Thanks.

Hello @yash14123 . You can find it yourself.
`grep` is a good place to start if you have no idea where to look

``` shell
$> git grep filled_area
skimage/measure/_regionprops.py:    'FilledArea': 'filled_area',
skimage/measure/_regionprops.py:    def filled_area(self):
skimage/measure/_regionprops.py:    **filled_area** : int
skimage/measure/tests/test_regionprops.py:def test_filled_area():
skimage/measure/tests/test_regionprops.py:    area = regionprops(SAMPLE)[0].filled_area
skimage/measure/tests/test_regionprops.py:    area = regionprops(SAMPLE_mod)[0].filled_area
```

No. I meant the documentation link. I am a newbie. Just help me out with the documentation page link. 

The documentation is generated from the source files. As indicated with the grep search, the file is.
https://github.com/scikit-image/scikit-image/blob/master/skimage/measure/_regionprops.py

![](https://github.trello.services/images/mini-trello-icon.png) [Clarify difference between filled_area, area, and convex_hull_area in regionprops](https://trello.com/c/AK4AQzxZ/4-clarify-difference-between-filled-area-area-and-convex-hull-area-in-regionprops)

See #2344 


Resolving patch:
diff --git a/skimage/measure/_regionprops.py b/skimage/measure/_regionprops.py
--- a/skimage/measure/_regionprops.py
+++ b/skimage/measure/_regionprops.py
@@ -395,7 +395,7 @@ def regionprops(label_image, intensity_image=None, cache=True,
     The following properties can be accessed as attributes or keys:
 
     **area** : int
-        Number of pixels of region.
+        Number of pixels of the region.
     **bbox** : tuple
         Bounding box ``(min_row, min_col, max_row, max_col)``.
         Pixels belonging to the bounding box are in the half-open interval
@@ -405,7 +405,8 @@ def regionprops(label_image, intensity_image=None, cache=True,
     **centroid** : array
         Centroid coordinate tuple ``(row, col)``.
     **convex_area** : int
-        Number of pixels of convex hull image.
+        Number of pixels of convex hull image, which is the smallest convex
+        polygon that encloses the region.
     **convex_image** : (H, J) ndarray
         Binary convex hull image which has the same size as bounding box.
     **coords** : (N, 2) ndarray
@@ -425,7 +426,8 @@ def regionprops(label_image, intensity_image=None, cache=True,
         Ratio of pixels in the region to pixels in the total bounding box.
         Computed as ``area / (rows * cols)``
     **filled_area** : int
-        Number of pixels of filled region.
+        Number of pixels of the region will all the holes filled in. Describes
+        the area of the filled_image.
     **filled_image** : (H, J) ndarray
         Binary region image with filled holes which has the same size as
         bounding box.


Test patch:
Repository: scikit-image/scikit-image

Issue:
perimeter documentation and prototype function
## Description
skimage.measure.perimeter lacks a relevant documentation and description.


The neighborhood configuration should precise that it is used for computing the contour and is different from the connectivity of the contour itself. 

Moreover, the general terminology (1-, 2-, 3-, ..., ndim-) should be adopted in the prototype of the function.




Discussion:

Resolving patch:
diff --git a/skimage/measure/_regionprops.py b/skimage/measure/_regionprops.py
--- a/skimage/measure/_regionprops.py
+++ b/skimage/measure/_regionprops.py
@@ -586,10 +586,12 @@ def perimeter(image, neighbourhood=4):
 
     Parameters
     ----------
-    image : array
-        Binary image.
+    image : (N, M) ndarray
+        2D binary image.
     neighbourhood : 4 or 8, optional
-        Neighborhood connectivity for border pixel determination.
+        Neighborhood connectivity for border pixel determination. It is used to
+        compute the contour. A higher neighbourhood widens the border on which
+        the perimeter is computed.
 
     Returns
     -------
@@ -601,7 +603,23 @@ def perimeter(image, neighbourhood=4):
     .. [1] K. Benkrid, D. Crookes. Design and FPGA Implementation of
            a Perimeter Estimator. The Queen's University of Belfast.
            http://www.cs.qub.ac.uk/~d.crookes/webpubs/papers/perimeter.doc
+
+    Examples
+    --------
+    >>> from skimage import data, util
+    >>> from skimage.measure import label
+    >>> # coins image (binary)
+    >>> img_coins = data.coins() > 110
+    >>> # total perimeter of all objects in the image
+    >>> perimeter(img_coins, neighbourhood=4)  # doctest: +ELLIPSIS
+    7796.867...
+    >>> perimeter(img_coins, neighbourhood=8)  # doctest: +ELLIPSIS
+    8806.268...
+
     """
+    if image.ndim != 2:
+        raise NotImplementedError('`perimeter` supports 2D images only')
+
     if neighbourhood == 4:
         strel = STREL_4
     else:


Test patch:
Repository: scikit-image/scikit-image

Issue:
Document top hat functions.
## Description

Assigned to myself.

Document (during the next sprint?)
* http://scikit-image.org/docs/stable/api/skimage.morphology.html#white-tophat
* http://scikit-image.org/docs/stable/api/skimage.morphology.html#black-tophat

- [ ] Add wikipedia page as ref : https://en.wikipedia.org/wiki/Top-hat_transform
- [ ] Add See also sections
- [ ] Add gallery example


I'm sure this is fairly unknown because not well documented...


Discussion:

Resolving patch:
diff --git a/doc/examples/filters/plot_tophat.py b/doc/examples/filters/plot_tophat.py
new file mode 100644
--- /dev/null
+++ b/doc/examples/filters/plot_tophat.py
@@ -0,0 +1,35 @@
+"""
+================================================================
+Removing small objects in grayscale images with a top hat filter
+================================================================
+
+This example shows how to remove small objects from grayscale images.
+The top-hat transform [1]_ is an operation that extracts small elements and
+details from given images. Here we use a white top-hat transform, which is
+defined as the difference between the input image and its
+(mathematical morphology) opening.
+
+.. [1] https://en.wikipedia.org/wiki/Top-hat_transform
+
+"""
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+from skimage import data
+from skimage import color, morphology
+
+image = color.rgb2gray(data.hubble_deep_field())[:500, :500]
+
+selem =  morphology.disk(1)
+res = morphology.white_tophat(image, selem)
+
+fig, ax = plt.subplots(ncols=3, figsize=(20, 8))
+ax[0].set_title('Original')
+ax[0].imshow(image, cmap='gray')
+ax[1].set_title('White tophat')
+ax[1].imshow(res, cmap='gray')
+ax[2].set_title('Complementary')
+ax[2].imshow(image - res, cmap='gray')
+
+plt.show()
diff --git a/skimage/morphology/grey.py b/skimage/morphology/grey.py
--- a/skimage/morphology/grey.py
+++ b/skimage/morphology/grey.py
@@ -376,6 +376,14 @@ def white_tophat(image, selem=None, out=None):
     out : array, same shape and type as `image`
         The result of the morphological white top hat.
 
+    See also
+    --------
+    black_tophat
+
+    References
+    ----------
+    .. [1] https://en.wikipedia.org/wiki/Top-hat_transform
+
     Examples
     --------
     >>> # Subtract grey background from bright peak
@@ -443,6 +451,14 @@ def black_tophat(image, selem=None, out=None):
     out : array, same shape and type as `image`
         The result of the morphological black top hat.
 
+    See also
+    --------
+    white_tophat
+
+    References
+    ----------
+    .. [1] https://en.wikipedia.org/wiki/Top-hat_transform
+
     Examples
     --------
     >>> # Change dark peak to bright peak and subtract background


Test patch:
Repository: scikit-image/scikit-image

Issue:
order the examples in our gallery
## Description


As suggested by @emmanuelle in #3388, it would be interesting to use the [ordering feature of sphinx-gallery](https://sphinx-gallery.readthedocs.io/en/stable/advanced_configuration.html?highlight=sorting#sub-gallery-order) a set a more logical order among sections and examples (eg operation on numpy arrays could come among the first ones).





Discussion:

Resolving patch:
diff --git a/doc/source/conf.py b/doc/source/conf.py
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -14,6 +14,8 @@
 import sys
 import os
 import skimage
+from sphinx_gallery.sorting import ExplicitOrder
+
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
@@ -45,15 +47,25 @@
 #------------------------------------------------------------------------
 
 sphinx_gallery_conf = {
-    'doc_module'        : ('skimage',),
+    'doc_module': ('skimage',),
     # path to your examples scripts
-    'examples_dirs' : '../examples',
+    'examples_dirs': '../examples',
     # path where to save gallery generated examples
-    'gallery_dirs'  : 'auto_examples',
+    'gallery_dirs': 'auto_examples',
     'backreferences_dir': 'api',
-    'reference_url'     : {
-            'skimage': None,}
-    }
+    'reference_url': {'skimage': None},
+    'subsection_order': ExplicitOrder([
+        '../examples/data',
+        '../examples/numpy_operations',
+        '../examples/color_exposure',
+        '../examples/edges',
+        '../examples/transform',
+        '../examples/filters',
+        '../examples/features_detection',
+        '../examples/segmentation',
+        '../examples/xx_applications',
+    ]),
+}
 
 # Determine if the matplotlib has a recent enough version of the
 # plot_directive, otherwise use the local fork.


Test patch:
Repository: scikit-image/scikit-image

Issue:
tifffile: try to use the one in the user's install first
Should we try importing tifffile before using the one we versionned it?


Discussion:
imho, an emphatic *yes*.
@hmaarrfk Certainly! Very good point! :slightly_smiling_face: 

Resolving patch:
diff --git a/skimage/io/_plugins/tifffile_plugin.py b/skimage/io/_plugins/tifffile_plugin.py
--- a/skimage/io/_plugins/tifffile_plugin.py
+++ b/skimage/io/_plugins/tifffile_plugin.py
@@ -1,4 +1,7 @@
-from ...external.tifffile import TiffFile, imsave, parse_kwargs
+try:
+    from tifffile import TiffFile, imsave, parse_kwargs
+except ImportError:
+    from ...external.tifffile import TiffFile, imsave, parse_kwargs
 
 
 def imread(fname, dtype=None, **kwargs):


Test patch: