diff --git a/mbtrack2/tracking/__init__.py b/mbtrack2/tracking/__init__.py
index 9ce56b06d1dd62911ee551cc96805a690ea4a189..38a0f8d4fc6c3e4dceae81ae5a760f3829667432 100644
--- a/mbtrack2/tracking/__init__.py
+++ b/mbtrack2/tracking/__init__.py
@@ -12,7 +12,9 @@ from mbtrack2.tracking.element import (Element,
                                        LongitudinalMap, 
                                        TransverseMap, 
                                        SynchrotronRadiation,
-                                       SkewQuadrupole)
+                                       SkewQuadrupole,
+                                       TransverseMapSector,
+                                       transverse_map_sector_generator)
 from mbtrack2.tracking.aperture import (CircularAperture, 
                                         ElipticalAperture,
                                         RectangularAperture, 
diff --git a/mbtrack2/tracking/element.py b/mbtrack2/tracking/element.py
index a9f2efdd067850154858dbbcb04e565a4a68898e..a31c66ec28cb95a03422b72cf7f3792a0cd8f8df 100644
--- a/mbtrack2/tracking/element.py
+++ b/mbtrack2/tracking/element.py
@@ -243,3 +243,161 @@ class SkewQuadrupole:
         bunch['xp'] = bunch['xp'] - self.strength * bunch['y']
         bunch['yp'] = bunch['yp'] - self.strength * bunch['x']
 
+class TransverseMapSector(Element):
+    """
+    Transverse map for a sector of the synchrotron, from an initial 
+    position s0 to a final position s1.
+
+    Parameters
+    ----------
+    ring : Synchrotron object
+        Ring parameters.
+    alpha0 : array of shape (2,)
+        Alpha Twiss function at the initial location of the sector.
+    beta0 : array of shape (2,)
+        Beta Twiss function at the initial location of the sector.
+    dispersion0 : array of shape (4,)
+        Dispersion function at the initial location of the sector.
+    alpha1 : array of shape (2,)
+        Alpha Twiss function at the final location of the sector.
+    beta1 : array of shape (2,)
+        Beta Twiss function at the final location of the sector.
+    dispersion1 : array of shape (4,)
+        Dispersion function at the final location of the sector.
+    phase_diff : array of shape (2,)
+        Phase difference between the initial and final location of the 
+        sector.
+    chro_diff : array of shape (2,)
+        Chromaticity difference between the initial and final location of 
+        the sector.
+    adts : array of shape (4,), optional
+        Amplitude-dependent tune shift of the sector, see Synchrotron class 
+        for details. The default is None.
+
+    """
+    def __init__(self, ring, alpha0, beta0, dispersion0, alpha1, beta1, 
+                 dispersion1, phase_diff, chro_diff, adts=None):
+        self.ring = ring
+        self.alpha0 = alpha0
+        self.beta0 = beta0
+        self.dispersion0 = dispersion0
+        self.alpha1 = alpha1
+        self.beta1 = beta1
+        self.dispersion1 = dispersion1  
+        self.tune_diff = phase_diff / (2*np.pi)
+        self.chro_diff = chro_diff
+        if adts is not None:
+            self.adts_poly = [np.poly1d(adts[0]),
+                              np.poly1d(adts[1]),
+                              np.poly1d(adts[2]), 
+                              np.poly1d(adts[3])]
+        else:
+            self.adts_poly = None
+    
+    @Element.parallel    
+    def track(self, bunch):
+        """
+        Tracking method for the element.
+        No bunch to bunch interaction, so written for Bunch objects and
+        @Element.parallel is used to handle Beam objects.
+        
+        Parameters
+        ----------
+        bunch : Bunch or Beam object
+        """
+
+        # Compute phase advance which depends on energy via chromaticity and ADTS
+        if self.adts_poly is None:
+            phase_advance_x = 2*np.pi * (self.tune_diff[0] + 
+                                         self.chro_diff[0]*bunch["delta"])
+            phase_advance_y = 2*np.pi * (self.tune_diff[1] + 
+                                         self.chro_diff[1]*bunch["delta"])
+        else:
+            phase_advance_x = 2*np.pi * (self.tune_diff[0] + 
+                                         self.chro_diff[0]*bunch["delta"] + 
+                                         self.adts_poly[0](bunch['x']) + 
+                                         self.adts_poly[2](bunch['y']))
+            phase_advance_y = 2*np.pi * (self.tune_diff[1] + 
+                                         self.chro_diff[1]*bunch["delta"] +
+                                         self.adts_poly[1](bunch['x']) + 
+                                         self.adts_poly[3](bunch['y']))
+        
+        # 6x6 matrix corresponding to (x, xp, delta, y, yp, delta)
+        matrix = np.zeros((6,6,len(bunch)))
+        
+        # Horizontal
+        matrix[0,0,:] = np.sqrt(self.beta1[0]/self.beta0[0])*(np.cos(phase_advance_x) + self.alpha0[0]*np.sin(phase_advance_x))
+        matrix[0,1,:] = np.sqrt(self.beta0[0]*self.beta1[0])*np.sin(phase_advance_x)
+        matrix[0,2,:] = self.dispersion1[0] - matrix[0,0,:]*self.dispersion0[0] - matrix[0,1,:]*self.dispersion0[1]
+        matrix[1,0,:] = ((self.alpha0[0] - self.alpha1[0])*np.cos(phase_advance_x) - (1 + self.alpha0[0]*self.alpha1[0])*np.sin(phase_advance_x))/np.sqrt(self.beta0[0]*self.beta1[0])
+        matrix[1,1,:] = np.sqrt(self.beta0[0]/self.beta1[0])*(np.cos(phase_advance_x) - self.alpha1[0]*np.sin(phase_advance_x))
+        matrix[1,2,:] = self.dispersion1[1] - matrix[1,0,:]*self.dispersion0[0] - matrix[1,1,:]*self.dispersion0[1]
+        matrix[2,2,:] = 1
+        
+        # Vertical
+        matrix[3,3,:] = np.sqrt(self.beta1[1]/self.beta0[1])*(np.cos(phase_advance_y) + self.alpha0[1]*np.sin(phase_advance_y))
+        matrix[3,4,:] = np.sqrt(self.beta0[1]*self.beta1[1])*np.sin(phase_advance_y)
+        matrix[3,5,:] = self.dispersion1[2] - matrix[3,3,:]*self.dispersion0[2] - matrix[3,4,:]*self.dispersion0[3]
+        matrix[4,3,:] = ((self.alpha0[1] - self.alpha1[1])*np.cos(phase_advance_y) - (1 + self.alpha0[1]*self.alpha1[1])*np.sin(phase_advance_y))/np.sqrt(self.beta0[1]*self.beta1[1])
+        matrix[4,4,:] = np.sqrt(self.beta0[1]/self.beta1[1])*(np.cos(phase_advance_y) - self.alpha1[1]*np.sin(phase_advance_y))
+        matrix[4,5,:] = self.dispersion1[3] - matrix[4,3,:]*self.dispersion0[2] - matrix[4,4,:]*self.dispersion0[3]
+        matrix[5,5,:] = 1
+        
+        x = matrix[0,0,:]*bunch["x"] + matrix[0,1,:]*bunch["xp"] + matrix[0,2,:]*bunch["delta"]
+        xp = matrix[1,0,:]*bunch["x"] + matrix[1,1,:]*bunch["xp"] + matrix[1,2,:]*bunch["delta"]
+        y =  matrix[3,3,:]*bunch["y"] + matrix[3,4,:]*bunch["yp"] + matrix[3,5,:]*bunch["delta"]
+        yp = matrix[4,3,:]*bunch["y"] + matrix[4,4,:]*bunch["yp"] + matrix[4,5,:]*bunch["delta"]
+        
+        bunch["x"] = x
+        bunch["xp"] = xp
+        bunch["y"] = y
+        bunch["yp"] = yp
+        
+def transverse_map_sector_generator(ring, positions):
+    """
+    Convenience function which generate a list of TransverseMapSector elements
+    from a ring with an AT lattice.
+    
+    Tracking through all the sectors is equivalent to a full turn (and thus to 
+    the TransverseMap object).
+
+    Parameters
+    ----------
+    ring : Synchrotron object
+        Ring parameters, must .
+    positions : array
+        List of longitudinal positions in [m] to use as starting and end points
+        of the TransverseMapSector elements.
+
+    Returns
+    -------
+    sectors : list
+        List of TransverseMapSector elements.
+
+    """
+    
+    if ring.optics.use_local_values:
+        raise ValueError("The Synchrotron object must be loaded from an AT lattice")
+    
+    N_sec = len(positions)
+    sectors = []
+    chro_diff = ring.chro/N_sec
+    for i in range(N_sec):
+        alpha0 = ring.optics.alpha(positions[i])
+        beta0 = ring.optics.beta(positions[i])
+        dispersion0 = ring.optics.dispersion(positions[i])
+        mu0 = ring.optics.mu(positions[i])
+        if i != (N_sec - 1):
+            alpha1 = ring.optics.alpha(positions[i+1])
+            beta1 = ring.optics.beta(positions[i+1])
+            dispersion1 = ring.optics.dispersion(positions[i+1])
+            mu1 = ring.optics.mu(positions[i+1])
+        else:
+            alpha1 = ring.optics.alpha(positions[0])
+            beta1 = ring.optics.beta(positions[0])
+            dispersion1 = ring.optics.dispersion(positions[0])
+            mu1 = ring.optics.mu(ring.L)
+        phase_diff = mu1 - mu0
+        sectors.append(TransverseMapSector(ring, alpha0, beta0, dispersion0, 
+                     alpha1, beta1, dispersion1, phase_diff, chro_diff))
+    return sectors
diff --git a/mbtrack2/utilities/optics.py b/mbtrack2/utilities/optics.py
index fdbd0091ab9166430c2cf329ed90fbe384931055..6552918fb8eebc751c1f48ab4476d190ba7b8221 100644
--- a/mbtrack2/utilities/optics.py
+++ b/mbtrack2/utilities/optics.py
@@ -123,6 +123,7 @@ class Optics:
         self.beta_array = np.tile(twiss.beta.T, self.periodicity)
         self.alpha_array = np.tile(twiss.alpha.T, self.periodicity)
         self.dispersion_array = np.tile(twiss.dispersion.T, self.periodicity)
+        self.mu_array = np.tile(twiss.mu.T, self.periodicity)
         
         self.position = np.append(self.position, self.lattice.circumference)
         self.beta_array = np.append(self.beta_array, self.beta_array[:,0:1],
@@ -131,12 +132,17 @@ class Optics:
                                      axis=1)
         self.dispersion_array = np.append(self.dispersion_array,
                                           self.dispersion_array[:,0:1], axis=1)
+        self.mu_array = np.append(self.mu_array,
+                                  self.mu_array[:,0:1], axis=1)
         
         self.gamma_array = (1 + self.alpha_array**2)/self.beta_array
         self.tune = tune * self.periodicity
         self.chro = chrom * self.periodicity
         self.ac = at.get_mcf(self.lattice)
         
+        self.mu_array[:,-1] = (np.floor(self.mu_array[:,-2]/(2*np.pi)) +
+                               self.tune)*2*np.pi
+        
         self.setup_interpolation()
         
         
@@ -162,6 +168,10 @@ class Optics:
                               kind='linear')
         self.disppY = interp1d(self.position, self.dispersion_array[3,:],
                                kind='linear')
+        self.muX = interp1d(self.position, self.mu_array[0,:],
+                              kind='linear')
+        self.muY = interp1d(self.position, self.mu_array[1,:],
+                              kind='linear')
     
     @property
     def local_beta(self):
@@ -303,13 +313,34 @@ class Optics:
                           self.dispY(position), self.disppY(position)]
             return np.array(dispersion)
         
+    def mu(self, position):
+        """
+        Return phase advances at specific locations given by position. 
+        If no lattice has been loaded, None is returned.
+
+        Parameters
+        ----------
+        position : array or float
+            Longitudinal position at which the phase advances are returned.
+
+        Returns
+        -------
+        mu : array
+            Phase advances.
+        """
+        if self.use_local_values:
+            return np.outer(np.array([0,0]), np.ones_like(position))
+        else:
+            mu = [self.muX(position), self.muY(position)]
+            return np.array(mu)
+        
     def plot(self, var, option, n_points=1000):
         """
         Plot optical variables.
     
         Parameters
         ----------
-        var : {"beta", "alpha", "gamma", "dispersion"}
+        var : {"beta", "alpha", "gamma", "dispersion", "mu"}
             Optical variable to be plotted.
         option : str
             If var = "beta", "alpha" and "gamma", option = {"x","y"} specifying
@@ -322,7 +353,7 @@ class Optics:
         """
     
         var_dict = {"beta":self.beta, "alpha":self.alpha, "gamma":self.gamma, 
-                    "dispersion":self.dispersion}
+                    "dispersion":self.dispersion, "mu":self.mu}
         
         if var == "dispersion":
             option_dict = {"x":0, "px":1, "y":2, "py":3}
@@ -332,15 +363,15 @@ class Optics:
             ylabel = label[option_dict[option]]
          
         
-        elif var=="beta" or var=="alpha" or var=="gamma":
+        elif var=="beta" or var=="alpha" or var=="gamma" or var=="mu":
             option_dict = {"x":0, "y":1}
             label_dict = {"beta":"$\\beta$", "alpha":"$\\alpha$", 
-                          "gamma":"$\\gamma$"}
+                          "gamma":"$\\gamma$", "mu":"$\\mu$"}
             
             if option == "x": label_sup = "$_{x}$"
             elif option == "y": label_sup = "$_{y}$"
             
-            unit = {"beta":" (m)", "alpha":"", "gamma":" (m$^{-1}$)"}
+            unit = {"beta":" (m)", "alpha":"", "gamma":" (m$^{-1}$)", "mu":""}
             
             ylabel = label_dict[var] + label_sup + unit[var]