Repository: NeuralEnsemble/python-neo

Issue:
Slicing `AnalogSignal` with numpy.int64 gives an incorrect result
Example:
```python
>>> signal[:, 0].shape
(1000, 1)
>>> signal[:, np.int64(0)].shape
(1000,)
```


Discussion:

Patch:
diff --git a/neo/core/analogsignal.py b/neo/core/analogsignal.py
index 8e129a52..aa971c80 100644
--- a/neo/core/analogsignal.py
+++ b/neo/core/analogsignal.py
@@ -285,11 +285,11 @@ class AnalogSignal(BaseNeo, pq.Quantity):
         Get the item or slice :attr:`i`.
         '''
         obj = super(AnalogSignal, self).__getitem__(i)
-        if isinstance(i, int):  # a single point in time across all channels
+        if isinstance(i, (int, np.integer)):  # a single point in time across all channels
             obj = pq.Quantity(obj.magnitude, units=obj.units)
         elif isinstance(i, tuple):
             j, k = i
-            if isinstance(j, int):  # extract a quantity array
+            if isinstance(j, (int, np.integer)):  # extract a quantity array
                 obj = pq.Quantity(obj.magnitude, units=obj.units)
             else:
                 if isinstance(j, slice):
@@ -303,7 +303,7 @@ class AnalogSignal(BaseNeo, pq.Quantity):
                     # in the general case, would need to return IrregularlySampledSignal(Array)
                 else:
                     raise TypeError("%s not supported" % type(j))
-                if isinstance(k, int):
+                if isinstance(k, (int, np.integer)):
                     obj = obj.reshape(-1, 1)
                 if self.channel_index:
                     obj.channel_index = self.channel_index.__getitem__(k)
diff --git a/neo/core/irregularlysampledsignal.py b/neo/core/irregularlysampledsignal.py
index b37034fc..045fb24a 100644
--- a/neo/core/irregularlysampledsignal.py
+++ b/neo/core/irregularlysampledsignal.py
@@ -225,11 +225,11 @@ class IrregularlySampledSignal(BaseNeo, pq.Quantity):
         Get the item or slice :attr:`i`.
         '''
         obj = super(IrregularlySampledSignal, self).__getitem__(i)
-        if isinstance(i, int):  # a single point in time across all channels
+        if isinstance(i, (int, np.integer)):  # a single point in time across all channels
             obj = pq.Quantity(obj.magnitude, units=obj.units)
         elif isinstance(i, tuple):
             j, k = i
-            if isinstance(j, int):  # a single point in time across some channels
+            if isinstance(j, (int, np.integer)):  # a single point in time across some channels
                 obj = pq.Quantity(obj.magnitude, units=obj.units)
             else:
                 if isinstance(j, slice):
@@ -238,7 +238,7 @@ class IrregularlySampledSignal(BaseNeo, pq.Quantity):
                     raise NotImplementedError("Arrays not yet supported")
                 else:
                     raise TypeError("%s not supported" % type(j))
-                if isinstance(k, int):
+                if isinstance(k, (int, np.integer)):
                     obj = obj.reshape(-1, 1)
         elif isinstance(i, slice):
             obj.times = self.times.__getitem__(i)


Test patch:
diff --git a/neo/test/coretest/test_analogsignal.py b/neo/test/coretest/test_analogsignal.py
index 0053e566..4b769fe3 100644
--- a/neo/test/coretest/test_analogsignal.py
+++ b/neo/test/coretest/test_analogsignal.py
@@ -313,28 +313,29 @@ class TestAnalogSignalArrayMethods(unittest.TestCase):
 
     def test__slice_should_return_AnalogSignalArray(self):
         # slice
-        result = self.signal1[3:8, 0]
-        self.assertIsInstance(result, AnalogSignal)
-        assert_neo_object_is_compliant(result)
-        self.assertEqual(result.name, 'spam')         # should slicing really preserve name and description?
-        self.assertEqual(result.description, 'eggs')  # perhaps these should be modified to indicate the slice?
-        self.assertEqual(result.file_origin, 'testfile.txt')
-        self.assertEqual(result.annotations, {'arg1': 'test'})
-
-        self.assertEqual(result.size, 5)
-        self.assertEqual(result.sampling_period, self.signal1.sampling_period)
-        self.assertEqual(result.sampling_rate, self.signal1.sampling_rate)
-        self.assertEqual(result.t_start,
-                         self.signal1.t_start+3*result.sampling_period)
-        self.assertEqual(result.t_stop,
-                         result.t_start + 5*result.sampling_period)
-        assert_array_equal(result.magnitude, self.data1[3:8].reshape(-1, 1))
-
-        # Test other attributes were copied over (in this case, defaults)
-        self.assertEqual(result.file_origin, self.signal1.file_origin)
-        self.assertEqual(result.name, self.signal1.name)
-        self.assertEqual(result.description, self.signal1.description)
-        self.assertEqual(result.annotations, self.signal1.annotations)
+        for index in (0, np.int64(0)):
+            result = self.signal1[3:8, index]
+            self.assertIsInstance(result, AnalogSignal)
+            assert_neo_object_is_compliant(result)
+            self.assertEqual(result.name, 'spam')         # should slicing really preserve name and description?
+            self.assertEqual(result.description, 'eggs')  # perhaps these should be modified to indicate the slice?
+            self.assertEqual(result.file_origin, 'testfile.txt')
+            self.assertEqual(result.annotations, {'arg1': 'test'})
+
+            self.assertEqual(result.size, 5)
+            self.assertEqual(result.sampling_period, self.signal1.sampling_period)
+            self.assertEqual(result.sampling_rate, self.signal1.sampling_rate)
+            self.assertEqual(result.t_start,
+                             self.signal1.t_start+3*result.sampling_period)
+            self.assertEqual(result.t_stop,
+                             result.t_start + 5*result.sampling_period)
+            assert_array_equal(result.magnitude, self.data1[3:8].reshape(-1, 1))
+
+            # Test other attributes were copied over (in this case, defaults)
+            self.assertEqual(result.file_origin, self.signal1.file_origin)
+            self.assertEqual(result.name, self.signal1.name)
+            self.assertEqual(result.description, self.signal1.description)
+            self.assertEqual(result.annotations, self.signal1.annotations)
 
     def test__slice_should_let_access_to_parents_objects(self):
         result =  self.signal1.time_slice(1*pq.ms,3*pq.ms)