diff --git a/tracking/wakepotential.py b/tracking/wakepotential.py
index f9197bca6bf62f3d9633bb683e2a723bf7f469f7..41bd2d019270b976e91883c1c8f3d8722b93fa8a 100644
--- a/tracking/wakepotential.py
+++ b/tracking/wakepotential.py
@@ -13,17 +13,23 @@ import pandas as pd
 from scipy import signal
 from scipy.interpolate import interp1d
 from mbtrack2.tracking.element import Element
-
+   
 class WakePotential(Element):
     """
-    Compute a wake potential from wake functions by performing a convolution 
-    with a bunch charge profile.
+    Compute a wake potential from uniformly sampled wake functions by 
+    performing a convolution with a bunch charge profile.
+    
+    Two different time bases are used. The first one is controled by the n_bin
+    parameter and is used to compute the bunch profile. Then the bunch profile
+    is interpolated on the wake function time base which is used to perform the
+    convolution to get the wake potential.
     
     Parameters
     ----------
     ring : Synchrotron object
     wakefield : Wakefield object
-        Wakefield object which contains the wake functions to be used.
+        Wakefield object which contains the wake functions to be used. The wake
+        functions must be uniformly sampled!
     n_bin : int, optional
         Number of bins for constructing the longitudinal bunch profile.
         
@@ -40,17 +46,24 @@ class WakePotential(Element):
     -------
     charge_density(bunch)
         Compute bunch charge density profile in [1/s].
-    dipole_moment(bunch, plane)
+    dipole_moment(bunch, plane, tau0)
         Return the dipole moment of the bunch computed on the same time array 
-        as the bunch profile.
+        as the wake function.
+    prepare_wakefunction(wake_type)
+        Prepare the wake function of a given wake_type to be used for the wake
+        potential computation. 
     get_wakepotential(bunch, wake_type)
-        Return the wake potential computed on the same time array as the bunch 
-        profile.
+        Return the wake potential computed on the wake function time array 
+        limited to the bunch profile.
     track(bunch)
         Tracking method for the element.
-    plot_last_wake(wake_type, plot_rho=True, plot_dipole=False)
+    plot_last_wake(wake_type)
         Plot the last wake potential of a given type computed during the last
         call of the track method.
+    reference_loss(bunch)
+        Calculate the loss factor and kick factor from the wake potential and 
+        compare it to a reference value assuming a Gaussian bunch computed in 
+        the frequency domain.
         
     """
     
@@ -105,16 +118,21 @@ class WakePotential(Element):
         if len(self.tau) != len(self.rho):
             self.tau = np.append(self.tau, self.tau[-1] + self.dtau)
             
-    def dipole_moment(self, bunch, plane):
+        self.tau_mean = np.mean(self.tau)
+        self.tau -= self.tau_mean
+            
+    def dipole_moment(self, bunch, plane, tau0):
         """
         Return the dipole moment of the bunch computed on the same time array 
-        as the bunch profile.
+        as the wake function.
 
         Parameters
         ----------
         bunch : Bunch object
         plane : str
             Plane on which the dipole moment is computed, "x" or "y".
+        tau0 : array
+            Time array on which the dipole moment will be interpolated, in [s].
 
         Returns
         -------
@@ -128,7 +146,7 @@ class WakePotential(Element):
         dipole = dipole/self.profile
         dipole[np.isnan(dipole)] = 0
         
-        # Add N values to get same size as tau/rho
+        # Add N values to get same size as tau/profile
         if self.n_bin % 2 == 0:
             N = int(self.n_bin/2)
             dipole = np.append(dipole, np.zeros(N))
@@ -138,13 +156,98 @@ class WakePotential(Element):
             dipole = np.append(dipole, np.zeros(N))
             dipole = np.insert(dipole, 0, np.zeros(N+1))
             
-        setattr(self, "dipole_" + plane, dipole)
-        return dipole
+        # Interpole on tau0 to get the same size as W0
+        interp_dipole = interp1d(self.tau, dipole, fill_value=0, 
+                             bounds_error=False)
+        dipole0 = interp_dipole(tau0)
+            
+        setattr(self, "dipole_" + plane, dipole0)
+        return dipole0
+    
+    
+    def prepare_wakefunction(self, wake_type):
+        """
+        Prepare the wake function of a given wake_type to be used for the wake
+        potential computation. 
+        
+        The new time array keeps the same sampling time as given in the 
+        WakeFunction definition but is restricted to the bunch profile time 
+        array.
+
+        Parameters
+        ----------
+        wake_type : str
+            Type of the wake function to prepare: "Wlong", "Wxdip", ...
+
+        Returns
+        -------
+        tau0 : array
+            Time base of the wake function in [s].
+        dtau0 : float
+            Difference between two points of the wake function time base in 
+            [s].
+        W0 : array
+            Wake function array in [V/C] or [V/C/m].
+
+        """
+        
+        try:
+            tau0 = getattr(self, "tau0_" + wake_type)
+            dtau0 = getattr(self, "dtau0_" + wake_type)
+            W0 = getattr(self, "W0_" + wake_type)
+        except AttributeError:
+            tau0 = np.array(getattr(self.wakefield, wake_type).data.index)
+            dtau0 = tau0[1] - tau0[0]
+            W0 = np.array(getattr(self.wakefield, wake_type).data["real"])
+        
+        # Keep only the wake function on the rho window
+        ind = np.all([min(self.tau[0], 0) < tau0, max(self.tau[-1], 0) > tau0],
+                     axis=0)
+        tau0 = tau0[ind]
+        W0 = W0[ind]
+        
+        # Check the wake function window for assymetry
+        assym = (np.abs(tau0[-1]) - np.abs(tau0[0])) / dtau0
+        n_assym = int(np.floor(assym))
+        if np.floor(assym) > 1:
+            
+            # add at head
+            if np.abs(tau0[-1]) >  np.abs(tau0[0]):
+                tau0 = np.arange(tau0[0] - dtau0*n_assym, 
+                                 tau0[-1] + dtau0, 
+                                 dtau0)
+                n_to_add = len(tau0) - len(W0)
+                W0 = np.insert(W0, 0, np.zeros(n_to_add))
+                
+            # add at tail
+            elif np.abs(tau0[0]) >  np.abs(tau0[-1]):
+                tau0 = np.arange(tau0[0], 
+                                 tau0[-1] + dtau0*(n_assym+1), 
+                                 dtau0)
+                n_to_add = len(tau0) - len(W0)
+                W0 = np.insert(W0, 0, np.zeros(n_to_add))
+                
+        # Check is the wf is shorter than rho then add zeros
+        if (tau0[0] > self.tau[0]) or (tau0[-1] < self.tau[-1]):
+            n = max(int(np.ceil((tau0[0] - self.tau[0])/dtau0)),
+                    int(np.ceil((self.tau[-1] - tau0[-1])/dtau0)))
+            
+            tau0 = np.arange(tau0[0] - dtau0*n, 
+                             tau0[-1] + dtau0*(n+1), 
+                             dtau0)
+            W0 = np.insert(W0, 0, np.zeros(n))
+            n_to_add = len(tau0) - len(W0)
+            W0 = np.insert(W0, len(W0), np.zeros(n_to_add))
+            
+        setattr(self, "tau0_" + wake_type, tau0)
+        setattr(self, "dtau0_" + wake_type, dtau0)
+        setattr(self, "W0_" + wake_type, W0)
+        return (tau0, dtau0, W0)
         
     def get_wakepotential(self, bunch, wake_type):
         """
-        Return the wake potential computed on the same time array as the bunch 
-        profile.
+        Return the wake potential computed on the wake function time array 
+        limited to the bunch profile.
 
         Parameters
         ----------
@@ -158,25 +261,28 @@ class WakePotential(Element):
             Wake potential.
 
         """
+
+        (tau0, dtau0, W0) = self.prepare_wakefunction(wake_type)
         
-        tau0 = getattr(self.wakefield, wake_type).data.index
-        W0 = getattr(self.wakefield, wake_type).data["real"]
-        interp_func_W0 = interp1d(tau0, W0, fill_value=0, 
+        interp_profile = interp1d(self.tau, self.rho, fill_value=0, 
                                      bounds_error=False)
-        W = interp_func_W0(self.tau - np.mean(self.tau))
+        
+        profile0 = interp_profile(tau0)
+        
         if wake_type == "Wlong" or wake_type == "Wxquad" or wake_type == "Wyquad":
-            Wp = signal.convolve(self.rho, W*-1, mode='same')*self.dtau
+            Wp = signal.convolve(profile0, W0*-1, mode='same')*dtau0
         elif wake_type == "Wxdip":
-            dipole = self.dipole_moment(bunch, "x")
-            Wp = signal.convolve(self.rho*dipole, W*-1, mode='same')*self.dtau
+            dipole0 = self.dipole_moment(bunch, "x", tau0)
+            Wp = signal.convolve(profile0*dipole0, W0*-1, mode='same')*dtau0
         elif wake_type == "Wydip":
-            dipole = self.dipole_moment(bunch, "y")
-            Wp = signal.convolve(self.rho*dipole, W*-1, mode='same')*self.dtau
+            dipole0 = self.dipole_moment(bunch, "y", tau0)
+            Wp = signal.convolve(profile0*dipole0, W0*-1, mode='same')*dtau0
         else:
             raise ValueError("This type of wake is not taken into account.")
         
+        setattr(self,"profile0_" + wake_type, profile0)
         setattr(self, wake_type, Wp)
-        return Wp
+        return tau0, Wp
     
     @Element.parallel
     def track(self, bunch):
@@ -193,8 +299,8 @@ class WakePotential(Element):
 
         self.charge_density(bunch)
         for wake_type in self.types:
-            Wp = self.get_wakepotential(bunch, wake_type)
-            f = interp1d(self.tau, Wp, fill_value = 0, bounds_error = False)
+            tau0, Wp = self.get_wakepotential(bunch, wake_type)
+            f = interp1d(tau0 + self.tau_mean, Wp, fill_value = 0, bounds_error = False)
             Wp_interp = f(bunch["tau"])
             if wake_type == "Wlong":
                 bunch["delta"] += Wp_interp * bunch.charge / self.ring.E0
@@ -209,7 +315,8 @@ class WakePotential(Element):
                 bunch["yp"] += (bunch["y"] * Wp_interp * bunch.charge 
                                 / self.ring.E0)
                 
-    def plot_last_wake(self, wake_type, plot_rho=True, plot_dipole=False):
+    def plot_last_wake(self, wake_type, plot_rho=True, plot_dipole=False, 
+                       plot_wake_function=True):
         """
         Plot the last wake potential of a given type computed during the last
         call of the track method.
@@ -222,6 +329,8 @@ class WakePotential(Element):
             Plot the normalised bunch profile. The default is True.
         plot_dipole : bool, optional
             Plot the normalised dipole moment. The default is False.
+        plot_wake_function : bool, optional
+            Plot the normalised wake function. The default is True.
 
         Returns
         -------
@@ -234,84 +343,86 @@ class WakePotential(Element):
                   "Wydip" : r"$W_{p,y}^{D} (V/pC)$",
                   "Wxquad" : r"$W_{p,x}^{Q} (V/pC/m)$",
                   "Wyquad" : r"$W_{p,y}^{Q} (V/pC/m)$"}
-        fig, ax = plt.subplots()
+        
         Wp = getattr(self, wake_type)
-        ax.plot(self.tau*1e12, Wp*1e-12, label=labels[wake_type])
+        tau0 = getattr(self, "tau0_" + wake_type)
+        
+        fig, ax = plt.subplots()
+        ax.plot(tau0*1e12, Wp*1e-12, label=labels[wake_type])
         ax.set_xlabel("$\\tau$ (ps)")
         ax.set_ylabel(labels[wake_type])
 
         if plot_rho is True:
+            profile0 = getattr(self,"profile0_" + wake_type)
+            profile_rescaled = profile0/max(profile0)*max(np.abs(Wp))
             rho_rescaled = self.rho/max(self.rho)*max(np.abs(Wp))
-            ax.plot(self.tau*1e12, rho_rescaled*1e-12, label=r"$\rho$ (a.u.)")
+            ax.plot(tau0*1e12, profile_rescaled*1e-12, label=r"$\rho$ interpolated (a.u.)")
+            ax.plot((self.tau + self.tau_mean)*1e12, rho_rescaled*1e-12, label=r"$\rho$ (a.u.)", linestyle='dashed')
+            plt.legend()
+            
+        if plot_wake_function is True:
+            W0 = getattr(self, "W0_" + wake_type)
+            W0_rescaled = W0/max(W0)*max(np.abs(Wp))
+            ax.plot(tau0*1e12, W0_rescaled*1e-12, label=r"$W_{function}$ (a.u.)")
             plt.legend()
             
         if plot_dipole is True:
             dipole = getattr(self, "dipole_" + wake_type[1])
             dipole_rescaled = dipole/max(dipole)*max(np.abs(Wp))
-            ax.plot(self.tau*1e12, dipole_rescaled*1e-12, label=r"Dipole moment (a.u.)")
+            ax.plot(tau0*1e12, dipole_rescaled*1e-12, label=r"Dipole moment (a.u.)")
             plt.legend()
             
         return fig
     
-    def energy_loss(self, bunch, compare_to='num'):
+    def reference_loss(self, bunch):
         """
-        Calculate the energy loss from the wake potential and compare it to a 
-        reference value assuming a Gaussian bunch.
+        Calculate the loss factor and kick factor from the wake potential and 
+        compare it to a reference value assuming a Gaussian bunch computed in 
+        the frequency domain.
 
         Parameters
         ----------
         bunch : Bunch object
-        compare_to : str, {"theory", "num"}, optional
-            The method for calculating the reference energy loss. Use 'theory' 
-            for the analytical loss factor of a resonator [1], or use 'num' 
-            for a numerical result obtained from loss_factor method in 
-            Impedance class.
 
         Returns
         -------
-        energy_loss_data : DataFrame
-            An output showing the enegy loss compared to the reference value.
-            
-        Reference
-        ---------
-        [1] A. W. Chao and M. Tigner, "Handbook of Accelerator Physics and
-            Engineering", 3rd printing, p.239
+        loss_data : DataFrame
+            An output showing the loss/kick factors compared to the reference 
+            values.
 
         """
-        
-        if np.where(self.types=="Wlong")[0].size == 0:
-            raise TypeError("No longitudinal wake function data.")
-                
-        else:
-            Wp = self.get_wakepotential(bunch, "Wlong")
-            Eloss = -1*np.trapz(Wp*self.rho, self.tau)*bunch.charge
-            
-            res = self.wakefield
-            sigma = bunch['tau'].std()
-            if compare_to == 'theory':
-                Eloss_0 = 0.5*res.wr*res.Rs*1/res.Q *np.exp(-1*res.wr**2*sigma**2) \
-                    * bunch.charge
-            elif compare_to == 'num':
-                Eloss_0 = res.Zlong.loss_factor(sigma)*bunch.charge
-            else:
-                raise KeyError("Reference method not correct. Enter \"theory\" "
-                               "or \"num\" ")
+        loss = []
+        loss_0 = []
+        delta_loss = []
+        index = []
+        for wake_type in self.types:
+            tau0, Wp = self.get_wakepotential(bunch, wake_type)
+            profile0 = getattr(self, "profile0_" + wake_type)
+            factorTD = -1*np.trapz(Wp*profile0, tau0)
             
-            delta_Eloss = (Eloss-Eloss_0) / Eloss_0 *100
+            if wake_type == "Wxdip":
+                factorTD = factorTD / bunch["x"].mean()
+            if wake_type == "Wydip":
+                factorTD = factorTD / bunch["y"].mean()
             
-            column = ['Energy loss [eV]', 'Reference energy loss [eV]', 'Relative error [%]']
-            energy_loss_data = pd.DataFrame(np.reshape([Eloss, Eloss_0, delta_Eloss], (1,3)), 
-                                            columns=column)
-        return energy_loss_data
+            Z = getattr(self.wakefield, "Z" + wake_type[1:])
+            sigma = bunch['tau'].std()
+            factorFD = Z.loss_factor(sigma)
             
+            loss.append(factorTD)
+            loss_0.append(factorFD)
+            delta_loss.append( (factorTD - factorFD) / factorFD *100 )
+            if wake_type == "Wlong":
+                index.append("Wlong [V/C]")
+            else:
+                index.append(wake_type + " [V/C/m]")
             
-        
-                
-                           
+            column = ['TD factor', 'FD factor', 'Relative error [%]']
             
-    
-    
-    
+        loss_data = pd.DataFrame(np.array([loss, loss_0, delta_loss]).T, 
+                                 columns=column, 
+                                 index=index)
+        return loss_data