diff --git a/Generators/ForeseeGenerator/python/Validate.py b/Generators/ForeseeGenerator/python/Validate.py
index 20f3893e7b8f4e293f4b43b9c336370893405b1b..8b53c84caad9190e4a9bda75f05970ec5f524da8 100644
--- a/Generators/ForeseeGenerator/python/Validate.py
+++ b/Generators/ForeseeGenerator/python/Validate.py
@@ -71,8 +71,8 @@ class EvgenValidation(EvgenAnalysisAlg):
 
     def binning(self):
         "binning for theta vs phi plot"
-        tmin, tmax, tnum = [-6, 0, 12]
-        pmin, pmax, pnum = [ 0, 5, 5]
+        tmin, tmax, tnum = [-6, 0, 24]
+        pmin, pmax, pnum = [ 0, 5, 10]
         t_edges = np.logspace(tmin, tmax, num=tnum+1)
         p_edges = np.logspace(pmin, pmax, num=pnum+1)
         return t_edges, p_edges
@@ -80,7 +80,6 @@ class EvgenValidation(EvgenAnalysisAlg):
     def initialize(self):
 
         # All daughters
-        self.hists.add("Masses", 100, 0, 0.01)
         self.hists.add("PIDs", 60, -30, 30)
 
         # Daughter i
@@ -88,22 +87,23 @@ class EvgenValidation(EvgenAnalysisAlg):
         for i in range(self.ndaughter):
             self.hists.add(f"P_d{i}", 100, 0, 10000)
             self.hists.add(f"Pt_d{i}", 100, 0, 1)
-            self.hists.add(f"Theta_d{i}", 10, 0, 0.001)
+            self.hists.add(f"Theta_d{i}", 20, 0, 0.001)
             self.hists.add(f"Phi_d{i}", 16, -3.2, 3.2)
             self.hists.add(f"ThetaVsP_d{i}", arrayX = tbins, arrayY = pbins)
+            self.hists.add(f"Mass_d{i}", 200, 0, 0.01)            
 
         # Mother
         self.hists.add("P_M", 100, 0, 10000) 
         self.hists.add("Pt_M", 100, 0, 1)       
-        self.hists.add("Theta_M", 10, 0, 0.001)
+        self.hists.add("Theta_M", 20, 0, 0.001)
         self.hists.add("Phi_M", 16, -3.2, 3.2)
-        self.hists.add("Mass_M", 100, 0, 1)
+        self.hists.add("Mass_M", 200, 0, 1)
         self.hists.add("ThetaVsP_M", arrayX = tbins, arrayY = pbins)
         
         return StatusCode.Success
 
 
-    def fillKin(self, label, p, mass = False, twoD = True):
+    def fillKin(self, label, p, mass = True, twoD = True):
 
         self.hists[f"P_{label}"].Fill(p.rho()/1000, 1)        
         self.hists[f"Pt_{label}"].Fill(p.perp()/1000, 1)
@@ -119,7 +119,6 @@ class EvgenValidation(EvgenAnalysisAlg):
         return
 
     def fillDaughter(self, p):
-        self.hists["Masses"].Fill(p.momentum().m()/1000, 1)
         self.hists["PIDs"].Fill(p.pdg_id())
         return
 
@@ -147,12 +146,13 @@ class EvgenValidation(EvgenAnalysisAlg):
     def finalize(self):
         self.hists.write(self.outname)
         return StatusCode.Success
+
         
 if __name__ == "__main__":
 
     import argparse, sys
     parser = argparse.ArgumentParser(description="Run gen-level validation")
-    parser.add_argument("file", help = "full path to imput file")
+    parser.add_argument("file", nargs="+", help = "full path to imput file")
     parser.add_argument("--ndaugthers", "-d", default = 2, type = float, help = "Number of daugthers to plot")
     parser.add_argument("--output", "-o",  default = "validation.root", help = "Name of output file")
     parser.add_argument("--mcEventKey", "-k",  default = "BeamTruthEvent", help = "Name of MC collection")
@@ -171,7 +171,7 @@ if __name__ == "__main__":
     ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01"             # Always needed; must match FaserVersion
     ConfigFlags.GeoModel.FaserVersion     = "FASER-01"           # Default FASER geometry
     ConfigFlags.Detector.EnableFaserSCT = True
-    ConfigFlags.Input.Files = [args.file]
+    ConfigFlags.Input.Files = args.file
     ConfigFlags.lock()
 
     from CalypsoConfiguration.MainServicesConfig import MainServicesCfg
diff --git a/Generators/ForeseeGenerator/share/generate_forsee_events.py b/Generators/ForeseeGenerator/share/generate_forsee_events.py
index 612278844a770e72bc0b40deb75acf7ab01bef25..2a9e7a7fefd775c9d012fdfefe38c4ca8227b6d7 100644
--- a/Generators/ForeseeGenerator/share/generate_forsee_events.py
+++ b/Generators/ForeseeGenerator/share/generate_forsee_events.py
@@ -1,6 +1,8 @@
 import os
 
 import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib
 
 from foresee import Foresee, Model, Utility
 
@@ -9,7 +11,7 @@ class ForeseeGenerator(object):
     Generate LLP particles within FASER acceptance from FORESEE
     """
     
-    def __init__(self, modelname, energy, mass, couplings, daughter1_pid, daughter2_pid, mother_pid = None):
+    def __init__(self, modelname, energy, mass, couplings, daughter1_pid, daughter2_pid, mother_pid = None, outdir = None):
 
         self.modelname = modelname
         self.energy = energy
@@ -18,6 +20,7 @@ class ForeseeGenerator(object):
         self.mother_pid = mother_pid
         self.daughter1_pid = daughter1_pid
         self.daughter2_pid = daughter2_pid
+        self.outdir = outdir
 
         #if not os.path.exists("files"):
         #    os.symlink(os.path.expandvars("$Calypso_DIR/../calypso/Generators/foresee/files"), "files")
@@ -152,30 +155,68 @@ class ForeseeGenerator(object):
         # Get LLP spectrum
         self.foresee.set_model(model=self.model)        
         plt = self.foresee.get_llp_spectrum(self.mass, coupling=1, do_plot=True)  # This is just a reference coupling 
-        #plt.savefig(f"{self.modelname}.png")
+        plt.savefig(f"{self.modelname}_m{self.mass}.png")
 
         def flatten(l):
             return [i for sublist in l for i in sublist]
 
         # Get list of events within detector
-        coups, ctaus, nsigs, energies, weights, thetas = self.foresee.get_events(mass=self.mass, energy=self.energy, couplings=self.couplings)
+        coups, ctaus, nsigs, energies, weights, thetas = self.foresee.get_events(mass=self.mass, energy=self.energy, couplings=self.couplings)        
+
+        self.plot(flatten(thetas), flatten(energies), flatten(weights))
 
         # Return energy (converting to MeV), theta and weights
         return [[e*1000 for e in flatten(energies)], flatten(thetas), flatten(weights)] 
 
+    def plot(self, thetas, energies, weights):
+        # Plot the results in Forsee format
+
+        t = np.array(thetas)
+        p = np.sqrt(np.array(energies)**2 - self.mass**2)
+
+        prange=[[-6, 0, 120],[ 0, 5, 50]]
+        tmin, tmax, tnum = prange[0]
+        pmin, pmax, pnum = prange[1]
+        t_edges = np.logspace(tmin, tmax, num=tnum+1)
+        p_edges = np.logspace(pmin, pmax, num=pnum+1)  
+
+        ticks = np.array([[np.linspace(10**(j),10**(j+1),9)] for j in range(-7,6)]).flatten()
+        ticks = [np.log10(x) for x in ticks]
+        ticklabels = np.array([[r"$10^{"+str(j)+"}$","","","","","","","",""] for j in range(-7,6)]).flatten()
+        matplotlib.rcParams.update({'font.size': 15})
+
+        fig = plt.figure(figsize=(8,5.5))
+        ax = plt.subplot(1,1,1)
+        h=ax.hist2d(x=np.log10(t),y=np.log10(p),weights=weights,
+                    bins=[tnum,pnum],range=[[tmin,tmax],[pmin,pmax]],
+                    norm=matplotlib.colors.LogNorm(), cmap="hsv",
+                    )
+        
+        fig.colorbar(h[3], ax=ax)
+        ax.set_xlabel(r"angle wrt. beam axis $\theta$ [rad]")
+        ax.set_ylabel(r"momentum $p$ [GeV]")
+        ax.set_xticks(ticks)
+        ax.set_xticklabels(ticklabels)
+        ax.set_yticks(ticks)
+        ax.set_yticklabels(ticklabels)
+        ax.set_xlim(tmin, tmax)
+        ax.set_ylim(pmin, pmax)
+        plt.savefig(f"{self.modelname}_m{self.mass}_acc.png")
+
     def write(self):
         # Write LLP results to a file
         
         energies, thetas, weights = self.data
 
-        dirname = f"files/models/{self.modelname}/events"
-        if not os.path.exists(dirname):
-            os.mkdir(dirname)
+        if self.outdir is None:
+            self.outdir = f"files/models/{self.modelname}/events"
+        if not os.path.exists(self.outdir):
+            os.mkdir(self.outdir)
 
         if len(self.couplings) == 1:
-            filename = f"{dirname}/events_{self.energy}TeV_m{self.mass}GeV_c{self.couplings[0]}to_{self.daughter1_pid}_{self.daughter2_pid}.npy"
+            filename = f"{self.outdir}/events_{self.energy}TeV_m{self.mass}GeV_c{self.couplings[0]}to_{self.daughter1_pid}_{self.daughter2_pid}.npy"
         else:
-            filename = f"{dirname}/events_{self.energy}TeV_m{self.mass}GeV_to_{self.daughter1_pid}_{self.daughter2_pid}.npy"
+            filename = f"{self.outdir}/events_{self.energy}TeV_m{self.mass}GeV_to_{self.daughter1_pid}_{self.daughter2_pid}.npy"
 
         print(f"Generated {len(thetas)} events")
         print(f"save data to file: {filename}")
@@ -238,6 +279,7 @@ if __name__ == "__main__":
     parser.add_argument("--pid1", required = True, type = int, help = "PID of daughter 1")
     parser.add_argument("--pid2", default = None, type = int, help = "PID of daughter 2 (if not set then will be -PID1)")
     parser.add_argument("--Ecom", default = "14", help = "Center of mass energy [TeV]")
+    parser.add_argument("--outdir", "-o", default = ".", help = "Output path")    
     parser.add_argument("--path", default = ".", help = "Path to foresee installation")
     args = parser.parse_args()
 
diff --git a/Generators/ForeseeGenerator/share/plot_validation.py b/Generators/ForeseeGenerator/share/plot_validation.py
new file mode 100644
index 0000000000000000000000000000000000000000..5b3d8b56f2ec4dc60f308be26374191ca47bfc2e
--- /dev/null
+++ b/Generators/ForeseeGenerator/share/plot_validation.py
@@ -0,0 +1,112 @@
+import ROOT as R
+from collections import namedtuple
+
+Hist = namedtuple("Hist", "name, xtitle, ytitle, xlo, xhi, ylo, yhi, r, d, logx, logy, ndiv",
+                  defaults = [None, None, None, None, None, None, 1, "hist", False, False, None])
+
+def plot(f, name, xtitle, ytitle, xlo = None, xhi = None, ylo = None, yhi = None,
+         r = 1, d = "hist", logx = False, logy = False, ndiv = None):
+
+    h = f.Get(name)
+
+    if xlo is not None and xhi is not None:
+        h.SetAxisRange(xlo, xhi)
+
+    if ylo is not None and yhi is not None:
+        h.SetAxisRange(ylo, yhi, "Y")
+        
+    if r != 1:
+        h.Rebin(r)
+
+    if xtitle is not None:
+        h.GetXaxis().SetTitle(xtitle)
+
+    if ytitle is not None:
+        h.GetYaxis().SetTitle(ytitle)
+
+    if logx:
+        R.gPad.SetLogx()
+
+    if logy:
+        R.gPad.SetLogy()
+
+    if ndiv is not None:
+        h.SetNdivisions(ndiv)
+
+    h.SetLabelSize(0.05, "X")
+    h.SetTitleSize(0.05, "X")
+    h.SetLabelSize(0.05, "Y")
+    h.SetTitleSize(0.05, "Y")
+
+    h.GetXaxis().SetTitleOffset(1.2)
+
+    R.gPad.SetBottomMargin(0.15)
+    R.gPad.SetLeftMargin(0.12)
+    R.gPad.SetRightMargin(0.2)        
+
+    h.Draw(d)
+    return h
+
+def plotn(f, configs, x, y, outname = "valplot"):
+
+    c = R.TCanvas()
+    c.Divide(x, y)
+    c._objs = []
+
+    if isinstance(configs, tuple):
+        configs = [configs]
+        
+    for i, cfg in enumerate(configs):
+        c.cd(i+1)
+        c._objs.append(plot(f, *cfg))
+        
+    c.Print(f"{outname}.eps")
+
+    return
+
+if __name__ == "__main__":
+
+    R.gROOT.SetBatch(True)
+    R.gStyle.SetOptStat(0)
+
+    fname = "validation.root"
+    f = R.TFile.Open(fname)
+    
+    config = [Hist("P_d0", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, r = 5),
+              Hist("Theta_d0", xtitle = "#theta [rad]", ndiv = -4),
+              Hist("Mass_d0", xtitle = "m^{0} [GeV]", xlo = 0, xhi = 0.001, ndiv = 4),               
+              Hist("Pt_d0", logy = True, xtitle = "p_{T}^{0} [GeV]", ndiv = 10, r = 5),
+              Hist("Phi_d0", xtitle = "#phi [rad]"),
+              Hist("ThetaVsP_d0", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz")
+              ]
+
+    plotn(f, config, 3, 2, "daug0")
+
+    config = [Hist("P_d1", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, r = 5),
+              Hist("Theta_d1", xtitle = "#theta [rad]", ndiv = -4),
+              Hist("Mass_d1", xtitle = "m^{0} [GeV]", xlo = 0, xhi = 0.001, ndiv = 4),               
+              Hist("Pt_d1", logy = True, xtitle = "p_{T}^{0} [GeV]", ndiv = 10, r = 5),
+              Hist("Phi_d1", xtitle = "#phi [rad]"),
+              Hist("ThetaVsP_d1", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz")
+              ]
+
+    plotn(f, config, 3, 2, "daug1")    
+
+    config = [Hist("P_M", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, r = 5),
+              Hist("Theta_M", xtitle = "#theta [rad]", ndiv = -4),
+              Hist("Mass_M", xtitle = "m^{0} [GeV]", xlo = 0, xhi = 0.05),               
+              Hist("Pt_M", logy = True, xtitle = "p_{T}^{0} [GeV]", ndiv = 10, r = 5),
+              Hist("Phi_M", xtitle = "#phi [rad]"),
+              Hist("ThetaVsP_M", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz")
+              ]
+
+    plotn(f, config, 3, 2, "mother")
+
+    plotn(f, Hist("PIDs", xtitle="PDG Id"), 1, 1, "pid") 
+
+    config = [Hist("ThetaVsP_M", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz"),
+              Hist("ThetaVsP_d0", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz"),
+              Hist("ThetaVsP_d1", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz")
+              ]                   
+
+    plotn(f, config, 2, 2, "twod")