diff --git a/CHANGELOG.md b/CHANGELOG.md
index 46e2f1831f9ea38f7340440a7b0cabec28957749..0dba60a7e1d94b6f93bfc100099916541d209e83 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ Changes currently on master, but not under a tag.
 - Added method to result to get injection recovery credible levels
 - Added function to generate a pp-plot from many results to core/result.py
 - Fixed a bug which caused `Interferometer.detector_tensor` not to update when `latitude`, `longitude`, `xarm_azimuth`, `yarm_azimuth`, `xarm_tilt`, `yarm_tilt` were updated.
+- Extracted time and frequency series behaviour from `WaveformGenerator` and `InterferometerStrainData` and moved it to `series.gw.CoupledTimeAndFrequencySeries`
 
 ### Changes
 - Switch the ordering the key-word arguments in `result.read_in_result` to put
diff --git a/bilby/gw/likelihood.py b/bilby/gw/likelihood.py
index 582d8a9dac7842a493be817c0d3b251e510facee..70c5fa6b12dd2d384b96ed5bbfcdccb8aec61c58 100644
--- a/bilby/gw/likelihood.py
+++ b/bilby/gw/likelihood.py
@@ -284,7 +284,7 @@ class GravitationalWaveTransient(likelihood.Likelihood):
             self.interferometers.start_time + np.linspace(
                 0, self.interferometers.duration,
                 int(self.interferometers.duration / 2 *
-                    self.waveform_generator.sampling_frequency))[1:]
+                    self.waveform_generator.sampling_frequency + 1))[1:]
         self.time_prior_array =\
             self.priors['geocent_time'].prob(times) * delta_tc
 
diff --git a/bilby/gw/series.py b/bilby/gw/series.py
index aab94dee94d96db575af6ae6ee42c7b719250f7b..a83a0a658bce8dcc1f2351f9dcfe0f25a82f4c01 100644
--- a/bilby/gw/series.py
+++ b/bilby/gw/series.py
@@ -20,6 +20,12 @@ class CoupledTimeAndFrequencySeries(object):
         self.start_time = start_time
         self._frequency_array_updated = False
         self._time_array_updated = False
+        self._frequency_array = None
+        self._time_array = None
+
+    def __repr__(self):
+        return self.__class__.__name__ + '(duration={}, sampling_frequency={}, start_time={})'\
+            .format(self.duration, self.sampling_frequency, self.start_time)
 
     @property
     def frequency_array(self):
@@ -31,7 +37,7 @@ class CoupledTimeAndFrequencySeries(object):
         """
         if self._frequency_array_updated is False:
             if self.sampling_frequency and self.duration:
-                self.frequency_array = utils.create_frequency_series(
+                self._frequency_array = utils.create_frequency_series(
                     sampling_frequency=self.sampling_frequency,
                     duration=self.duration)
             else:
diff --git a/bilby/gw/waveform_generator.py b/bilby/gw/waveform_generator.py
index 05dbeff99d1c93b2d1ca1cb6858096fdd84f64b5..6e9a5f6a79a698ec963062529b9bb02177df4874 100644
--- a/bilby/gw/waveform_generator.py
+++ b/bilby/gw/waveform_generator.py
@@ -168,7 +168,7 @@ class WaveformGenerator(object):
         model_strain = dict()
         for key in transformed_model_strain:
             if transformation_function == utils.nfft:
-                model_strain[key], self.frequency_array = \
+                model_strain[key], _ = \
                     transformation_function(transformed_model_strain[key], self.sampling_frequency)
             else:
                 model_strain[key] = transformation_function(transformed_model_strain[key], self.sampling_frequency)
diff --git a/test/detector_test.py b/test/detector_test.py
index 2edbeca291d208d339e131d3c3ec278ba0dce809..028e1d33f6e16eb69c5965663a6a2e817a619fc7 100644
--- a/test/detector_test.py
+++ b/test/detector_test.py
@@ -518,42 +518,6 @@ class TestInterferometerStrainData(unittest.TestCase):
                 frequency_domain_strain=np.array([0, 1, 2]), frequency_array=np.array([5, 15, 25]))
             self.assertTrue(np.array_equal(self.ifosd.frequency_mask, [False, True, False]))
 
-    def test_frequency_array_setting_direct(self):
-        with mock.patch('bilby.core.utils.create_frequency_series') as m:
-            m.return_value = np.array([5, 15, 25])
-            self.ifosd.set_from_frequency_domain_strain(
-                frequency_domain_strain=np.array([0, 1, 2]), frequency_array=np.array([5, 15, 25]))
-            self.assertTrue(np.array_equal(self.ifosd.frequency_array, np.array(np.array([5, 15, 25]))))
-
-    def test_duration_setting(self):
-        with mock.patch('bilby.core.utils.create_frequency_series') as m:
-            m.return_value = np.array([0, 1, 2])
-            self.ifosd.set_from_frequency_domain_strain(
-                frequency_domain_strain=np.array([0, 1, 2]), frequency_array=np.array([0, 1, 2]))
-            self.assertAlmostEqual(self.ifosd.duration, 1)
-
-    def test_sampling_frequency_setting(self):
-        with mock.patch('bilby.core.utils.create_frequency_series') as n:
-            with mock.patch('bilby.core.utils.get_sampling_frequency_and_duration_from_frequency_array') as m:
-                m.return_value = 8, 456
-                n.return_value = np.array([1, 2, 3])
-                self.ifosd.set_from_frequency_domain_strain(
-                    frequency_domain_strain=np.array([0, 1, 2]), frequency_array=np.array([0, 1, 2]))
-                self.assertEqual(8, self.ifosd.sampling_frequency)
-
-    def test_frequency_array_setting(self):
-        duration = 3
-        sampling_frequency = 1
-        with mock.patch('bilby.core.utils.create_frequency_series') as m:
-            m.return_value = [1, 2, 3]
-            self.ifosd.set_from_frequency_domain_strain(
-                frequency_domain_strain=np.array([0, 1, 2]), duration=duration,
-                sampling_frequency=sampling_frequency)
-            self.assertTrue(np.array_equal(
-                self.ifosd.frequency_array,
-                bilby.core.utils.create_frequency_series(duration=duration,
-                                                         sampling_frequency=sampling_frequency)))
-
     def test_set_data_fails(self):
         with mock.patch('bilby.core.utils.create_frequency_series') as m:
             m.return_value = [1, 2, 3]
@@ -606,60 +570,6 @@ class TestInterferometerStrainData(unittest.TestCase):
         self.assertTrue(np.all(
             self.ifosd.frequency_domain_strain == frequency_domain_strain * self.ifosd.frequency_mask))
 
-    def test_time_array_when_set(self):
-        test_array = np.array([1, 2, 3])
-        self.ifosd.time_array = test_array
-        self.assertTrue(np.array_equal(test_array, self.ifosd.time_array))
-
-    def test_time_array_when_not_set(self):
-        with mock.patch('bilby.core.utils.create_time_series') as m:
-            self.ifosd.start_time = 3
-            self.ifosd.sampling_frequency = 1000
-            self.ifosd.duration = 5
-            m.return_value = 4
-            self.assertEqual(m.return_value, self.ifosd.time_array)
-            m.assert_called_with(sampling_frequency=1000,
-                                 duration=5,
-                                 starting_time=3)
-
-    def test_time_array_without_sampling_frequency(self):
-        self.ifosd.sampling_frequency = None
-        self.ifosd.duration = 4
-        with self.assertRaises(ValueError):
-            test = self.ifosd.time_array
-
-    def test_time_array_without_duration(self):
-        self.ifosd.sampling_frequency = 4096
-        self.ifosd.duration = None
-        with self.assertRaises(ValueError):
-            test = self.ifosd.time_array
-
-    def test_frequency_array_when_set(self):
-        test_array = np.array([1, 2, 3])
-        self.ifosd.frequency_array = test_array
-        self.assertTrue(np.array_equal(test_array, self.ifosd.frequency_array))
-
-    def test_frequency_array_when_not_set(self):
-        with mock.patch('bilby.core.utils.create_frequency_series') as m:
-            m.return_value = [1, 2, 3]
-            self.ifosd.sampling_frequency = 1000
-            self.ifosd.duration = 5
-            self.assertListEqual(m.return_value, self.ifosd.frequency_array)
-            m.assert_called_with(sampling_frequency=1000,
-                                 duration=5)
-
-    def test_frequency_array_without_sampling_frequency(self):
-        self.ifosd.sampling_frequency = None
-        self.ifosd.duration = 4
-        with self.assertRaises(ValueError):
-            test = self.ifosd.frequency_array
-
-    def test_frequency_array_without_duration(self):
-        self.ifosd.sampling_frequency = 4096
-        self.ifosd.duration = None
-        with self.assertRaises(ValueError):
-            test = self.ifosd.frequency_array
-
     def test_time_within_data_before(self):
         self.ifosd.start_time = 3
         self.ifosd.duration = 2
diff --git a/test/series_test.py b/test/series_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..685164abf6f11192f77a089582bfb07571fc8d55
--- /dev/null
+++ b/test/series_test.py
@@ -0,0 +1,102 @@
+from __future__ import absolute_import
+import unittest
+import bilby
+import numpy as np
+
+
+class TestCoupledTimeAndFrequencySeries(unittest.TestCase):
+
+    def setUp(self):
+        self.duration = 2
+        self.sampling_frequency = 4096
+        self.start_time = -1
+        self.series = bilby.gw.series.CoupledTimeAndFrequencySeries(duration=self.duration,
+                                                                    sampling_frequency=self.sampling_frequency,
+                                                                    start_time=self.start_time)
+
+    def tearDown(self):
+        del self.duration
+        del self.sampling_frequency
+        del self.start_time
+        del self.series
+
+    def test_repr(self):
+        expected = 'CoupledTimeAndFrequencySeries(duration={}, sampling_frequency={}, start_time={})'\
+            .format(self.series.duration,
+                    self.series.sampling_frequency,
+                    self.series.start_time)
+        self.assertEqual(expected, repr(self.series))
+
+    def test_duration_from_init(self):
+        self.assertEqual(self.duration, self.series.duration)
+
+    def test_sampling_from_init(self):
+        self.assertEqual(self.sampling_frequency, self.series.sampling_frequency)
+
+    def test_start_time_from_init(self):
+        self.assertEqual(self.start_time, self.series.start_time)
+
+    def test_frequency_array_type(self):
+        self.assertIsInstance(self.series.frequency_array, np.ndarray)
+
+    def test_time_array_type(self):
+        self.assertIsInstance(self.series.time_array, np.ndarray)
+
+    def test_frequency_array_from_init(self):
+        expected = bilby.core.utils.create_frequency_series(sampling_frequency=self.sampling_frequency,
+                                                            duration=self.duration)
+        self.assertTrue(np.array_equal(expected, self.series.frequency_array))
+
+    def test_time_array_from_init(self):
+        expected = bilby.core.utils.create_time_series(sampling_frequency=self.sampling_frequency,
+                                                       duration=self.duration,
+                                                       starting_time=self.start_time)
+        self.assertTrue(np.array_equal(expected, self.series.time_array))
+
+    def test_frequency_array_setter(self):
+        new_sampling_frequency = 100
+        new_duration = 3
+        new_frequency_array = bilby.core.utils.create_frequency_series(sampling_frequency=new_sampling_frequency,
+                                                                       duration=new_duration)
+        self.series.frequency_array = new_frequency_array
+        self.assertTrue(np.array_equal(new_frequency_array, self.series.frequency_array))
+        self.assertLessEqual(np.abs(new_sampling_frequency - self.series.sampling_frequency), 1)
+        self.assertAlmostEqual(new_duration, self.series.duration)
+        self.assertAlmostEqual(self.start_time, self.series.start_time)
+
+    def test_time_array_setter(self):
+        new_sampling_frequency = 100
+        new_duration = 3
+        new_start_time = 4
+        new_time_array = bilby.core.utils.create_time_series(sampling_frequency=new_sampling_frequency,
+                                                             duration=new_duration,
+                                                             starting_time=new_start_time)
+        self.series.time_array = new_time_array
+        self.assertTrue(np.array_equal(new_time_array, self.series.time_array))
+        self.assertAlmostEqual(new_sampling_frequency, self.series.sampling_frequency, places=1)
+        self.assertAlmostEqual(new_duration, self.series.duration, places=1)
+        self.assertAlmostEqual(new_start_time, self.series.start_time, places=1)
+
+    def test_time_array_without_sampling_frequency(self):
+        self.series.sampling_frequency = None
+        self.series.duration = 4
+        with self.assertRaises(ValueError):
+            test = self.series.time_array
+
+    def test_time_array_without_duration(self):
+        self.series.sampling_frequency = 4096
+        self.series.duration = None
+        with self.assertRaises(ValueError):
+            test = self.series.time_array
+
+    def test_frequency_array_without_sampling_frequency(self):
+        self.series.sampling_frequency = None
+        self.series.duration = 4
+        with self.assertRaises(ValueError):
+            test = self.series.frequency_array
+
+    def test_frequency_array_without_duration(self):
+        self.series.sampling_frequency = 4096
+        self.series.duration = None
+        with self.assertRaises(ValueError):
+            test = self.series.frequency_array