Repository: lightkurve/lightkurve
Issue: NaN times are possible for certain quality masks.

I see NaN times when I use a quality_bitmask=None:

```python
tpf = KeplerTargetPixelFile.from_archive(201572338, quality_bitmask=None)
nan_times = tpf.time != tpf.time
nan_times.sum()

145
```


Many of these NaN times have quality values of 98304, which indicates *'No fine point', 'No data'*.
The possibility of NaN times is not necessarily a bug, and will likely only occur when quality_bitmask=None, since these quality flags are masked by default.  However, their presence does raise the question of whether we want to build in resilience to the possibility of NaN times.  They *do* have cadence numbers.

This question arose while designing `tpf.interact()`, which has so-far safely assumed times are all finite, but gets broken when NaN times are present.  I suspect it affects other places in the code that assume finite times.

Changed files:
lightkurve/tests/test_targetpixelfile.py, lightkurve/utils.py, lightkurve/prf.py

diff --git a/lightkurve/prf.py b/lightkurve/prf.py
index 1927e808..463c7aff 100644
--- a/lightkurve/prf.py
+++ b/lightkurve/prf.py
@@ -20,6 +20,7 @@ from .utils import channel_to_module_output, plot_image
 # signature function.
 if sys.version_info[0] == 2:
     from inspect import getargspec
+
     def _get_number_of_arguments(func):
         list_of_args = getargspec(func).args
         if 'self' in list_of_args:
@@ -28,6 +29,7 @@ if sys.version_info[0] == 2:
             return len(list_of_args)
 else:
     from inspect import signature
+
     def _get_number_of_arguments(func):
         return len(signature(func).parameters)
 
@@ -35,6 +37,7 @@ else:
 __all__ = ['KeplerPRF', 'PRFPhotometry', 'SceneModel', 'SimpleKeplerPRF',
            'get_initial_guesses']
 
+
 class KeplerPRF(object):
     """
     Kepler's Pixel Response Function as designed by [1]_.
@@ -160,7 +163,8 @@ class KeplerPRF(object):
         cdelt2p = np.zeros(n_hdu, dtype='float32')
 
         for i in range(n_hdu):
-            prfn[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i] = self._read_prf_calibration_file(prffile, i+1)
+            prfn[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i] = self._read_prf_calibration_file(
+                prffile, i+1)
 
         prfn = np.array(prfn)
         PRFcol = np.arange(0.5, np.shape(prfn[0])[1] + 0.5)
@@ -199,6 +203,7 @@ class KeplerPRF(object):
                    extent=(self.column, self.column + self.shape[1],
                            self.row, self.row + self.shape[0]), **kwargs)
 
+
 class PRFPhotometry(object):
     """
     This class performs PRF Photometry on TPF-like files.
@@ -458,9 +463,10 @@ def get_initial_guesses(data, ref_col, ref_row):
     row0 = np.nansum(yy * data) / flux0
     marg_col = data[:, int(np.round(col0 - ref_col))]
     marg_row = data[int(np.round(row0 - ref_row)), :]
-    sigma_y = math.sqrt(np.abs((np.arange(marg_row.size) - row0) ** 2 * marg_row).sum() / marg_row.sum())
-    sigma_x = math.sqrt(np.abs((np.arange(marg_col.size) - col0) ** 2 * marg_col).sum() / marg_col.sum())
+    sigma_y = math.sqrt(np.abs((np.arange(marg_row.size) - row0)
+                               ** 2 * marg_row).sum() / marg_row.sum())
+    sigma_x = math.sqrt(np.abs((np.arange(marg_col.size) - col0)
+                               ** 2 * marg_col).sum() / marg_col.sum())
     sigma0 = math.sqrt((sigma_x**2 + sigma_y**2)/2.0)
 
     return flux0, col0, row0, sigma0
-
diff --git a/lightkurve/tests/test_targetpixelfile.py b/lightkurve/tests/test_targetpixelfile.py
index 81826edc..ebab19f2 100644
--- a/lightkurve/tests/test_targetpixelfile.py
+++ b/lightkurve/tests/test_targetpixelfile.py
@@ -60,6 +60,7 @@ def test_tpf_zeros():
     # If you don't mask out bad data, time contains NaNs
     assert np.any(lc.time != tpf.time)  # Using the property that NaN does not equal NaN
     # When you do mask out bad data everything should work.
+    assert (tpf.timeobj.jd == 0).any()
     tpf = KeplerTargetPixelFile(filename_tpf_all_zeros, quality_bitmask='hard')
     lc = tpf.to_lightcurve()
     assert len(lc.time) == len(lc.flux)
@@ -91,9 +92,9 @@ def test_quality_flag_decoding():
         == [flags[3][1], flags[4][1], flags[5][1]]
 
 
-@pytest.mark.parametrize("quality_bitmask,answer",[('hardest', 1101),
-    ('hard', 1101), ('default', 1233), (None, 1290),
-    (1, 1290), (100, 1278), (2096639, 1101)])
+@pytest.mark.parametrize("quality_bitmask,answer", [('hardest', 1101),
+                                                    ('hard', 1101), ('default', 1233), (None, 1290),
+                                                    (1, 1290), (100, 1278), (2096639, 1101)])
 def test_bitmasking(quality_bitmask, answer):
     '''Test whether the bitmasking behaves like it should'''
     tpf = KeplerTargetPixelFile(filename_tpf_one_center, quality_bitmask=quality_bitmask)
@@ -121,7 +122,7 @@ def test_wcs_tabby():
     col -= tpf.column
     row -= tpf.row
     y, x = int(np.round(col[0])), int(np.round(row[1]))
-    #Compare with RA and Dec from Simbad
+    # Compare with RA and Dec from Simbad
     assert np.isclose(ra[x, y], 301.5643971, 1e-4)
     assert np.isclose(dec[x, y], 44.4568869, 1e-4)
 
@@ -196,6 +197,7 @@ def test_tpf_factory():
     assert(tpf.time[0] == 5)
     assert(tpf.time[9] == 95)
 
+
 def test_properties(capfd):
     '''Test if the describe function produces an output.
     The output is 1870 characters at the moment, but we might add more properties.'''
@@ -204,6 +206,7 @@ def test_properties(capfd):
     out, err = capfd.readouterr()
     assert len(out) > 1000
 
+
 def test_interact():
     """Test the Jupyter notebook interact() widget."""
     tpf = KeplerTargetPixelFile(filename_tpf_one_center)
diff --git a/lightkurve/utils.py b/lightkurve/utils.py
index 0189ec4f..8415b112 100644
--- a/lightkurve/utils.py
+++ b/lightkurve/utils.py
@@ -126,7 +126,7 @@ def channel_to_module_output(channel):
     if channel < 1 or channel > 88:
         raise ValueError("Channel number must be in the range 1-88.")
     lookup = _get_channel_lookup_array()
-    lookup[:,0] = 0
+    lookup[:, 0] = 0
     modout = np.where(lookup == channel)
     return (modout[0][0], modout[1][0])
 
@@ -158,33 +158,33 @@ def _get_channel_lookup_array():
     # In the array below, channel == array[module][output]
     # Note: modules 1, 5, 21, 25 are the FGS guide star CCDs.
     return np.array([
-       [0,     0,    0,    0,    0],
-       [1,    85,    0,    0,    0],
-       [2,     1,    2,    3,    4],
-       [3,     5,    6,    7,    8],
-       [4,     9,   10,   11,   12],
-       [5,    86,    0,    0,    0],
-       [6,    13,   14,   15,   16],
-       [7,    17,   18,   19,   20],
-       [8,    21,   22,   23,   24],
-       [9,    25,   26,   27,   28],
-       [10,   29,   30,   31,   32],
-       [11,   33,   34,   35,   36],
-       [12,   37,   38,   39,   40],
-       [13,   41,   42,   43,   44],
-       [14,   45,   46,   47,   48],
-       [15,   49,   50,   51,   52],
-       [16,   53,   54,   55,   56],
-       [17,   57,   58,   59,   60],
-       [18,   61,   62,   63,   64],
-       [19,   65,   66,   67,   68],
-       [20,   69,   70,   71,   72],
-       [21,   87,    0,    0,    0],
-       [22,   73,   74,   75,   76],
-       [23,   77,   78,   79,   80],
-       [24,   81,   82,   83,   84],
-       [25,   88,    0,    0,    0],
-       ])
+        [0,     0,    0,    0,    0],
+        [1,    85,    0,    0,    0],
+        [2,     1,    2,    3,    4],
+        [3,     5,    6,    7,    8],
+        [4,     9,   10,   11,   12],
+        [5,    86,    0,    0,    0],
+        [6,    13,   14,   15,   16],
+        [7,    17,   18,   19,   20],
+        [8,    21,   22,   23,   24],
+        [9,    25,   26,   27,   28],
+        [10,   29,   30,   31,   32],
+        [11,   33,   34,   35,   36],
+        [12,   37,   38,   39,   40],
+        [13,   41,   42,   43,   44],
+        [14,   45,   46,   47,   48],
+        [15,   49,   50,   51,   52],
+        [16,   53,   54,   55,   56],
+        [17,   57,   58,   59,   60],
+        [18,   61,   62,   63,   64],
+        [19,   65,   66,   67,   68],
+        [20,   69,   70,   71,   72],
+        [21,   87,    0,    0,    0],
+        [22,   73,   74,   75,   76],
+        [23,   77,   78,   79,   80],
+        [24,   81,   82,   83,   84],
+        [25,   88,    0,    0,    0],
+    ])
 
 
 def running_mean(data, window_size):
@@ -227,6 +227,7 @@ def bkjd_to_time(bkjd, timecorr, timslice, bjdref=2454833.):
     bjd = bkjd + bjdref
     jd = bjd - timecorr
     jd += (0.25 + 0.62 * (5 - timslice)) / 86400.
+    jd[~np.isfinite(jd)] = 0
     return Time(jd, format='jd')