Repository: openmrslab/suspect

Issue:
Slice spectrum
It should be possible to generate a slice object for a specified frequency range from an MRSSpectrum object, which can be used to extract specific regions of a spectrum (or set of spectra).

Discussion:

Patch:
diff --git a/suspect/mrsobjects.py b/suspect/mrsobjects.py
index 7fb4764..3785dc1 100644
--- a/suspect/mrsobjects.py
+++ b/suspect/mrsobjects.py
@@ -324,3 +324,46 @@ class MRSSpectrum(MRSBase):
         suspect.adjust_frequency : equivalent function
         """
         return self.fid().adjust_frequency(frequency_shift).spectrum()
+
+    def slice_hz(self, lower_bound, upper_bound):
+        """
+        Creates a slice object to access the region of the spectrum between
+        the specified bounds, in Hertz.
+        
+        Parameters
+        ----------
+        lower_bound : float
+            The lower frequency bound of the region, in Hertz.
+        upper_bound : float
+            The upper frequency bound of the region, in Hertz.
+        
+        Returns
+        -------
+        out : Slice
+        """
+        lower_index = numpy.floor((lower_bound + self.sw / 2) / self.df)
+        upper_index = numpy.ceil((upper_bound + self.sw / 2) / self.df)
+        if lower_index < 0:
+            raise ValueError("Could not create a slice for lower bound {}, value is outside range".format(lower_bound))
+        if upper_index < 0:
+            raise ValueError("Could not create a slice for upper bound {}, value is outside range".format(upper_bound))
+        return slice(int(lower_index), int(upper_index))
+
+    def slice_ppm(self, lower_bound, upper_bound):
+        """
+        Creates a slice object to access the region of the spectrum between
+        the specified bounds, in PPM.
+
+        Parameters
+        ----------
+        lower_bound : float
+            The lower frequency bound of the region, in PPM.
+        upper_bound : float
+            The upper frequency bound of the region, in PPM.
+
+        Returns
+        -------
+        out : Slice
+        """
+        return self.slice_hz(self.ppm_to_hertz(lower_bound),
+                             self.ppm_to_hertz(upper_bound))


Test patch:
diff --git a/tests/test_mrs/test_core.py b/tests/test_mrs/test_core.py
index 97a9f0e..2ea638e 100644
--- a/tests/test_mrs/test_core.py
+++ b/tests/test_mrs/test_core.py
@@ -1,6 +1,7 @@
 import suspect
 
 import numpy
+import pytest
 
 
 def test_adjust_zero_phase():
@@ -15,3 +16,23 @@ def test_adjust_first_phase():
     numpy.testing.assert_almost_equal(phased_data[0], -1j)
     numpy.testing.assert_almost_equal(phased_data[-1], numpy.exp(1j * 0.4 * numpy.pi))
     numpy.testing.assert_almost_equal(phased_data[5], 1)
+
+
+def test_slice_hz():
+    data = suspect.MRSData(numpy.ones(1024), 1e-3, 123)
+    spectrum = data.spectrum()
+    whole_slice = spectrum.slice_hz(-500, 500)
+    assert whole_slice == slice(0, 1024)
+    restricted_slice = spectrum.slice_hz(-100, 200)
+    assert restricted_slice == slice(409, 717)
+    with pytest.raises(ValueError):
+        too_large_slice = spectrum.slice_hz(-1000, 1000)
+
+
+def test_slice_ppm():
+    data = suspect.MRSData(numpy.ones(1000), 1e-3, 123)
+    spectrum = data.spectrum()
+    a_slice = spectrum.slice_ppm(5.7, 3.7)
+    assert a_slice == slice(377, 623)
+    reversed_slice = spectrum.slice_ppm(3.7, 5.7)
+    assert a_slice == slice(377, 623)