diff --git a/tracking/monitors/__init__.py b/tracking/monitors/__init__.py
index ffff2a982845826ee31b220f00633f247934d3a6..3f1f9d7b02ae3b87e9dd7566b0360d5983f9b211 100644
--- a/tracking/monitors/__init__.py
+++ b/tracking/monitors/__init__.py
@@ -12,7 +12,8 @@ from mbtrack2.tracking.monitors.monitors import (Monitor, BunchMonitor,
                                                  WakePotentialMonitor,
                                                  TuneMonitor,
                                                  CavityMonitor,
-                                                 BunchSpectrumMonitor)
+                                                 BunchSpectrumMonitor,
+                                                 BeamSpectrumMonitor)
 from mbtrack2.tracking.monitors.plotting import (plot_bunchdata, 
                                                  plot_phasespacedata,
                                                  plot_profiledata,
diff --git a/tracking/monitors/monitors.py b/tracking/monitors/monitors.py
index 5b70c9bb35b038cc64607da042955c19062e7f05..8c2271c72db3d12c6eaf71803ee916e10badaef2 100644
--- a/tracking/monitors/monitors.py
+++ b/tracking/monitors/monitors.py
@@ -1089,6 +1089,15 @@ class BunchSpectrumMonitor(Monitor):
         allow several cores to write in the same file at the same time.
         If False, open the HDF5 file in standard mode.
         
+    Attributes
+    ----------
+    fft_resolution : float
+        Return the fft resolution in [Hz].
+    signal_resolution : float
+        Return the signal resolution in [Hz].
+    frequency_samples : array of float
+        Return the fft frequency samples in [Hz].        
+        
     Methods
     -------
     track(bunch):
@@ -1146,9 +1155,37 @@ class BunchSpectrumMonitor(Monitor):
         self.incoherent = np.zeros((3, self.n_fft//2+1, buffer_size))
         self.coherent = np.zeros((3, self.n_fft//2+1, buffer_size))
         
+        self.file[self.group_name].create_dataset(
+            "freq", data=self.frequency_samples)
+
+    @property
+    def fft_resolution(self):
+        """
+        Return the fft resolution in [Hz].
+        
+        It is defined as the sampling frequency over the number of samples.
+        """
+        return self.ring.f0/self.n_fft
+    
+    @property
+    def signal_resolution(self):
+        """
+        Return the signal resolution in [Hz].
+        
+        It is defined as the inverse of the signal length.
+        """
+        return 1/(self.ring.T0*self.save_every)
+    
+    @property
+    def frequency_samples(self):
+        """
+        Return the fft frequency samples in [Hz].
+        """
+        return rfftfreq(self.n_fft, self.ring.T0)    
+        
     def track(self, object_to_save):
         """
-        Save positions and mean data.
+        Save spectrum data.
 
         Parameters
         ----------
@@ -1227,7 +1264,7 @@ class BunchSpectrumMonitor(Monitor):
         Returns
         -------
         incoherent : array
-            The average of the transformed input in each plane.
+            Bunch incoherent spectrum.
 
         """
         fourier = rfft(positions, n=self.n_fft)
@@ -1243,7 +1280,196 @@ class BunchSpectrumMonitor(Monitor):
         Returns
         -------
         coherent : array
-            The average of the transformed input in each plane.
+            Bunch coherent spectrum.
+
+        """
+        coherent = np.abs(rfft(mean, n=self.n_fft))
+        
+        return coherent
+    
+class BeamSpectrumMonitor(Monitor):
+    """
+    Monitor coherent beam spectrum. 
+    
+    Parameters
+    ----------
+    ring : Synchrotron object
+    n_fft : int or float, optional
+        The number of points used for FFT computation, if n_fft is bigger than
+        save_every zero-padding is applied.
+    file_name : string, optional
+        Name of the HDF5 where the data will be stored. Must be specified
+        the first time a subclass of Monitor is instancied and must be None
+        the following times.
+    save_every : int or float, optional
+        Set the frequency of the save. The spectrum is computed saved every 
+        save_every call of the montior.
+    buffer_size : int or float, optional
+        Size of the save buffer.
+    total_size : int or float, optional
+        Total size of the save. The following relationships between the 
+        parameters must exist: 
+            total_size % buffer_size == 0
+            number of call to track / save_every == total_size - 1   
+    mpi_mode : bool, optional
+        If True, open the HDF5 file in parallel mode, which is needed to
+        allow several cores to write in the same file at the same time.
+        If False, open the HDF5 file in standard mode.
+        
+    Attributes
+    ----------
+    fft_resolution : float
+        Return the fft resolution in [Hz].
+    signal_resolution : float
+        Return the signal resolution in [Hz].
+    frequency_samples : array of float
+        Return the fft frequency samples in [Hz].
+        
+    Methods
+    -------
+    track(bunch):
+        Save tune and/or FFT data.
+    
+    """
+    
+    def __init__(self, ring, n_fft=10000, 
+                 file_name=None, save_every=10, 
+                 buffer_size=5, total_size=10, mpi_mode=True,
+                 dim="all"):
+        
+        self.n_fft = int(n_fft)
+        self.store_dict = {"x":0,"y":1,"tau":2}
+
+        if dim == "all":
+            self.track_dict = {"x":0,"y":1,"tau":2}
+            self.mean_index = [True, False, True, False, True, False]
+        elif dim == "tau":
+            self.track_dict = {"tau":0}
+            self.mean_index = [False, False, False, False, True, False]
+        elif dim == "x":
+            self.track_dict = {"x":0}
+            self.mean_index = [True, False, False, False, False, False]
+        elif dim == "y":
+            self.track_dict = {"y":0}
+            self.mean_index = [False, False, True, False, False, False]
+        
+        self.size_list = len(self.track_dict)
+        
+        self.ring = ring
+        group_name = "BeamSpectrum"
+        
+        dict_buffer = {"coherent":(3, n_fft//2+1, buffer_size)}
+        dict_file = {"coherent":(3, n_fft//2+1, total_size)}
+        
+        self.monitor_init(group_name, save_every, buffer_size, total_size,
+                          dict_buffer, dict_file, file_name, mpi_mode)
+        
+        self.dict_buffer = dict_buffer
+        self.dict_file = dict_file
+        
+        self.save_count = 0
+        
+        self.mean = np.zeros((self.size_list, ring.h, save_every))
+        self.coherent = np.zeros((3, self.n_fft//2+1, buffer_size))
+        
+        self.file[self.group_name].create_dataset(
+            "freq", data=self.frequency_samples)
+        
+    @property
+    def fft_resolution(self):
+        """
+        Return the fft resolution in [Hz].
+        
+        It is defined as the sampling frequency over the number of samples.
+        """
+        return self.ring.f1/self.n_fft
+    
+    @property
+    def signal_resolution(self):
+        """
+        Return the signal resolution in [Hz].
+        
+        It is defined as the inverse of the signal length.
+        """
+        return 1/(self.ring.T0*self.save_every)
+    
+    @property
+    def frequency_samples(self):
+        """
+        Return the fft frequency samples in [Hz].
+        """
+        return rfftfreq(self.n_fft, self.ring.T1)
+        
+    def track(self, beam):
+        """
+        Save mean data.
+
+        Parameters
+        ----------
+        beam : Beam object
+
+        """
+        if (beam.mpi_switch == True):
+            bunch_num = beam.mpi.bunch_num
+            bunch = beam[bunch_num]
+            self.mean[:, bunch_num, self.buffer_count] = bunch.mean[self.mean_index]
+        else:
+            self.mean[:, :, self.buffer_count] = beam.bunch_mean[self.mean_index,:]
+            
+        self.save_count += 1
+            
+        if self.track_count > 0 and self.track_count % self.save_every == 0:
+            self.to_buffer(beam)
+            self.save_count = 0
+        
+        self.track_count += 1
+
+    def to_buffer(self, beam):
+        """
+        A method to hold saved data before writing it to the output file.
+
+        """
+        
+        self.time[self.buffer_count] = self.track_count
+        
+        for key, value in self.track_dict.items():
+            if (beam.mpi_switch == True):
+                data_core = self.mean[value, beam.mpi.bunch_num, :]
+                full_data = beam.mpi.comm.allgather(data_core)
+                data = np.reshape(full_data, (-1), 'F')
+            else:
+                data = np.reshape(self.mean[value, :, :], (-1), 'F')
+            self.coherent[self.store_dict[key],:,self.buffer_count] = self.get_beam_spectrum(data)        
+        self.buffer_count += 1
+        
+        if self.buffer_count == self.buffer_size:
+            self.write()
+            self.buffer_count = 0
+            
+    def write(self):
+        """
+        Write data from buffer to output file.
+
+        """
+        self.file[self.group_name]["time"][self.write_count*self.buffer_size:(
+                    self.write_count+1)*self.buffer_size] = self.time
+
+        self.file[self.group_name]["coherent"][:,:, 
+                self.write_count * self.buffer_size:(self.write_count+1) * 
+                self.buffer_size] = self.coherent
+            
+        self.file.flush()
+        self.write_count += 1
+    
+    def get_beam_spectrum(self, mean):
+        """
+        Compute the beam coherent spectrum i.e. the absolute value of the FT 
+        of the mean position of every bunch.
+
+        Returns
+        -------
+        coherent : array
+            The beam coherent spectrum.
 
         """
         coherent = np.abs(rfft(mean, n=self.n_fft))