Repository: StingraySoftware/stingray
Pull request #307 (2018-02-01 19:35:35)

warning about unequal bin sizes now works correctly when GTIs are loaded
Should fix issue #257, if I understood it correctly.


Patch:
diff --git a/stingray/gti.py b/stingray/gti.py
index 9cf38921..5a0cab84 100644
--- a/stingray/gti.py
+++ b/stingray/gti.py
@@ -148,6 +148,11 @@ def create_gti_mask(time, gtis, safe_interval=0, min_length=0,
     epsilon : float
         fraction of dt that is tolerated at the borders of a GTI
     """
+    if len(time) == 0:
+        raise ValueError("Passing an empty time array to create_gti_mask")
+    if len(gtis) == 0:
+        raise ValueError("Passing an empty GTI array to create_gti_mask")
+
     try:
         from numba import jit
     except ImportError:
@@ -156,6 +161,7 @@ def create_gti_mask(time, gtis, safe_interval=0, min_length=0,
                                         min_length=min_length,
                                         return_new_gtis=return_new_gtis,
                                         dt=dt, epsilon=epsilon)
+
     gtis = np.array(gtis, dtype=np.longdouble)
     check_gtis(gtis)
 
@@ -176,8 +182,8 @@ def create_gti_mask(time, gtis, safe_interval=0, min_length=0,
     # in order to simplify the calculation of the mask, but they will _not_
     # be returned.
     gtis_to_mask = copy.deepcopy(gtis_new)
-    gtis_to_mask[:, 0] = gtis_new[:, 0] - epsilon*dt + dt / 2
-    gtis_to_mask[:, 1] = gtis_new[:, 1] + epsilon*dt - dt / 2
+    gtis_to_mask[:, 0] = gtis_new[:, 0] - epsilon * dt + dt / 2
+    gtis_to_mask[:, 1] = gtis_new[:, 1] + epsilon * dt - dt / 2
 
     mask, gtimask = \
         create_gti_mask_jit((time - time[0]).astype(np.float64),
diff --git a/stingray/lightcurve.py b/stingray/lightcurve.py
index 91e37b84..501ca64a 100644
--- a/stingray/lightcurve.py
+++ b/stingray/lightcurve.py
@@ -180,10 +180,13 @@ class Lightcurve(object):
             np.asarray(assign_value_if_none(gti,
                                             [[self.tstart,
                                               self.tstart + self.tseg]]))
+
         check_gtis(self.gti)
-        good = create_gti_mask(self.time, self.gti)
+
+        good = create_gti_mask(self.time, self.gti, dt=self.dt)
 
         self.time = self.time[good]
+
         if input_counts:
             self.counts = np.asarray(counts)[good]
             self.countrate = self.counts / self.dt
@@ -201,7 +204,13 @@ class Lightcurve(object):
 
         # Issue a warning if the input time iterable isn't regularly spaced,
         # i.e. the bin sizes aren't equal throughout.
-        dt_array = np.diff(self.time)
+        dt_array = []
+        for g in self.gti:
+            mask = create_gti_mask(self.time, [g], dt=self.dt)
+            t = self.time[mask]
+            dt_array.extend(np.diff(t))
+        dt_array = np.asarray(dt_array)
+
         if not (np.allclose(dt_array, np.repeat(self.dt, dt_array.shape[0]))):
             simon("Bin sizes in input time array aren't equal throughout! "
                   "This could cause problems with Fourier transforms. "
@@ -247,8 +256,8 @@ class Lightcurve(object):
             raise ValueError("MJDref is different in the two light curves")
 
         common_gti = cross_two_gtis(self.gti, other.gti)
-        mask_self = create_gti_mask(self.time, common_gti)
-        mask_other = create_gti_mask(other.time, common_gti)
+        mask_self = create_gti_mask(self.time, common_gti, dt=self.dt)
+        mask_other = create_gti_mask(other.time, common_gti, dt=other.dt)
 
         # ValueError is raised by Numpy while asserting np.equal over arrays
         # with different dimensions.
@@ -411,6 +420,7 @@ class Lightcurve(object):
 
             new_counts = self.counts[start:stop:step]
             new_time = self.time[start:stop:step]
+
             new_gti = [[self.time[start] - 0.5 * self.dt,
                         self.time[stop - 1] + 0.5 * self.dt]]
             new_gti = np.asarray(new_gti)
@@ -420,8 +430,9 @@ class Lightcurve(object):
                 new_gti = cross_two_gtis(new_gti, new_gt1)
 
             new_gti = cross_two_gtis(self.gti, new_gti)
+
             return Lightcurve(new_time, new_counts, mjdref=self.mjdref,
-                              gti=new_gti)
+                              gti=new_gti, dt=self.dt)
         else:
             raise IndexError("The index must be either an integer or a slice "
                              "object !")
@@ -470,7 +481,7 @@ class Lightcurve(object):
         """
         baseline = np.zeros_like(self.time)
         for g in self.gti:
-            good = create_gti_mask(self.time, [g])
+            good = create_gti_mask(self.time, [g], dt=self.dt)
             _, baseline[good] = \
                 baseline_als(self.time[good], self.counts[good], lam, p,
                              niter, offset_correction=offset_correction,


Test patch:
diff --git a/stingray/tests/test_gti.py b/stingray/tests/test_gti.py
index b7b0eade..e7d2007d 100644
--- a/stingray/tests/test_gti.py
+++ b/stingray/tests/test_gti.py
@@ -59,6 +59,20 @@ class TestGTI(object):
         # bin at times 0, 2, 4 and 5 are not in.
         assert np.all(mask == np.array([0, 1, 0, 0, 0, 0, 0], dtype=bool))
 
+    def test_gti_mask_fails_empty_time(self):
+        arr = np.array([])
+        gti = np.array([[0, 2.1], [3.9, 5]])
+        with pytest.raises(ValueError) as excinfo:
+            create_gti_mask(arr, gti, return_new_gtis=True)
+        assert 'empty time array' in str(excinfo)
+
+    def test_gti_mask_fails_empty_gti(self):
+        arr = np.array([0, 1, 2, 3, 4, 5, 6])
+        gti = np.array([])
+        with pytest.raises(ValueError) as excinfo:
+            create_gti_mask(arr, gti, return_new_gtis=True)
+        assert 'empty GTI array' in str(excinfo)
+
     def test_gti_mask_complete(self):
         arr = np.array([0, 1, 2, 3, 4, 5, 6])
         gti = np.array([[0, 2.1], [3.9, 5]])
diff --git a/stingray/tests/test_lightcurve.py b/stingray/tests/test_lightcurve.py
index 8fbde0ee..ea7da9f4 100644
--- a/stingray/tests/test_lightcurve.py
+++ b/stingray/tests/test_lightcurve.py
@@ -439,7 +439,7 @@ class TestLightcurve(object):
         assert np.all(lc[::2].gti == [[0.5, 1.5], [2.5, 3.5]])
         assert np.all(lc[:].gti == lc.gti)
         assert lc[:].mjdref == lc.mjdref
-
+        assert lc[::2].n == 2
 
     def test_slicing_index_error(self):
         lc = Lightcurve(self.times, self.counts)