diff --git a/lisainstrument/containers.py b/lisainstrument/containers.py
index e8c9679bc88adc76af82c7a5794f1863e8b180e1..f8fb9227db7f6ce0b3afdd49075ad47e1b29a170 100644
--- a/lisainstrument/containers.py
+++ b/lisainstrument/containers.py
@@ -137,6 +137,66 @@ class ForEachObject(abc.ABC):
             return self.dict == other
         return numpy.all([self[index] == other for index in self.indices()])
 
+    def __abs__(self):
+        return self.transformed(lambda index, value: abs(value))
+
+    def __neg__(self):
+        return self.transformed(lambda index, value: -value)
+
+    def __add__(self, other):
+        if numpy.isscalar(other):
+            return self.transformed(lambda _, value: value + other)
+        if isinstance(other, type(self)):
+            return self.transformed(lambda index, value: value + other[index])
+        raise TypeError(f"unsupported operand type for +: '{type(self)}' and '{type(other)}'")
+
+    def __radd__(self, other):
+        return self + other
+
+    def __sub__(self, other):
+        if numpy.isscalar(other):
+            return self.transformed(lambda _, value: value - other)
+        if isinstance(other, type(self)):
+            return self.transformed(lambda index, value: value - other[index])
+        raise TypeError(f"unsupported operand type for -: '{type(self)}' and '{type(other)}'")
+
+    def __rsub__(self, other):
+        return -(self - other)
+
+    def __mul__(self, other):
+        if numpy.isscalar(other):
+            return self.transformed(lambda _, value: value * other)
+        if isinstance(other, type(self)):
+            return self.transformed(lambda index, value: value * other[index])
+        raise TypeError(f"unsupported operand type for *: '{type(self)}' and '{type(other)}'")
+
+    def __rmul__(self, other):
+        return self * other
+
+    def __floordiv__(self, other):
+        if numpy.isscalar(other):
+            return self.transformed(lambda _, value: value // other)
+        if isinstance(other, type(self)):
+            return self.transformed(lambda index, value: value // other[index])
+        raise TypeError(f"unsupported operand type for //: '{type(self)}' and '{type(other)}'")
+
+    def __truediv__(self, other):
+        if numpy.isscalar(other):
+            return self.transformed(lambda _, value: value / other)
+        if isinstance(other, type(self)):
+            return self.transformed(lambda index, value: value / other[index])
+        raise TypeError(f"unsupported operand type for /: '{type(self)}' and '{type(other)}'")
+
+    def __rtruediv__(self, other):
+        if numpy.isscalar(other):
+            return self.transformed(lambda _, value: other / value)
+        raise TypeError(f"unsupported operand type for /: '{type(self)}' and '{type(other)}'")
+
+    def __pow__(self, other):
+        if numpy.isscalar(other):
+            return self.transformed(lambda _, value: value**other)
+        raise TypeError(f"unsupported operand type for **: '{type(self)}' and '{type(other)}'")
+
     def __repr__(self):
         return repr(self.dict)
 
@@ -149,14 +209,14 @@ class ForEachSC(ForEachObject):
         return ['1', '2', '3']
 
     @staticmethod
-    def distant_left(sc):
+    def distant_left_sc(sc):
         """Return index of distant rleftspacecraft."""
         if sc not in ForEachSC.indices():
             raise ValueError(f"invalid spacecraft index '{sc}'")
         return f'{int(sc) % 3 + 1}'
 
     @staticmethod
-    def distant_right(sc):
+    def distant_right_sc(sc):
         """Return index of distant right spacecraft."""
         if sc not in ForEachSC.indices():
             raise ValueError(f"invalid spacecraft index '{sc}'")
@@ -167,14 +227,43 @@ class ForEachSC(ForEachObject):
         """Return index of left MOSA."""
         if sc not in ForEachSC.indices():
             raise ValueError(f"invalid spacecraft index '{sc}'")
-        return f'{sc}{ForEachSC.distant_left(sc)}'
+        return f'{sc}{ForEachSC.distant_left_sc(sc)}'
 
     @staticmethod
     def right_mosa(sc):
         """Return index of right MOSA."""
         if sc not in ForEachSC.indices():
             raise ValueError(f"invalid spacecraft index '{sc}'")
-        return f'{sc}{ForEachSC.distant_right(sc)}'
+        return f'{sc}{ForEachSC.distant_right_sc(sc)}'
+
+    def for_each_mosa(self):
+        """Return a ForEachMOSA instance by sharing the spacecraft values on both MOSAs."""
+        return ForEachMOSA(lambda mosa: self[ForEachMOSA.sc(mosa)])
+
+    def __add__(self, other):
+        if isinstance(other, ForEachMOSA):
+            return self.for_each_mosa() + other
+        return super().__add__(other)
+
+    def __sub__(self, other):
+        if isinstance(other, ForEachMOSA):
+            return self.for_each_mosa() - other
+        return super().__sub__(other)
+
+    def __mul__(self, other):
+        if isinstance(other, ForEachMOSA):
+            return self.for_each_mosa() * other
+        return super().__mul__(other)
+
+    def __floordiv__(self, other):
+        if isinstance(other, ForEachMOSA):
+            return self.for_each_mosa() // other
+        return super().__floordiv__(other)
+
+    def __truediv__(self, other):
+        if isinstance(other, ForEachMOSA):
+            return self.for_each_mosa() / other
+        return super().__truediv__(other)
 
 
 class ForEachMOSA(ForEachObject):
@@ -184,20 +273,13 @@ class ForEachMOSA(ForEachObject):
     def indices(cls):
         return ['12', '23', '31', '13', '32', '21']
 
-    def __init__(self, values):
-        """Initialize from a `ForEachSC` instance or rely on super's implementation."""
-        if isinstance(values, ForEachSC):
-            super().__init__(lambda mosa: values[ForEachMOSA.sc(mosa)])
-        else:
-            super().__init__(values)
-
     @staticmethod
     def sc(mosa):
         """Return index of spacecraft hosting MOSA."""
         return f'{mosa[0]}'
 
     @staticmethod
-    def distant(mosa):
+    def distant_mosa(mosa):
         """Return index of distant MOSA.
 
         In practive, we invert the indices to swap emitter and receiver.
@@ -207,7 +289,7 @@ class ForEachMOSA(ForEachObject):
         return f'{mosa[1]}{mosa[0]}'
 
     @staticmethod
-    def adjacent(mosa):
+    def adjacent_mosa(mosa):
         """Return index of adjacent MOSA.
 
         In practice, we replace the second index by the only unused spacecraft index.
@@ -218,3 +300,36 @@ class ForEachMOSA(ForEachObject):
         if len(unused) != 1:
             raise RuntimeError(f"cannot find adjacent MOSA for '{mosa}'")
         return f'{mosa[0]}{unused[0]}'
+
+    def distant(self):
+        """Return a ForEachMOSA instance for distant MOSAs."""
+        return ForEachMOSA(lambda mosa: self[ForEachMOSA.distant_mosa(mosa)])
+
+    def adjacent(self):
+        """Return a ForEachMOSA instance for adjacent MOSAs."""
+        return ForEachMOSA(lambda mosa: self[ForEachMOSA.adjacent_mosa(mosa)])
+
+    def __add__(self, other):
+        if isinstance(other, ForEachSC):
+            return self + other.for_each_mosa()
+        return super().__add__(other)
+
+    def __sub__(self, other):
+        if isinstance(other, ForEachSC):
+            return self - other.for_each_mosa()
+        return super().__sub__(other)
+
+    def __mul__(self, other):
+        if isinstance(other, ForEachSC):
+            return self * other.for_each_mosa()
+        return super().__mul__(other)
+
+    def __floordiv__(self, other):
+        if isinstance(other, ForEachSC):
+            return self // other.for_each_mosa()
+        return super().__floordiv__(other)
+
+    def __truediv__(self, other):
+        if isinstance(other, ForEachSC):
+            return self / other.for_each_mosa()
+        return super().__truediv__(other)
diff --git a/lisainstrument/instrument.py b/lisainstrument/instrument.py
index 178649ec26783d9f7f943065ebcc7041fca8efc8..603db909f21c116840314ab339994e44335ec4a8 100644
--- a/lisainstrument/instrument.py
+++ b/lisainstrument/instrument.py
@@ -195,14 +195,15 @@ class Instrument:
         elif callable(interpolation):
             logger.info("Using user-provided interpolation function")
             self.interpolation_order = None
-            self.interpolate = lambda x, shift: x if numpy.isscalar(x) else interpolation(x, shift)
+            self.interpolate = lambda x, shift: x if numpy.isscalar(x) else \
+                interpolation(x, shift * self.physics_fs)
         else:
             method = str(interpolation[0])
             if method == 'lagrange':
                 self.interpolation_order = int(interpolation[1])
                 logging.debug("Using Lagrange interpolation of order %s", self.interpolation_order)
                 self.interpolate = lambda x, shift: x if numpy.isscalar(x) else \
-                    dsp.timeshift(x, shift, self.interpolation_order)
+                    dsp.timeshift(x, shift * self.physics_fs, self.interpolation_order)
             else:
                 raise ValueError(f"invalid interpolation parameters '{interpolation}'")
 
@@ -413,105 +414,80 @@ class Instrument:
         self.local_carrier_offsets = self.offsets_freqs
 
         logger.debug("Computing carrier fluctuations for local beams")
+        self.local_carrier_fluctuations = self.laser_noises + self.glitch_lasers
         if self.three_lasers:
-            self.local_carrier_fluctuations = ForEachMOSA(lambda mosa:
-                self.laser_noises[ForEachMOSA.sc(mosa)] + self.glitch_lasers[ForEachMOSA.sc(mosa)]
-            )
-        else:
-            self.local_carrier_fluctuations = ForEachMOSA(lambda mosa:
-                self.laser_noises[mosa] + self.glitch_lasers[mosa]
-            )
+            self.local_carrier_fluctuations = self.local_carrier_fluctuations.for_each_mosa()
 
         logger.debug("Computing upper sideband offsets for local beams")
-        self.local_usb_offsets = ForEachMOSA(lambda mosa:
-            self.offsets_freqs[mosa] + self.modulation_freqs[mosa] * (1 + self.clock_noise_offsets[mosa[0]])
-        )
+        self.local_usb_offsets = \
+            self.offsets_freqs + self.modulation_freqs * (1 + self.clock_noise_offsets)
 
         logger.debug("Computing upper sideband fluctuations for local beams")
-        if self.three_lasers:
-            self.local_usb_fluctuations = ForEachMOSA(lambda mosa:
-                self.laser_noises[ForEachMOSA.sc(mosa)] + self.glitch_lasers[ForEachMOSA.sc(mosa)]
-                + self.modulation_freqs[mosa] * (self.clock_noise_fluctuations[mosa[0]] + self.modulation_noises[mosa])
-            )
-        else:
-            self.local_usb_fluctuations = ForEachMOSA(lambda mosa:
-                self.laser_noises[mosa] + self.glitch_lasers[mosa] \
-                + self.modulation_freqs[mosa] * (self.clock_noise_fluctuations[mosa[0]] + self.modulation_noises[mosa])
-            )
+        self.local_usb_fluctuations = \
+            self.laser_noises + self.glitch_lasers \
+            + self.modulation_freqs * (self.clock_noise_fluctuations + self.modulation_noises)
 
         logger.debug("Computing local timer deviations")
-        self.local_timer_deviations = ForEachSC(lambda sc:
-            self.clock_offsets[sc] + numpy.cumsum(
-                numpy.broadcast_to(self.clock_noise_offsets[sc] + self.clock_noise_fluctuations[sc], \
-                    (self.physics_size,)) * self.dt)
-        )
+        self.local_timer_deviations = \
+            self.clock_offsets + ForEachSC(lambda sc:
+                numpy.cumsum(numpy.broadcast_to(
+                    self.clock_noise_offsets[sc] + self.clock_noise_fluctuations[sc],
+                    self.physics_size)
+                * self.dt)
+            )
 
         ## Propagation to distant MOSA
 
         logger.info("Propagating local beams to distant MOSAs")
 
         logger.debug("Propagating carrier offsets to distant MOSAs")
-        self.distant_carrier_offsets = ForEachMOSA(lambda mosa:
-            (1 - self.d_pprs[mosa]) * \
-            self.interpolate(self.local_carrier_offsets[ForEachMOSA.distant(mosa)],
-                - self.pprs[mosa] * self.physics_fs) \
-            - self.d_pprs[mosa] * self.central_freq
-        )
+        self.distant_carrier_offsets = \
+            -self.d_pprs * self.central_freq \
+            + (1 - self.d_pprs) * self.local_carrier_offsets.distant() \
+            .transformed(lambda mosa, x: self.interpolate(x, -self.pprs[mosa]))
 
         logger.debug("Propagating carrier fluctuations to distant MOSAs")
-        self.distant_carrier_fluctuations = ForEachMOSA(lambda mosa:
-            self.central_freq * self.gws[mosa] + (1 - self.d_pprs[mosa]) * \
-            self.interpolate(self.local_carrier_fluctuations[ForEachMOSA.distant(mosa)],
-                -self.pprs[mosa] * self.physics_fs)
-        )
+        self.distant_carrier_fluctuations = \
+            self.central_freq * self.gws \
+            + (1 - self.d_pprs) * self.local_carrier_fluctuations.distant() \
+            .transformed(lambda mosa, x: self.interpolate(x, -self.pprs[mosa]))
 
         logger.debug("Propagating upper sideband offsets to distant MOSAs")
-        self.distant_usb_offsets = ForEachMOSA(lambda mosa:
-            (1 - self.d_pprs[mosa]) * \
-            self.interpolate(self.local_usb_offsets[ForEachMOSA.distant(mosa)],
-                -self.pprs[mosa] * self.physics_fs) \
-            - self.d_pprs[mosa] * self.central_freq
-        )
+        self.distant_usb_offsets = \
+            -self.d_pprs * self.central_freq \
+            + (1 - self.d_pprs) * self.local_usb_offsets.distant() \
+            .transformed(lambda mosa, x: self.interpolate(x, -self.pprs[mosa]))
 
         logger.debug("Propagating upper sideband fluctuations to distant MOSAs")
-        self.distant_usb_fluctuations = ForEachMOSA(lambda mosa:
-            self.central_freq * self.gws[mosa] + (1 - self.d_pprs[mosa]) * \
-            self.interpolate(self.local_usb_fluctuations[ForEachMOSA.distant(mosa)],
-                - self.pprs[mosa] * self.physics_fs)
-        )
+        self.distant_usb_fluctuations = \
+            self.central_freq * self.gws \
+            + (1 - self.d_pprs) * self.local_usb_fluctuations.distant() \
+            .transformed(lambda mosa, x: self.interpolate(x, -self.pprs[mosa]))
 
         logger.debug("Propagating timer deviations to distant MOSAs")
-        self.distant_timer_deviations = ForEachMOSA(lambda mosa:
-            self.interpolate(self.local_timer_deviations[mosa[1]],
-                - self.pprs[mosa] * self.physics_fs) \
+        self.distant_timer_deviations = \
+            self.local_timer_deviations.for_each_mosa().distant() \
+            .transformed(lambda mosa, x: self.interpolate(x, -self.pprs[mosa])
             - self.pprs[mosa]
         )
 
-        ## Propagation to adjacent MOSA
-
-        logging.info("Propagating local beams to adjacent MOSAs")
+        logging.info("Propagating local beams to adjacent")
 
         logger.debug("Propagating carrier offsets to adjacent MOSAs")
-        self.adjacent_carrier_offsets = ForEachMOSA(lambda mosa:
-            self.local_carrier_offsets[ForEachMOSA.adjacent(mosa)]
-        )
+        self.adjacent_carrier_offsets = self.local_carrier_offsets.adjacent()
 
         logger.debug("Propagating carrier fluctuations to adjacent MOSAs")
-        self.adjacent_carrier_fluctuations = ForEachMOSA(lambda mosa:
-            self.local_carrier_fluctuations[ForEachMOSA.adjacent(mosa)] \
-            + self.central_freq * self.backlink_noises[mosa]
-        )
+        self.adjacent_carrier_fluctuations = \
+            self.local_carrier_fluctuations.adjacent() \
+            + self.central_freq * self.backlink_noises
 
         logger.debug("Propagating upper sideband offsets to adjacent MOSAs")
-        self.adjacent_usb_offsets = ForEachMOSA(lambda mosa:
-            self.local_usb_offsets[ForEachMOSA.adjacent(mosa)]
-        )
+        self.adjacent_usb_offsets = self.local_usb_offsets.adjacent()
 
         logger.debug("Propagating upper sideband fluctuations to adjacent MOSAs")
-        self.adjacent_usb_fluctuations = ForEachMOSA(lambda mosa:
-            self.local_usb_fluctuations[ForEachMOSA.adjacent(mosa)] \
-            + self.central_freq * self.backlink_noises[mosa]
-        )
+        self.adjacent_usb_fluctuations = \
+            self.local_usb_fluctuations.adjacent() \
+            + self.central_freq * self.backlink_noises
 
         ## Inter-spacecraft interferometer local beams
 
@@ -550,32 +526,27 @@ class Instrument:
         logger.info("Computing inter-spacecraft beatnotes on TPS")
 
         logger.debug("Computing inter-spacecraft carrier beatnote offsets on TPS")
-        self.tps_isc_carrier_offsets = ForEachMOSA(lambda mosa:
-            self.distant_isc_carrier_offsets[mosa] - self.local_isc_carrier_offsets[mosa]
-        )
+        self.tps_isc_carrier_offsets = \
+            self.distant_isc_carrier_offsets - self.local_isc_carrier_offsets
 
         logger.debug("Computing inter-spacecraft carrier beatnote fluctuations on TPS")
-        self.tps_isc_carrier_fluctuations = ForEachMOSA(lambda mosa:
-            self.distant_isc_carrier_fluctuations[mosa] - self.local_isc_carrier_fluctuations[mosa]
-        )
+        self.tps_isc_carrier_fluctuations = \
+            self.distant_isc_carrier_fluctuations - self.local_isc_carrier_fluctuations
 
         logging.debug("Computing inter-spacecraft upper sideband beatnote offsets on TPS")
-        self.tps_isc_usb_offsets = ForEachMOSA(lambda mosa:
-            self.distant_isc_usb_offsets[mosa] - self.local_isc_usb_offsets[mosa]
-        )
+        self.tps_isc_usb_offsets = \
+            self.distant_isc_usb_offsets - self.local_isc_usb_offsets
 
         logger.debug("Computing inter-spacecraft upper sideband beatnote fluctuations on TPS")
-        self.tps_isc_usb_fluctuations = ForEachMOSA(lambda mosa:
-            self.distant_isc_usb_fluctuations[mosa] - self.local_isc_usb_fluctuations[mosa]
-        )
+        self.tps_isc_usb_fluctuations = \
+            self.distant_isc_usb_fluctuations - self.local_isc_usb_fluctuations
 
         ## Measured pseudo-ranging on TPS grid (high-frequency)
 
         logger.info("Computing measured pseudo-ranges on TPS")
-        self.tps_mprs = ForEachMOSA(lambda mosa:
-            self.local_timer_deviations[ForEachMOSA.sc(mosa)] \
-            - self.distant_timer_deviations[mosa] + self.ranging_noises[mosa]
-        )
+        self.tps_mprs = \
+            self.local_timer_deviations \
+            - self.distant_timer_deviations + self.ranging_noises
 
         ## Test-mass interferometer local beams
 
@@ -585,19 +556,17 @@ class Instrument:
         self.local_tm_carrier_offsets = self.local_carrier_offsets
 
         logging.debug("Propagating local carrier fluctuations to test-mass interferometer")
-        self.local_tm_carrier_fluctuations = ForEachMOSA(lambda mosa:
-            self.local_carrier_fluctuations[mosa]
-            + self.central_freq * (self.testmass_noises[mosa] + self.glitch_tms[mosa] / c)
-        )
+        self.local_tm_carrier_fluctuations = \
+            self.local_carrier_fluctuations \
+            + self.central_freq * (self.testmass_noises + self.glitch_tms / c)
 
         logger.debug("Propagating local upper sideband offsets to test-mass interferometer")
         self.local_tm_usb_offsets = self.local_usb_offsets
 
         logger.debug("Propagating local upper sideband fluctuations to test-mass interferometer")
-        self.local_tm_usb_fluctuations = ForEachMOSA(lambda mosa:
-            self.local_usb_fluctuations[mosa]
-            + self.central_freq * (self.testmass_noises[mosa] + self.glitch_tms[mosa] / c)
-        )
+        self.local_tm_usb_fluctuations = \
+            self.local_usb_fluctuations \
+            + self.central_freq * (self.testmass_noises + self.glitch_tms / c)
 
         ## Test-mass interferometer adjacent beams
 
@@ -620,24 +589,20 @@ class Instrument:
         logger.info("Computing test-mass beatnotes on TPS")
 
         logger.debug("Computing test-mass carrier beatnote offsets on TPS")
-        self.tps_tm_carrier_offsets = ForEachMOSA(lambda mosa:
-            self.adjacent_tm_carrier_offsets[mosa] - self.local_tm_carrier_offsets[mosa]
-        )
+        self.tps_tm_carrier_offsets = \
+            self.adjacent_tm_carrier_offsets - self.local_tm_carrier_offsets
 
         logger.debug("Computing test-mass carrier beatnote fluctuations on TPS")
-        self.tps_tm_carrier_fluctuations = ForEachMOSA(lambda mosa:
-            self.adjacent_tm_carrier_fluctuations[mosa] - self.local_tm_carrier_fluctuations[mosa]
-        )
+        self.tps_tm_carrier_fluctuations = \
+            self.adjacent_tm_carrier_fluctuations - self.local_tm_carrier_fluctuations
 
         logger.debug("Computing test-mass upper sideband beatnote offsets on TPS")
-        self.tps_tm_usb_offsets = ForEachMOSA(lambda mosa:
-            self.adjacent_tm_usb_offsets[mosa] - self.local_tm_usb_offsets[mosa]
-        )
+        self.tps_tm_usb_offsets = \
+            self.adjacent_tm_usb_offsets - self.local_tm_usb_offsets
 
         logger.debug("Computing test-mass upper sideband beatnote fluctuations on TPS")
-        self.tps_tm_usb_fluctuations = ForEachMOSA(lambda mosa:
-            self.adjacent_tm_usb_fluctuations[mosa] - self.local_tm_usb_fluctuations[mosa]
-        )
+        self.tps_tm_usb_fluctuations = \
+            self.adjacent_tm_usb_fluctuations - self.local_tm_usb_fluctuations
 
         ## Reference interferometer local beams
 
@@ -676,116 +641,111 @@ class Instrument:
         logger.info("Computing reference beatnotes on TPS")
 
         logger.debug("Computing reference carrier beatnote offsets on TPS")
-        self.tps_ref_carrier_offsets = ForEachMOSA(lambda mosa:
-            self.adjacent_ref_carrier_offsets[mosa] - self.local_ref_carrier_offsets[mosa]
-        )
+        self.tps_ref_carrier_offsets = \
+            self.adjacent_ref_carrier_offsets - self.local_ref_carrier_offsets
 
         logger.debug("Computing reference carrier beatnote fluctuations on TPS")
-        self.tps_ref_carrier_fluctuations = ForEachMOSA(lambda mosa:
-            self.adjacent_ref_carrier_fluctuations[mosa] - self.local_ref_carrier_fluctuations[mosa]
-        )
+        self.tps_ref_carrier_fluctuations = \
+            self.adjacent_ref_carrier_fluctuations - self.local_ref_carrier_fluctuations
 
         logger.debug("Computing reference upper sideband beatnote offsets on TPS")
-        self.tps_ref_usb_offsets = ForEachMOSA(lambda mosa:
-            self.adjacent_ref_usb_offsets[mosa] - self.local_ref_usb_offsets[mosa]
-        )
+        self.tps_ref_usb_offsets = \
+            self.adjacent_ref_usb_offsets - self.local_ref_usb_offsets
 
         logger.debug("Computing reference upper sideband beatnote fluctuations on TPS")
-        self.tps_ref_usb_fluctuations = ForEachMOSA(lambda mosa:
-            self.adjacent_ref_usb_fluctuations[mosa] - self.local_ref_usb_fluctuations[mosa]
-        )
+        self.tps_ref_usb_fluctuations = \
+            self.adjacent_ref_usb_fluctuations - self.local_ref_usb_fluctuations
 
         ## Sampling beatnotes and measured pseudo-ranges to THE grid
 
         logger.info("Inverting timer deviations")
-        self.inverse_timer_deviations = ForEachSC(lambda sc:
-            self.invert_timer_deviations(self.local_timer_deviations[sc], sc)
-        )
+        self.inverse_timer_deviations = self.local_timer_deviations \
+            .transformed(lambda sc, x: self.invert_timer_deviations(x, sc))
 
-        self.timestamped = lambda mosa, x: self.interpolate(x,
-            -self.inverse_timer_deviations[ForEachMOSA.sc(mosa)] * self.physics_fs)
+        self.timestamped = \
+            lambda mosa, x: self.interpolate(x, -self.inverse_timer_deviations.for_each_mosa()[mosa])
 
         logger.info("Sampling inter-spacecraft beatnotes to THE grid")
 
         logger.debug("Sampling inter-spacecraft carrier beatnote fluctuations to THE grid")
-        self.the_isc_carrier_offsets = ForEachMOSA(lambda mosa:
-            self.tps_isc_carrier_offsets[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
+        self.the_isc_carrier_offsets = (
+            self.tps_isc_carrier_offsets / (1 + self.clock_noise_offsets)
         ).transformed(self.timestamped)
 
         logger.debug("Sampling inter-spacecraft carrier beatnote fluctuations to THE grid")
-        self.the_isc_carrier_fluctuations = ForEachMOSA(lambda mosa:
-            self.tps_isc_carrier_fluctuations[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
-                - self.tps_isc_carrier_offsets[mosa] * self.clock_noise_fluctuations[mosa[0]]
-                / (1 + self.clock_noise_offsets[mosa[0]])**2
+        self.the_isc_carrier_fluctuations = (
+            self.tps_isc_carrier_fluctuations / (1 + self.clock_noise_offsets)
+                - self.tps_isc_carrier_offsets * self.clock_noise_fluctuations
+                / (1 + self.clock_noise_offsets)**2
         ).transformed(self.timestamped)
 
         logging.debug("Sampling inter-spacecraft upper sideband beatnote offsets to THE grid")
-        self.the_isc_usb_offsets = ForEachMOSA(lambda mosa:
-            self.tps_isc_usb_offsets[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
+        self.the_isc_usb_offsets = (
+            self.tps_isc_usb_offsets / (1 + self.clock_noise_offsets)
         ).transformed(self.timestamped)
 
         logger.debug("Sampling inter-spacecraft upper sideband beatnote fluctuations to THE grid")
-        self.the_isc_usb_fluctuations = ForEachMOSA(lambda mosa:
-            self.tps_isc_usb_fluctuations[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
-                - self.tps_isc_usb_offsets[mosa] * self.clock_noise_fluctuations[mosa[0]]
-                / (1 + self.clock_noise_offsets[mosa[0]])**2
+        self.the_isc_usb_fluctuations = (
+            self.tps_isc_usb_fluctuations / (1 + self.clock_noise_offsets)
+                - self.tps_isc_usb_offsets * self.clock_noise_fluctuations
+                / (1 + self.clock_noise_offsets)**2
         ).transformed(self.timestamped)
 
         logger.info("Sampling measured pseudo-ranges to THE grid")
-        self.the_mprs = ForEachMOSA(lambda mosa:
-            self.tps_mprs[mosa]
+        self.the_mprs = (
+            self.tps_mprs
         ).transformed(self.timestamped)
 
         logger.info("Sampling test-mass beatnotes to THE grid")
 
         logger.debug("Sampling test-mass carrier beatnote offsets to THE grid")
-        self.the_tm_carrier_offsets = ForEachMOSA(lambda mosa:
-            self.tps_tm_carrier_offsets[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
+        self.the_tm_carrier_offsets = (
+            self.tps_tm_carrier_offsets / (1 + self.clock_noise_offsets)
         ).transformed(self.timestamped)
 
         logger.debug("Sampling test-mass carrier beatnote fluctuations to THE grid")
-        self.the_tm_carrier_fluctuations = ForEachMOSA(lambda mosa:
-            self.tps_tm_carrier_fluctuations[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
-                - self.tps_tm_carrier_offsets[mosa] * self.clock_noise_fluctuations[mosa[0]]
-                / (1 + self.clock_noise_offsets[mosa[0]])**2
+        self.the_tm_carrier_fluctuations = (
+            self.tps_tm_carrier_fluctuations / (1 + self.clock_noise_offsets)
+                - self.tps_tm_carrier_offsets * self.clock_noise_fluctuations
+                / (1 + self.clock_noise_offsets)**2
         ).transformed(self.timestamped)
 
         logger.debug("Sampling test-mass upper sideband beatnote offsets to THE grid")
-        self.the_tm_usb_offsets = ForEachMOSA(lambda mosa:
-            self.tps_tm_usb_offsets[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
+        self.the_tm_usb_offsets = (
+            self.tps_tm_usb_offsets / (1 + self.clock_noise_offsets)
         ).transformed(self.timestamped)
 
         logging.debug("Sampling test-mass upper sideband beatnote fluctuations to THE grid")
-        self.the_tm_usb_fluctuations = ForEachMOSA(lambda mosa:
-            self.tps_tm_usb_fluctuations[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
-                - self.tps_tm_usb_offsets[mosa] * self.clock_noise_fluctuations[mosa[0]]
-                / (1 + self.clock_noise_offsets[mosa[0]])**2
+        self.the_tm_usb_fluctuations = (
+            self.tps_tm_usb_fluctuations / (1 + self.clock_noise_offsets)
+                - self.tps_tm_usb_offsets * self.clock_noise_fluctuations
+                / (1 + self.clock_noise_offsets)**2
         ).transformed(self.timestamped)
 
         logger.info("Sampling reference beatnotes to THE grid")
 
         logger.debug("Sampling reference carrier beatnote offsets to THE grid")
-        self.the_ref_carrier_offsets = ForEachMOSA(lambda mosa:
-            self.tps_ref_carrier_offsets[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
+        self.the_ref_carrier_offsets = (
+            self.tps_ref_carrier_offsets / (1 + self.clock_noise_offsets)
         ).transformed(self.timestamped)
 
         logger.debug("Sampling reference carrier beatnote fluctuations to THE grid")
-        self.the_ref_carrier_fluctuations = ForEachMOSA(lambda mosa:
-            self.tps_ref_carrier_fluctuations[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
-                - self.tps_ref_carrier_offsets[mosa] * self.clock_noise_fluctuations[mosa[0]]
-                / (1 + self.clock_noise_offsets[mosa[0]])**2
+        self.the_ref_carrier_fluctuations = (
+            self.tps_ref_carrier_fluctuations / (1 + self.clock_noise_offsets)
+                - self.tps_ref_carrier_offsets * self.clock_noise_fluctuations
+                / (1 + self.clock_noise_offsets)**2
         ).transformed(self.timestamped)
 
         logger.debug("Sampling reference upper sideband beatnote offsets to THE grid")
-        self.the_ref_usb_offsets = ForEachMOSA(lambda mosa:
-            self.tps_ref_usb_offsets[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
+        self.the_ref_usb_offsets = (
+            self.tps_ref_usb_offsets / (1 + self.clock_noise_offsets)
         ).transformed(self.timestamped)
 
         logger.debug("Sampling reference upper sideband beatnote fluctuations to THE grid")
-        self.the_ref_usb_fluctuations = ForEachMOSA(lambda mosa:
-            self.tps_ref_usb_fluctuations[mosa] / (1 + self.clock_noise_offsets[mosa[0]])
-                - self.tps_ref_usb_offsets[mosa] * self.clock_noise_fluctuations[mosa[0]]
-                / (1 + self.clock_noise_offsets[mosa[0]])**2
+        self.the_ref_usb_fluctuations = (
+            self.tps_ref_usb_fluctuations / (1 + self.clock_noise_offsets)
+                - self.tps_ref_usb_offsets * self.clock_noise_fluctuations
+                / (1 + self.clock_noise_offsets)**2
         ).transformed(self.timestamped)
 
         ## Total frequencies
@@ -793,34 +753,28 @@ class Instrument:
         logger.info("Computing total beatnote frequencies")
 
         logger.debug("Computing total inter-spacecraft carrier beatnotes")
-        self.the_isc_carriers = ForEachMOSA(lambda mosa:
-            self.the_isc_carrier_offsets[mosa] + self.the_isc_carrier_fluctuations[mosa]
-        )
+        self.the_isc_carriers = \
+            self.the_isc_carrier_offsets + self.the_isc_carrier_fluctuations
 
         logger.debug("Computing total inter-spacecraft upper sideband beatnotes")
-        self.the_isc_usbs = ForEachMOSA(lambda mosa:
-            self.the_isc_usb_offsets[mosa] + self.the_isc_usb_fluctuations[mosa]
-        )
+        self.the_isc_usbs = \
+            self.the_isc_usb_offsets + self.the_isc_usb_fluctuations
 
         logger.debug("Computing total test-mass carrier beatnotes")
-        self.the_tm_carriers = ForEachMOSA(lambda mosa:
-            self.the_tm_carrier_offsets[mosa] + self.the_tm_carrier_fluctuations[mosa]
-        )
+        self.the_tm_carriers = \
+            self.the_tm_carrier_offsets + self.the_tm_carrier_fluctuations
 
         logger.debug("Computing total test-mass upper sideband beatnotes")
-        self.the_tm_usbs = ForEachMOSA(lambda mosa:
-            self.the_tm_usb_offsets[mosa] + self.the_tm_usb_fluctuations[mosa]
-        )
+        self.the_tm_usbs = \
+            self.the_tm_usb_offsets + self.the_tm_usb_fluctuations
 
         logger.debug("Computing total reference carrier beatnotes")
-        self.the_ref_carriers = ForEachMOSA(lambda mosa:
-            self.the_ref_carrier_offsets[mosa] + self.the_ref_carrier_fluctuations[mosa]
-        )
+        self.the_ref_carriers = \
+            self.the_ref_carrier_offsets + self.the_ref_carrier_fluctuations
 
         logger.debug("Computing total reference upper sideband beatnotes")
-        self.the_ref_usbs = ForEachMOSA(lambda mosa:
-            self.the_ref_usb_offsets[mosa] + self.the_ref_usb_fluctuations[mosa]
-        )
+        self.the_ref_usbs = \
+            self.the_ref_usb_offsets + self.the_ref_usb_fluctuations
 
         ## Antialiasing filtering
 
@@ -912,15 +866,14 @@ class Instrument:
         if self.clock_freqlindrifts == self.clock_freqquaddrifts == 0:
             # Optimize to use a scalar if we only have a constant frequency offset
             logger.debug("Generating clock noise offsets as constant frequency offsets")
-            self.clock_noise_offsets = ForEachSC(lambda sc:
-                self.clock_freqoffsets[sc]
-            )
+            self.clock_noise_offsets = self.clock_freqoffsets
         else:
             logger.debug("Generating clock noise offsets")
             t = self.physics_t
-            self.clock_noise_offsets = ForEachSC(lambda sc:
-                self.clock_freqoffsets[sc] + self.clock_freqlindrifts[sc] * t + self.clock_freqquaddrifts[sc] * t**2
-            )
+            self.clock_noise_offsets = \
+                self.clock_freqoffsets \
+                + self.clock_freqlindrifts * t \
+                + self.clock_freqquaddrifts * t**2
 
         logger.debug("Generating clock noise fluctuations")
         self.clock_noise_fluctuations = ForEachSC(lambda sc:
@@ -939,7 +892,8 @@ class Instrument:
 
         logger.info("Generating backlink noise")
         self.backlink_noises = ForEachMOSA(lambda mosa:
-            noises.backlink(self.physics_fs, self.physics_size, self.backlink_asds[mosa], self.backlink_fknees[mosa])
+            noises.backlink(self.physics_fs, self.physics_size,
+                self.backlink_asds[mosa], self.backlink_fknees[mosa])
         )
 
         ## Test-mass acceleration noise
@@ -954,7 +908,8 @@ class Instrument:
 
         logger.info("Generating ranging noise")
         self.ranging_noises = ForEachMOSA(lambda mosa:
-            self.ranging_biases[mosa] + noises.ranging(self.physics_fs, self.physics_size, self.ranging_asds[mosa])
+            self.ranging_biases[mosa] + noises.ranging(self.physics_fs,
+                self.physics_size, self.ranging_asds[mosa])
         )
 
     def invert_timer_deviations(self, timer_deviations, sc):
diff --git a/tests/test_containers.py b/tests/test_containers.py
index 094ced5a4a5ff424c9e9f15959d656263b332975..32abe7113158def261505539379e4f00e23c29bd 100644
--- a/tests/test_containers.py
+++ b/tests/test_containers.py
@@ -120,6 +120,141 @@ def test_equality():
     assert object_1 == object_2
 
 
+def test_addition():
+    """Check that we can add two ForEachObject subclasses of the same type, or a scalar."""
+
+    object_1 = ForEachAB({'A': 1, 'B': 2})
+    object_2 = ForEachAB({'A': 3, 'B': -4})
+    object_3 = ForEachMOSA(0)
+
+    result = object_1 + object_2
+    assert result['A'] == 4
+    assert result['B'] == -2
+
+    result = object_1 + 10
+    assert result['A'] == 11
+    assert result['B'] == 12
+
+    result = -5 + object_2
+    assert result['A'] == -2
+    assert result['B'] == -9
+
+    with raises(TypeError):
+        result = object_1 + object_3
+    with raises(TypeError):
+        result = object_2 + object_3
+
+
+def test_subtraction():
+    """Check that we can subtract two ForEachObject subclasses of the same type, or a scalar."""
+
+    object_1 = ForEachAB({'A': 1, 'B': 2})
+    object_2 = ForEachAB({'A': 3, 'B': -4})
+    object_3 = ForEachMOSA(0)
+
+    result = object_1 - object_2
+    assert result['A'] == -2
+    assert result['B'] == 6
+
+    result = object_1 - 10
+    assert result['A'] == -9
+    assert result['B'] == -8
+
+    result = 10 - object_2
+    assert result['A'] == 7
+    assert result['B'] == 14
+
+    with raises(TypeError):
+        result = object_1 - object_3
+    with raises(TypeError):
+        result = object_2 - object_3
+
+
+def test_multiplication():
+    """Check that we can multiply two ForEachObject subclasses of the same type, or a scalar."""
+
+    object_1 = ForEachAB({'A': 1, 'B': 2})
+    object_2 = ForEachAB({'A': 3, 'B': -4})
+    object_3 = ForEachMOSA(0)
+
+    result = object_1 * object_2
+    assert result['A'] == 3
+    assert result['B'] == -8
+
+    result = object_1 * 2
+    assert result['A'] == 2
+    assert result['B'] == 4
+
+    result = 10 * object_2
+    assert result['A'] == 30
+    assert result['B'] == -40
+
+    with raises(TypeError):
+        result = object_1 * object_3
+    with raises(TypeError):
+        result = object_2 * object_3
+
+
+def test_floor_division():
+    """Check that we can apply floor division on two ForEachObject subclasses, or a scalar."""
+
+    object_1 = ForEachAB({'A': 1, 'B': 2})
+    object_2 = ForEachAB({'A': 3, 'B': -4})
+    object_3 = ForEachMOSA(0)
+
+    result = object_2 // object_1
+    assert result['A'] == 3
+    assert result['B'] == -2
+
+    result = object_2 // 2
+    assert result['A'] == 1
+    assert result['B'] == -2
+
+    with raises(TypeError):
+        result = object_1 // object_3
+    with raises(TypeError):
+        result = 20 // object_1
+
+
+def test_real_division():
+    """Check that we can divide two ForEachObject subclasses of the same type, or a scalar."""
+
+    object_1 = ForEachAB({'A': 1, 'B': 2})
+    object_2 = ForEachAB({'A': 3, 'B': -4})
+    object_3 = ForEachMOSA(0)
+
+    result = object_1 / object_2
+    assert result['A'] == 1/3
+    assert result['B'] == -1/2
+
+    result = object_1 / 5
+    assert result['A'] == 1/5
+    assert result['B'] == 2/5
+
+    result = 10 / object_2
+    assert result['A'] == 10/3
+    assert result['B'] == -10/4
+
+    with raises(TypeError):
+        result = object_1 / object_3
+    with raises(TypeError):
+        result = object_2 / object_3
+
+
+def test_power():
+    """Check that we take the power of a ForEachObject instance."""
+
+    object_1 = ForEachAB({'A': 1, 'B': -2})
+
+    result = object_1**1
+    assert result['A'] == 1
+    assert result['B'] == -2
+
+    result = object_1**2
+    assert result['A'] == 1
+    assert result['B'] == 4
+
+
 def test_transformed():
     """Check that we transformation is correctly applied to ForEachObject instances."""
 
@@ -132,6 +267,25 @@ def test_transformed():
     assert my_object['A'] == 'a'
     assert my_object['B'] == 'b'
 
+
+def test_abs():
+    """Check that we can take the absolute value of ForEachObject instances."""
+
+    my_object = ForEachAB({'A': -1, 'B': 2})
+    my_object = abs(my_object)
+    assert my_object['A'] == 1
+    assert my_object['B'] == 2
+
+
+def test_neg():
+    """Check that we can take the negative value of ForEachObject instances."""
+
+    my_object = ForEachAB({'A': -1, 'B': 2})
+    my_object = -my_object
+    assert my_object['A'] == 1
+    assert my_object['B'] == -2
+
+
 def test_write():
     """Check that we can write a ForEachObject instance."""
 
@@ -153,13 +307,13 @@ def test_sc_indices():
 
     assert ForEachSC.indices() == ['1', '2', '3']
 
-    assert ForEachSC.distant_left('1') == '2'
-    assert ForEachSC.distant_left('2') == '3'
-    assert ForEachSC.distant_left('3') == '1'
+    assert ForEachSC.distant_left_sc('1') == '2'
+    assert ForEachSC.distant_left_sc('2') == '3'
+    assert ForEachSC.distant_left_sc('3') == '1'
 
-    assert ForEachSC.distant_right('1') == '3'
-    assert ForEachSC.distant_right('2') == '1'
-    assert ForEachSC.distant_right('3') == '2'
+    assert ForEachSC.distant_right_sc('1') == '3'
+    assert ForEachSC.distant_right_sc('2') == '1'
+    assert ForEachSC.distant_right_sc('3') == '2'
 
     assert ForEachSC.left_mosa('1') == '12'
     assert ForEachSC.left_mosa('2') == '23'
@@ -182,32 +336,95 @@ def test_mosa_indices():
     assert ForEachMOSA.sc('32') == '3'
     assert ForEachMOSA.sc('21') == '2'
 
-    assert ForEachMOSA.distant('12') == '21'
-    assert ForEachMOSA.distant('23') == '32'
-    assert ForEachMOSA.distant('31') == '13'
-    assert ForEachMOSA.distant('13') == '31'
-    assert ForEachMOSA.distant('32') == '23'
-    assert ForEachMOSA.distant('21') == '12'
+    assert ForEachMOSA.distant_mosa('12') == '21'
+    assert ForEachMOSA.distant_mosa('23') == '32'
+    assert ForEachMOSA.distant_mosa('31') == '13'
+    assert ForEachMOSA.distant_mosa('13') == '31'
+    assert ForEachMOSA.distant_mosa('32') == '23'
+    assert ForEachMOSA.distant_mosa('21') == '12'
 
-    assert ForEachMOSA.adjacent('12') == '13'
-    assert ForEachMOSA.adjacent('23') == '21'
-    assert ForEachMOSA.adjacent('31') == '32'
-    assert ForEachMOSA.adjacent('13') == '12'
-    assert ForEachMOSA.adjacent('32') == '31'
-    assert ForEachMOSA.adjacent('21') == '23'
+    assert ForEachMOSA.adjacent_mosa('12') == '13'
+    assert ForEachMOSA.adjacent_mosa('23') == '21'
+    assert ForEachMOSA.adjacent_mosa('31') == '32'
+    assert ForEachMOSA.adjacent_mosa('13') == '12'
+    assert ForEachMOSA.adjacent_mosa('32') == '31'
+    assert ForEachMOSA.adjacent_mosa('21') == '23'
 
-def test_init_mosa_with_sc():
-    """Test one can initialize ForEachMOSA from ForEachSC."""
+
+def test_foreachsc_to_foreachmosa():
+    """Test that one can turn a ForEachSC instance to a ForEachMOSA instance."""
 
     my_sc = ForEachSC(lambda sc: 10 * int(sc))
     assert my_sc['1'] == 10
     assert my_sc['2'] == 20
     assert my_sc['3'] == 30
 
-    my_mosa = ForEachMOSA(my_sc)
+    my_mosa = my_sc.for_each_mosa()
     assert my_mosa['12'] == 10
     assert my_mosa['13'] == 10
     assert my_mosa['21'] == 20
     assert my_mosa['23'] == 20
     assert my_mosa['31'] == 30
     assert my_mosa['32'] == 30
+
+
+def test_auto_foreachsc_to_foreachmosa():
+    """Test that ForEachSC turn automatically into ForEachMOSA during operations."""
+
+    my_sc = ForEachSC(int)
+    my_mosa = ForEachMOSA(int)
+
+    my_add_1 = my_sc + my_mosa
+    my_add_2 = my_mosa + my_sc
+    assert my_add_1 == my_sc.for_each_mosa() + my_mosa
+    assert my_add_1 == my_add_2
+
+    my_sub_1 = my_sc - my_mosa
+    my_sub_2 = my_mosa - my_sc
+    assert my_sub_1 == my_sc.for_each_mosa() - my_mosa
+    assert my_sub_1 == -my_sub_2
+
+    my_mult_1 = my_sc * my_mosa
+    my_mult_2 = my_mosa * my_sc
+    assert my_mult_1 == my_sc.for_each_mosa() * my_mosa
+    assert my_mult_1 == my_mult_2
+
+
+def test_foreachmosa_distant():
+    """Test that one can generate a ForEachMOSA instant for distant MOSAs."""
+
+    my_mosa = ForEachMOSA(int)
+    assert my_mosa['12'] == 12
+    assert my_mosa['13'] == 13
+    assert my_mosa['21'] == 21
+    assert my_mosa['23'] == 23
+    assert my_mosa['31'] == 31
+    assert my_mosa['32'] == 32
+
+    distant_mosa = my_mosa.distant()
+    assert distant_mosa['12'] == 21
+    assert distant_mosa['13'] == 31
+    assert distant_mosa['21'] == 12
+    assert distant_mosa['23'] == 32
+    assert distant_mosa['31'] == 13
+    assert distant_mosa['32'] == 23
+
+
+def test_foreachmosa_adjacent():
+    """Test that one can generate a ForEachMOSA instant for adjacent MOSAs."""
+
+    my_mosa = ForEachMOSA(int)
+    assert my_mosa['12'] == 12
+    assert my_mosa['13'] == 13
+    assert my_mosa['21'] == 21
+    assert my_mosa['23'] == 23
+    assert my_mosa['31'] == 31
+    assert my_mosa['32'] == 32
+
+    adjacent_mosa = my_mosa.adjacent()
+    assert adjacent_mosa['12'] == 13
+    assert adjacent_mosa['13'] == 12
+    assert adjacent_mosa['21'] == 23
+    assert adjacent_mosa['23'] == 21
+    assert adjacent_mosa['31'] == 32
+    assert adjacent_mosa['32'] == 31