Repository: scikit-image/scikit-image

Issue:
Use astropy instead of pyfits to read FITS images
pyfits is not currently installable on 3.5, and it looks like AstroPy is more actively maintained.


Discussion:
@stefanv, I only found 2 references to `pyfits`
  *  [fits_plugin](https://github.com/scikit-image/scikit-image/blame/ef78faf04435717a1b5797bc1a02c73d9b5e8e7f/skimage/io/_plugins/fits_plugin.py#L6)
  *  [test_fits](https://github.com/scikit-image/scikit-image/blob/ef78faf04435717a1b5797bc1a02c73d9b5e8e7f/skimage/io/tests/test_fits.py#L11)

I searched for `import pyfits` and `from pyfits`.

Do you want somebody to completely rip out all mentions of `pyfits` and get rid of the logic that allows fallback?

Resolving patch:
diff --git a/skimage/io/_plugins/fits_plugin.py b/skimage/io/_plugins/fits_plugin.py
--- a/skimage/io/_plugins/fits_plugin.py
+++ b/skimage/io/_plugins/fits_plugin.py
@@ -3,15 +3,12 @@
 import skimage.io as io
 
 try:
-    from astropy.io import fits as pyfits
+    from astropy.io import fits
 except ImportError:
-    try:
-        import pyfits
-    except ImportError:
-        raise ImportError(
-            "PyFITS could not be found. Please refer to\n"
-            "http://www.stsci.edu/resources/software_hardware/pyfits\n"
-            "for further instructions.")
+    raise ImportError(
+        "Astropy could not be found. It is needed to read FITS files.\n"
+        "Please refer to http://www.astropy.org for installation\n"
+        "instructions.")
 
 
 def imread(fname, dtype=None):
@@ -44,14 +41,14 @@ def imread(fname, dtype=None):
 
     """
 
-    hdulist = pyfits.open(fname)
+    hdulist = fits.open(fname)
 
     # Iterate over FITS image extensions, ignoring any other extension types
     # such as binary tables, and get the first image data array:
     img_array = None
     for hdu in hdulist:
-        if isinstance(hdu, pyfits.ImageHDU) or \
-           isinstance(hdu, pyfits.PrimaryHDU):
+        if isinstance(hdu, fits.ImageHDU) or \
+           isinstance(hdu, fits.PrimaryHDU):
             if hdu.data is not None:
                 img_array = hdu.data
                 break
@@ -92,16 +89,16 @@ def imread_collection(load_pattern, conserve_memory=True):
     # files and finding the image extensions in each one:
     ext_list = []
     for filename in load_pattern:
-        hdulist = pyfits.open(filename)
+        hdulist = fits.open(filename)
         for n, hdu in zip(range(len(hdulist)), hdulist):
-            if isinstance(hdu, pyfits.ImageHDU) or \
-               isinstance(hdu, pyfits.PrimaryHDU):
+            if isinstance(hdu, fits.ImageHDU) or \
+               isinstance(hdu, fits.PrimaryHDU):
                 # Ignore (primary) header units with no data (use '.size'
                 # rather than '.data' to avoid actually loading the image):
                 try:
+                    data_size = hdu.size  # size is int in Astropy 3.1.2
+                except TypeError:
                     data_size = hdu.size()
-                except TypeError:  # (size changed to int in PyFITS 3.1)
-                    data_size = hdu.size
                 if data_size > 0:
                     ext_list.append((filename, n))
         hdulist.close()
@@ -138,7 +135,7 @@ def FITSFactory(image_ext):
     if type(filename) is not str or type(extnum) is not int:
         raise ValueError("Expected a (filename, extension) tuple")
 
-    hdulist = pyfits.open(filename)
+    hdulist = fits.open(filename)
 
     data = hdulist[extnum].data
 


Test patch:
diff --git a/skimage/io/tests/test_fits.py b/skimage/io/tests/test_fits.py
--- a/skimage/io/tests/test_fits.py
+++ b/skimage/io/tests/test_fits.py
@@ -4,54 +4,39 @@
 from skimage import data_dir
 from skimage._shared import testing
 
-
-pyfits_available = True
-
-try:
-    from astropy.io import fits as pyfits
-except ImportError:
-    try:
-        import pyfits
-    except ImportError:
-        pyfits_available = False
-
-if pyfits_available:
-    import skimage.io._plugins.fits_plugin as fplug
+testing.pytest.importorskip('astropy')
+from astropy.io import fits
+import skimage.io._plugins.fits_plugin as fplug
 
 
 def test_fits_plugin_import():
-    # Make sure we get an import exception if PyFITS isn't there
+    # Make sure we get an import exception if Astropy isn't there
     # (not sure how useful this is, but it ensures there isn't some other
     # error when trying to load the plugin)
     try:
         io.use_plugin('fits')
     except ImportError:
-        assert not pyfits_available
-    else:
-        assert pyfits_available
+        raise()
 
 
 def teardown():
     io.reset_plugins()
 
 
-@testing.skipif(not pyfits_available, reason="pyfits not installed")
 def test_imread_MEF():
     io.use_plugin('fits')
     testfile = os.path.join(data_dir, 'multi.fits')
     img = io.imread(testfile)
-    assert np.all(img == pyfits.getdata(testfile, 1))
+    assert np.all(img == fits.getdata(testfile, 1))
 
 
-@testing.skipif(not pyfits_available, reason="pyfits not installed")
 def test_imread_simple():
     io.use_plugin('fits')
     testfile = os.path.join(data_dir, 'simple.fits')
     img = io.imread(testfile)
-    assert np.all(img == pyfits.getdata(testfile, 0))
+    assert np.all(img == fits.getdata(testfile, 0))
 
 
-@testing.skipif(not pyfits_available, reason="pyfits not installed")
 def test_imread_collection_single_MEF():
     io.use_plugin('fits')
     testfile = os.path.join(data_dir, 'multi.fits')
@@ -62,7 +47,6 @@ def test_imread_collection_single_MEF():
     assert _same_ImageCollection(ic1, ic2)
 
 
-@testing.skipif(not pyfits_available, reason="pyfits not installed")
 def test_imread_collection_MEF_and_simple():
     io.use_plugin('fits')
     testfile1 = os.path.join(data_dir, 'multi.fits')