Repository: StingraySoftware/stingray
Pull request #302 (2018-01-25 09:51:26)

Support for Numpy integers and fixed slicing
In issue #299, I've discussed that Lightcurve does not support Numpy integers like `int64`. This is a simple fix for that.

Another issue is with slicing. If `new_lc = lc[:]` is run, the length of Lightcurve counts reduces by half. Since I am not an astronomer, I am not familiar with 'Good Time Intervals' and 'Time Resolution'. So I would need help to fix the second problem.

**Needs discussion**: If we could create a `copy()` function so that the package provides more options other than slicing.



Patch:
diff --git a/stingray/gti.py b/stingray/gti.py
index 25f91a9b..3b9d784b 100644
--- a/stingray/gti.py
+++ b/stingray/gti.py
@@ -324,9 +324,21 @@ def cross_two_gtis(gti0, gti1):
     --------
     cross_gtis : From multiple GTI lists, extract common intervals *EXACTLY*
 
+    Examples
+    --------
+    >>> gti1 = np.array([[1, 2]])
+    >>> gti2 = np.array([[1, 2]])
+    >>> newgti = cross_gtis([gti1, gti2])
+    >>> np.all(newgti == [[1, 2]])
+    True
+    >>> gti1 = np.array([[1, 4]])
+    >>> gti2 = np.array([[1, 2], [2, 4]])
+    >>> newgti = cross_gtis([gti1, gti2])
+    >>> np.all(newgti == [[1, 4]])
+    True
     """
-    gti0 = np.asarray(gti0)
-    gti1 = np.asarray(gti1)
+    gti0 = join_equal_gti_boundaries(np.asarray(gti0))
+    gti1 = join_equal_gti_boundaries(np.asarray(gti1))
     # Check GTIs
     check_gtis(gti0)
     check_gtis(gti1)
@@ -504,9 +516,31 @@ def check_separate(gti0, gti1):
         return False
 
 
+def join_equal_gti_boundaries(gti):
+    """If the start of a GTI is right at the end of another, join them.
+
+    """
+    new_gtis = gti
+    touching = gti[:-1, 1] == gti[1:, 0]
+    if np.any(touching):
+        ng = []
+        count = 0
+        while count < len(gti) - 1:
+            if new_gtis[count, 1] == gti[count + 1, 0]:
+                ng.append([gti[count, 0], gti[count + 1, 1]])
+            else:
+                ng.append(gti[count])
+            count += 1
+        new_gtis = np.asarray(ng)
+    return new_gtis
+
+
 def append_gtis(gti0, gti1):
     """Union of two non-overlapping GTIs.
 
+    If the two GTIs "touch", this is tolerated and the touching GTIs are
+    joined in a single one.
+
     Parameters
     ----------
     gti0: 2-d float array
@@ -519,6 +553,13 @@ def append_gtis(gti0, gti1):
     -------
     gti: 2-d float array
         The newly created GTI
+
+    Examples
+    --------
+    >>> np.all(append_gtis([[0, 1]], [[2, 3]]) == [[0, 1], [2, 3]])
+    True
+    >>> np.all(append_gtis([[0, 1]], [[1, 3]]) == [[0, 3]])
+    True
     """
 
     gti0 = np.asarray(gti0)
@@ -533,7 +574,9 @@ def append_gtis(gti0, gti1):
         raise ValueError('In order to append, GTIs must be mutually'
             'exclusive.')
 
-    return np.concatenate([gti0, gti1])
+    new_gtis = np.sort(np.concatenate([gti0, gti1]))
+
+    return join_equal_gti_boundaries(new_gtis)
 
 
 def join_gtis(gti0, gti1):
diff --git a/stingray/lightcurve.py b/stingray/lightcurve.py
index 501ca64a..0ccfc638 100644
--- a/stingray/lightcurve.py
+++ b/stingray/lightcurve.py
@@ -411,7 +411,7 @@ class Lightcurve(object):
         >>> lc[:2].counts
         array([11, 22])
         """
-        if isinstance(index, int):
+        if isinstance(index, (int, np.integer)):
             return self.counts[index]
         elif isinstance(index, slice):
             start = assign_value_if_none(index.start, 0)
@@ -428,7 +428,6 @@ class Lightcurve(object):
                 new_gt1 = np.array(list(zip(new_time - self.dt / 2,
                                             new_time + self.dt / 2)))
                 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,


Test patch:
diff --git a/stingray/tests/test_lightcurve.py b/stingray/tests/test_lightcurve.py
index ea7da9f4..7c10e6d1 100644
--- a/stingray/tests/test_lightcurve.py
+++ b/stingray/tests/test_lightcurve.py
@@ -447,6 +447,13 @@ class TestLightcurve(object):
         with pytest.raises(StingrayError):
             lc_new = lc[1:2]
 
+    def test_index(self):
+        lc = Lightcurve(self.times, self.counts)
+
+        index = 1
+        index_np32, index_np64 = np.int32(index), np.int64(index)
+        assert lc[index] == lc[index_np32] == lc[index_np64]
+
     def test_join_with_different_dt(self):
         _times = [5, 5.5, 6]
         _counts = [2, 2, 2]
@@ -574,6 +581,16 @@ class TestLightcurve(object):
         assert np.all(lc.time == np.array([1, 3, 2, 4]))
         assert lc.mjdref == mjdref
 
+    def test_sort_reverse(self):
+        times = np.arange(1000)
+        counts = np.random.rand(1000)*100
+        lc = Lightcurve(times, counts)
+        lc_1 = lc
+        lc_2 = Lightcurve(np.arange(1000, 2000), np.random.rand(1000)*1000)
+        lc_long = lc_1.join(lc_2)  # Or vice-versa
+        new_lc_long = lc_long[:]  # Copying into a new object
+        assert new_lc_long.n == lc_long.n
+
     def test_plot_matplotlib_not_installed(self):
         try:
             import matplotlib.pyplot as plt