diff --git a/Derviation/DerivationAlgs/CMakeLists.txt b/Derviation/DerivationAlgs/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d5ef7b4b3e64410b5db7c39a08bbd16acec22562
--- /dev/null
+++ b/Derviation/DerivationAlgs/CMakeLists.txt
@@ -0,0 +1,15 @@
+################################################################################
+# Package: DerivationAlgs
+################################################################################
+
+# Declare the package name:
+atlas_subdir( DerivationAlgs )
+
+atlas_add_component( DerivationAlgs
+		     src/*.cxx src/*.h
+		     src/components/*.cxx 
+                     LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps GaudiKernel StoreGateLib DerivationToolsLib)
+
+atlas_install_python_modules( python/*.py )
+
+
diff --git a/Derviation/DerivationAlgs/python/DerivationAlgsConfig.py b/Derviation/DerivationAlgs/python/DerivationAlgsConfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..70164d27e32d613ccf3c86c54d638de966fce14a
--- /dev/null
+++ b/Derviation/DerivationAlgs/python/DerivationAlgsConfig.py
@@ -0,0 +1,70 @@
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+
+def DerivationAlgCfg(flags, stream, tools, **kwargs):
+
+    acc = ComponentAccumulator()
+    
+    kwargs.setdefault("Tools", tools)
+    acc.addEventAlgo(CompFactory.Derive(stream + "_DerivationAlg", **kwargs))
+
+    return acc
+
+def DerivationOutputCfg(flags, stream, accept, items = [], extra_items = [], exclude_items = [], **kwargs):
+
+    acc = ComponentAccumulator()
+
+    if not items:
+        items = [ "xAOD::EventInfo#*"
+                  , "xAOD::EventAuxInfo#*"
+                  , "xAOD::FaserTriggerData#*"
+                  , "xAOD::FaserTriggerDataAux#*"
+                  , "FaserSiHitCollection#*"  # Strip hits, do we want this?
+                  , "FaserSCT_RDO_Container#*" 
+                  , "xAOD::WaveformHitContainer#*"
+                  , "xAOD::WaveformHitAuxContainer#*"
+                  , "xAOD::WaveformClock#*"
+                  , "xAOD::WaveformClockAuxInfo#*"
+                  ]
+
+    if not items and extra_items:
+        items.append(extra_items)
+
+    exclude_list = []
+    if exclude_items:
+        for ex in exclude_items:
+            if ex in items:
+                exclude_list.append(ex)
+
+            if ex.endswith("*"):
+                for it in items:
+                    if it.startswith(ex.rstrip("*")):
+                        exclude_list.append(it)
+
+    items = list(set(items) - set(exclude_list)) 
+                        
+
+    #flags.unlock()
+    #flags.addFlag(f"Output.AOD{stream}FileName", f"my.{stream}.xAOD.root")
+    #flags.lock()
+
+    acc.merge(OutputStreamCfg(flags, stream, items))
+    acc.getEventAlgo(f"OutputStream{stream}").AcceptAlgs = [accept]
+    ##acc.getEventAlgo(f"OutputStream{stream}").TakeItemsFromInput = True    # crashes
+
+    return acc
+
+def FullyConfiguredStream(flags, stream, tools, items = [], extra_items = [], **kwargs):
+    # TODO:
+    # - get items from input + why crash
+
+    acc = ComponentAccumulator()
+
+    acc.merge(DerivationAlgCfg(flags, stream, tools, **kwargs))
+    acc.merge(DerivationOutputCfg(flags, stream, stream + "_DerivationAlg", items, extra_items))
+              
+    return acc
+
+
+    
diff --git a/Derviation/DerivationAlgs/share/runDerive.py b/Derviation/DerivationAlgs/share/runDerive.py
new file mode 100644
index 0000000000000000000000000000000000000000..b8b22c187c15a39993a68aa722e5d6bae3362f7b
--- /dev/null
+++ b/Derviation/DerivationAlgs/share/runDerive.py
@@ -0,0 +1,147 @@
+
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg
+
+
+def DerivationAlgCfg(flags, name, frac, **kwargs):
+
+    acc = ComponentAccumulator()
+
+    tool = CompFactory.ExampleDerivationTool(name + "_TestTool", SaveFraction = frac)
+    print ("ZEBRA", tool.SaveFraction)
+
+    kwargs.setdefault("Tools", [tool])
+    acc.addEventAlgo(CompFactory.Derive(name, **kwargs))
+
+    return acc
+
+def DerivationAlgCfg2(flags, name, **kwargs):
+
+    acc = ComponentAccumulator()
+
+    tool = CompFactory.TriggerStreamTool(name + "_TriggerSteamTool")
+    kwargs.setdefault("Tools", [tool])
+    acc.addEventAlgo(CompFactory.Derive(name, **kwargs))
+
+    return acc
+
+
+if __name__ == "__main__":
+
+    import sys
+    from AthenaCommon.Logging import log, logging
+    from AthenaCommon.Constants import DEBUG, VERBOSE, INFO
+    from AthenaCommon.Configurable import Configurable
+    from CalypsoConfiguration.AllConfigFlags import ConfigFlags
+    from AthenaConfiguration.TestDefaults import defaultTestFiles
+    from CalypsoConfiguration.MainServicesConfig import MainServicesCfg
+    from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+    from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg
+
+    # Set up logging and new style config
+    log.setLevel(DEBUG)
+    Configurable.configurableRun3Behavior = True
+
+    ConfigFlags.Input.Files = [
+        "/eos/experiment/faser/rec/2022/p0008/007984/Faser-Physics-007984-00000-p0008-xAOD.root"
+        #"/bundle/data/FASER/Ti12data/filter/r0008/007983/Faser-Physics-007983-TrigMask08-r0008-xAOD.root"
+        ]
+
+    ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02"             # Always needed; must match FaserVersionS
+    ConfigFlags.IOVDb.DatabaseInstance = "OFLP200"               # Use MC conditions for now
+    ConfigFlags.Input.ProjectName = "data21"                     # Needed to bypass autoconfig
+    ConfigFlags.Input.isMC = False                               # Needed to bypass autoconfig
+    ConfigFlags.GeoModel.FaserVersion     = "FASERNU-03"         # FASER geometry
+    ConfigFlags.Common.isOnline = False
+    ConfigFlags.GeoModel.Align.Dynamic = False
+    ConfigFlags.Beam.NumberOfCollisions = 0.
+
+    ConfigFlags.Detector.GeometryFaserSCT = True
+
+    ConfigFlags.addFlag("Output.AODSTREAM1FileName", "my.STREAM1.xAOD.root")
+    ConfigFlags.addFlag("Output.AODSTREAM2FileName", "my.STREAM2.xAOD.root")
+    ConfigFlags.addFlag("Output.AODSTREAM3FileName", "my.STREAM3.xAOD.root")        
+    #ConfigFlags.Output.STREAM1FileName = fileName
+
+    ConfigFlags.lock()
+
+    # Core components
+    cfg = MainServicesCfg(ConfigFlags)
+    cfg.merge(PoolReadCfg(ConfigFlags))
+    cfg.merge(PoolWriteCfg(ConfigFlags))
+
+    # Derivation alg
+    cfg.merge(DerivationAlgCfg(ConfigFlags, "DerivationAlg1", 10))
+    cfg.merge(DerivationAlgCfg(ConfigFlags, "DerivationAlg2", 90))
+    cfg.merge(DerivationAlgCfg2(ConfigFlags, "DerivationAlg3"))        
+
+    # Writing
+    from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+    streamName1 = "AODSTREAM1"  # Needs to have AOD in name
+    itemList1 = [ "xAOD::EventInfo#*"
+             , "xAOD::EventAuxInfo#*"
+             , "xAOD::FaserTriggerData#*"
+             , "xAOD::FaserTriggerDataAux#*"
+             , "FaserSiHitCollection#*"  # Strip hits, do we want this?
+             , "FaserSCT_RDO_Container#*" 
+             , "xAOD::WaveformHitContainer#*"
+             , "xAOD::WaveformHitAuxContainer#*"
+             , "xAOD::WaveformClock#*"
+             , "xAOD::WaveformClockAuxInfo#*"
+#             , "FaserSCT_SpacePointContainer#*"  # Crashes
+#              , "Tracker::FaserSCT_ClusterContainer#*"
+#              , "TrackCollection#*"
+                  ]
+    
+    cfg.merge(OutputStreamCfg(ConfigFlags, streamName1, itemList1)) #, disableEventTag = True))
+    cfg.getEventAlgo("OutputStreamAODSTREAM1").AcceptAlgs = ["DerivationAlg1"]
+    #cfg.getEventAlgo("OutputStreamAODSTREAM1").TakeItemsFromInput = True
+
+
+    # Writing
+    from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+    streamName2 = "AODSTREAM2"  # Needs to have AOD in name
+    itemList2 = [ "xAOD::EventInfo#*"
+             , "xAOD::EventAuxInfo#*"
+             , "xAOD::FaserTriggerData#*"
+             , "xAOD::FaserTriggerDataAux#*"
+                  ]
+    cfg.merge(OutputStreamCfg(ConfigFlags, streamName2, itemList2)) #, disableEventTag = True))
+    cfg.getEventAlgo("OutputStreamAODSTREAM2").AcceptAlgs = ["DerivationAlg2"]
+
+    # Writing
+    from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+    streamName3 = "AODSTREAM3"  # Needs to have AOD in name
+    itemList3 = [ "xAOD::EventInfo#*"
+             , "xAOD::EventAuxInfo#*"
+             , "xAOD::FaserTriggerData#*"
+             , "xAOD::FaserTriggerDataAux#*"
+                  ]
+    cfg.merge(OutputStreamCfg(ConfigFlags, streamName3, itemList3)) #, disableEventTag = True))
+    cfg.getEventAlgo("OutputStreamAODSTREAM3").AcceptAlgs = ["DerivationAlg3"]
+
+
+    
+#     from OutputStreamAthenaPool.MultipleStreamManager import MSMgr
+#     streamName = "STREAM1"
+#     fileName = "streaming.STREAM1.root"
+#     testStream = MSMgr.NewPoolRootStream(streamName, fileName)
+#     testStream.AcceptAlgs(["DerivationAlg1"])
+#     cfg.addEventAlgo(testStream)
+
+#     # Hack to avoid problem with our use of MC databases when isMC = False
+#     replicaSvc = acc.getService("DBReplicaSvc")
+#     replicaSvc.COOLSQLiteVetoPattern = ""
+#     replicaSvc.UseCOOLSQLite = True
+#     replicaSvc.UseCOOLFrontier = False
+#     replicaSvc.UseGeomSQLite = True
+
+    # Execute and finish
+    cfg.printConfig()
+
+    
+    sc = cfg.run(maxEvents=1000)
+
+    # Success should be 0
+    sys.exit(not sc.isSuccess())  
diff --git a/Derviation/DerivationAlgs/share/run_streaming.py b/Derviation/DerivationAlgs/share/run_streaming.py
new file mode 100644
index 0000000000000000000000000000000000000000..98b4d053fe93ecdfda282c31bff7645f0b5cbedf
--- /dev/null
+++ b/Derviation/DerivationAlgs/share/run_streaming.py
@@ -0,0 +1,91 @@
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg
+
+if __name__ == "__main__":
+
+    import sys
+    from AthenaCommon.Logging import log, logging
+    from AthenaCommon.Constants import DEBUG, VERBOSE, INFO
+    from AthenaCommon.Configurable import Configurable
+    from CalypsoConfiguration.AllConfigFlags import ConfigFlags
+    from AthenaConfiguration.TestDefaults import defaultTestFiles
+    from CalypsoConfiguration.MainServicesConfig import MainServicesCfg
+    from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+    from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg
+
+    # Set up logging and new style config
+    log.setLevel(DEBUG)
+    Configurable.configurableRun3Behavior = True
+
+    ConfigFlags.Input.Files = [
+        "/eos/experiment/faser/rec/2022/p0008/007984/Faser-Physics-007984-00000-p0008-xAOD.root"
+        ]
+
+    ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02"             # Always needed; must match FaserVersionS
+    ConfigFlags.IOVDb.DatabaseInstance = "OFLP200"               # Use MC conditions for now
+    ConfigFlags.Input.ProjectName = "data21"                     # Needed to bypass autoconfig
+    ConfigFlags.Input.isMC = False                               # Needed to bypass autoconfig
+    ConfigFlags.GeoModel.FaserVersion     = "FASERNU-03"         # FASER geometry
+    ConfigFlags.Common.isOnline = False
+    ConfigFlags.GeoModel.Align.Dynamic = False
+    ConfigFlags.Beam.NumberOfCollisions = 0.
+
+    ConfigFlags.Detector.GeometryFaserSCT = True
+
+    for stream in ["STREAM1", "STREAM2", "STREAM3"]:
+        ConfigFlags.addFlag(f"Output.AOD{stream}FileName", f"my.{stream}.xAOD.root")
+
+    ConfigFlags.lock()
+
+    # Core components
+    cfg = MainServicesCfg(ConfigFlags)
+    cfg.merge(PoolReadCfg(ConfigFlags))
+    cfg.merge(PoolWriteCfg(ConfigFlags))
+
+    # Derivations
+
+    from DerivationAlgs.DerivationAlgsConfig import FullyConfiguredStream
+
+    name = "STREAM1"
+    cfg.merge(FullyConfiguredStream(ConfigFlags, stream = name,
+                                    tools = [CompFactory.ExampleDerivationTool(name + "_TestTool", SaveFraction = 10.)])
+              )
+
+
+    name = "STREAM2"
+    cfg.merge(FullyConfiguredStream(ConfigFlags, stream = name,
+                                    tools = [CompFactory.ExampleDerivationTool(name + "_TestTool", SaveFraction = 90.)],
+                                    items = [ "xAOD::EventInfo#*"
+                                              , "xAOD::EventAuxInfo#*"
+                                              , "xAOD::FaserTriggerData#*"
+                                              , "xAOD::FaserTriggerDataAux#*"
+                                              ])                            
+              )
+
+    name = "STREAM3"
+    cfg.merge(FullyConfiguredStream(ConfigFlags, stream = name,
+                                    tools = [CompFactory.TriggerStreamTool(name + "_TriggerTool")], 
+                                    items = [ "xAOD::EventInfo#*"
+                                              , "xAOD::EventAuxInfo#*"
+                                              , "xAOD::FaserTriggerData#*"
+                                              , "xAOD::FaserTriggerDataAux#*"
+                                              ])                            
+              )              
+                                                  
+
+#     # Hack to avoid problem with our use of MC databases when isMC = False
+#     replicaSvc = acc.getService("DBReplicaSvc")
+#     replicaSvc.COOLSQLiteVetoPattern = ""
+#     replicaSvc.UseCOOLSQLite = True
+#     replicaSvc.UseCOOLFrontier = False
+#     replicaSvc.UseGeomSQLite = True
+
+    # Execute and finish
+    cfg.printConfig()
+
+    
+    sc = cfg.run(maxEvents=1000)
+
+    # Success should be 0
+    sys.exit(not sc.isSuccess())  
diff --git a/Derviation/DerivationAlgs/src/Derive.cxx b/Derviation/DerivationAlgs/src/Derive.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..10af3de102e32a0cbc04d7f1f0c9dda165228a50
--- /dev/null
+++ b/Derviation/DerivationAlgs/src/Derive.cxx
@@ -0,0 +1,53 @@
+#include "Derive.h"
+
+
+Derive::Derive(const std::string& name, 
+					 ISvcLocator* pSvcLocator)
+  : AthFilterAlgorithm(name, pSvcLocator) { 
+
+  declareProperty("Tools", m_tools);
+
+}
+
+StatusCode 
+Derive::initialize() {
+  ATH_MSG_INFO(name() << "::initalize()" );
+
+  ATH_CHECK( m_tools.retrieve() );
+  return StatusCode::SUCCESS;
+}
+
+StatusCode 
+Derive::finalize() {
+  ATH_MSG_INFO(name() << "::finalize()");
+  ATH_MSG_INFO("Derivation" << name() << " accepted " << m_passed << " out of " << m_events << " events");
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode 
+Derive::execute() {
+  ATH_MSG_DEBUG("Executing ... ");
+
+  m_events++;
+
+  bool acceptEvent(true);  
+
+  for (auto& tool : m_tools) {
+    
+    // Skimming - remove events
+    if (!tool->passed()) acceptEvent = false;
+
+    // Thinning - remove info from event
+    ATH_CHECK(tool->removeBranch());
+
+    // Augmenting - add info to an event
+    ATH_CHECK(tool->addBranch());
+
+  }
+
+  setFilterPassed(acceptEvent);
+  if (acceptEvent) m_passed++;
+
+  return StatusCode::SUCCESS;
+}
diff --git a/Derviation/DerivationAlgs/src/Derive.h b/Derviation/DerivationAlgs/src/Derive.h
new file mode 100644
index 0000000000000000000000000000000000000000..43d0f59d5e29e30d722a867cb408667bb67d587d
--- /dev/null
+++ b/Derviation/DerivationAlgs/src/Derive.h
@@ -0,0 +1,64 @@
+#ifndef DERIVATIONALGS_DERIVE_H
+#define DERIVATIONALGS_DERIVE_H
+
+// Base class
+#include "AthenaBaseComps/AthFilterAlgorithm.h"
+
+// FASER
+#include "DerivationTools/IDerivationTool.h"
+
+// Gaudi
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/IAlgTool.h"
+
+// Athena
+#include "xAODEventInfo/EventInfo.h"
+#include "StoreGate/ReadHandleKey.h"
+
+// ROOT
+#include <TRandom3.h>
+
+// STL
+
+class Derive : public AthFilterAlgorithm {
+
+public:
+  // Constructor
+  Derive(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual ~Derive() = default;
+
+  /** @name Usual algorithm methods */
+  //@{
+  virtual StatusCode initialize() override;
+  virtual StatusCode execute() override;
+  virtual StatusCode finalize() override;
+  //@}
+
+
+ private:
+
+  /** @name Disallow default instantiation, copy, assignment */
+  //@{
+  Derive() = delete;
+  Derive(const Derive&) = delete;
+  Derive &operator=(const Derive&) = delete;
+  //@}
+
+  /// 
+
+  /** @name Steerable tools */
+  //@
+  ToolHandleArray<IDerivationTool> m_tools;  
+  //@}
+
+  /** Number of events processed */
+  int m_events {0};
+
+  /** Number of events selected */
+  int m_passed {0};
+  
+};
+
+
+#endif // DERIVATIONALGS_DERIVE_H
diff --git a/Derviation/DerivationAlgs/src/components/DerivationAlgs_entries.cxx b/Derviation/DerivationAlgs/src/components/DerivationAlgs_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c46a518fefa207cc65c90781eb1660a9438c8e32
--- /dev/null
+++ b/Derviation/DerivationAlgs/src/components/DerivationAlgs_entries.cxx
@@ -0,0 +1,3 @@
+#include "../Derive.h"
+
+DECLARE_COMPONENT( Derive )
diff --git a/Derviation/DerivationTools/CMakeLists.txt b/Derviation/DerivationTools/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c167cb1598233f25fb51a5bcbea28c6f17a22c40
--- /dev/null
+++ b/Derviation/DerivationTools/CMakeLists.txt
@@ -0,0 +1,24 @@
+################################################################################
+# Package: DerivationTools
+################################################################################
+
+# Declare the package name:
+atlas_subdir( DerivationTools )
+
+# External dependencies:
+find_package( ROOT )
+
+# Component(s) in the package:
+atlas_add_library( DerivationToolsLib
+                   DerivationTools/*.h src/*.cxx src/*.h
+                   PUBLIC_HEADERS DerivationTools
+                   PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+                   LINK_LIBRARIES AthenaBaseComps AthenaKernel xAODFaserTrigger
+                   PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES}
+		   )
+
+atlas_add_component( DerivationTools
+		     src/components/*.cxx 
+		     INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps GaudiKernel xAODEventInfo xAODFaserTrigger DerivationToolsLib)
+
diff --git a/Derviation/DerivationTools/DerivationTools/IDerivationTool.h b/Derviation/DerivationTools/DerivationTools/IDerivationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..29970fe09230f02c11aea8b5c8663540bc8312fc
--- /dev/null
+++ b/Derviation/DerivationTools/DerivationTools/IDerivationTool.h
@@ -0,0 +1,48 @@
+/*
+  Copyright (C) 2021 CERN for the benefit of the FASER collaboration
+*/
+
+/**
+ * @file IDerivationTool.h
+ * Header file for the IDerivationTool class
+ * @author Carl Gwilliam, 2021
+ */
+
+
+#ifndef DERIVATIONTOOLS_IDERIVATIONTOOL_H
+#define DERIVATIONTOOLS_IDERIVATIONTOOL_H
+
+// Gaudi
+#include "GaudiKernel/IAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+
+///Interface for derivation tools
+class IDerivationTool : virtual public IAlgTool 
+{
+public:
+
+  // InterfaceID
+  DeclareInterfaceID(IDerivationTool, 1, 0);
+
+  virtual ~IDerivationTool() = default;
+
+  // Apply skimming
+  virtual bool passed() = 0;
+
+  /// Apply thinning
+  virtual StatusCode removeBranch() = 0;
+
+  /// Apply augmentation
+  virtual StatusCode addBranch() = 0;
+
+
+private:
+  // None
+
+};
+
+
+
+
+#endif //DERIVATIONTOOLS_IDERIVATIONTOOL_H
diff --git a/Derviation/DerivationTools/src/ExampleDerivationTool.cxx b/Derviation/DerivationTools/src/ExampleDerivationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4c8f212d3622a2b843affe6a6d9cb70d720859d1
--- /dev/null
+++ b/Derviation/DerivationTools/src/ExampleDerivationTool.cxx
@@ -0,0 +1,46 @@
+/*
+  Copyright (C) 2021 CERN for the benefit of the FASER collaboration
+*/
+
+/**
+ * @file ExamplederivationTool.cxx
+ * Implementation file for the ExamplederivationTool class
+ * @ author C. Gwilliam, 2021
+ **/
+
+#include "ExampleDerivationTool.h"
+
+// Constructor
+ExampleDerivationTool::ExampleDerivationTool(const std::string& type, const std::string& name, const IInterface* parent) :
+  base_class(type, name, parent)
+{
+}
+
+// Initialization
+StatusCode
+ExampleDerivationTool::initialize() {
+  ATH_MSG_INFO( name() << "::initalize()" );
+
+  return StatusCode::SUCCESS;
+}
+
+bool
+ExampleDerivationTool::passed(){
+
+  bool accept(false);
+
+  m_events++;
+
+  float frac = ((float)(m_passed+1))/(float)m_events * 100.0;
+
+  if (frac > m_fraction) {
+    ATH_MSG_INFO("Filter failed");
+    accept = false;
+  } else {
+    ATH_MSG_INFO("Filter passed " << m_passed << " " << m_events << " " << frac << " " << m_fraction);
+    accept = true;
+    m_passed++;
+  }
+
+  return accept;
+}
diff --git a/Derviation/DerivationTools/src/ExampleDerivationTool.h b/Derviation/DerivationTools/src/ExampleDerivationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..06933482b0878a6fa346f80af4425d68bed46a9a
--- /dev/null
+++ b/Derviation/DerivationTools/src/ExampleDerivationTool.h
@@ -0,0 +1,52 @@
+/*
+   Copyright (C) 2021 CERN for the benefit of the FASER collaboration
+*/
+
+/** @file TriggerStreamTool.h
+ *  Header file for TriggerStreamTool.h
+ *
+ */
+#ifndef DERIVATIONTOOLS_EXAMPLEDERIVATIONTOOL_H
+#define DERIVATIONTOOLS_EXAMPLEDERIVATIONTOOL_H
+
+//Athena
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "DerivationTools/IDerivationTool.h"
+
+//Gaudi
+#include "GaudiKernel/ToolHandle.h"
+
+//STL
+
+class ExampleDerivationTool: public extends<AthAlgTool, IDerivationTool> {
+ public:
+
+  /// Normal constructor for an AlgTool; 'properties' are also declared here
+ ExampleDerivationTool(const std::string& type, 
+			  const std::string& name, const IInterface* parent);
+
+  /// Retrieve the necessary services in initialize
+  StatusCode initialize();
+
+  // Apply skimming
+  bool passed();
+
+  /// Apply thinning
+  StatusCode removeBranch() {return StatusCode::SUCCESS;}
+
+  /// Apply augmentation
+  StatusCode addBranch() {return StatusCode::SUCCESS;}
+
+ private:
+  
+  Gaudi::Property<float> m_fraction {this, "SaveFraction", 100, "Fraction of events to save"};
+
+  /** Number of events processed */
+  int m_events {0};
+
+  /** Number of events selected */
+  int m_passed {0};
+
+};
+
+#endif // WAVEDIGITOOLS_WAVEFORMDIGITISATIONTOOL_H
diff --git a/Derviation/DerivationTools/src/TriggerStreamTool.cxx b/Derviation/DerivationTools/src/TriggerStreamTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..dc37364d574f3d90a875da5cb8f5ee31b8188338
--- /dev/null
+++ b/Derviation/DerivationTools/src/TriggerStreamTool.cxx
@@ -0,0 +1,35 @@
+/*
+  Copyright (C) 2021 CERN for the benefit of the FASER collaboration
+*/
+
+/**
+ * @file TriggerStreamTool.cxx
+ * Implementation file for the TriggerStreamTool class
+ * @ author C. Gwilliam, 2021
+ **/
+
+#include "TriggerStreamTool.h"
+
+// Constructor
+TriggerStreamTool::TriggerStreamTool(const std::string& type, const std::string& name, const IInterface* parent) :
+  base_class(type, name, parent)
+{
+}
+
+// Initialization
+StatusCode
+TriggerStreamTool::initialize() {
+  ATH_MSG_INFO( name() << "::initalize()" );
+
+  ATH_CHECK( m_triggerDataKey.initialize() );
+
+  return StatusCode::SUCCESS;
+}
+
+bool
+TriggerStreamTool::passed() {
+
+  SG::ReadHandle<xAOD::FaserTriggerData> triggerData(m_triggerDataKey);
+  
+  return triggerData->tap() & 0x8;
+}
diff --git a/Derviation/DerivationTools/src/TriggerStreamTool.h b/Derviation/DerivationTools/src/TriggerStreamTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..7ad45d1cc3748a8ce06c3aae50522ac57cffd02c
--- /dev/null
+++ b/Derviation/DerivationTools/src/TriggerStreamTool.h
@@ -0,0 +1,53 @@
+/*
+   Copyright (C) 2021 CERN for the benefit of the FASER collaboration
+*/
+
+/** @file TriggerStreamTool.h
+ *  Header file for TriggerStreamTool.h
+ *
+ */
+#ifndef DERIVATIONTOOLS_TRIGGERSTREAMTOOL_H
+#define DERIVATIONTOOLS_TRIGGERSTREAMTOOL_H
+
+
+// FASER
+#include "StoreGate/ReadHandleKey.h"
+#include "xAODFaserTrigger/FaserTriggerData.h"
+
+//Athena
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "DerivationTools/IDerivationTool.h"
+
+//Gaudi
+#include "GaudiKernel/ToolHandle.h"
+
+//STL
+
+class TriggerStreamTool: public extends<AthAlgTool, IDerivationTool> {
+ public:
+
+  /// Normal constructor for an AlgTool; 'properties' are also declared here
+ TriggerStreamTool(const std::string& type, 
+			  const std::string& name, const IInterface* parent);
+
+  /// Retrieve the necessary services in initialize
+  StatusCode initialize();
+
+  // Apply skimming
+  bool passed();
+
+  /// Apply thinning
+  StatusCode removeBranch() {return StatusCode::SUCCESS;}
+
+  /// Apply augmentation
+  StatusCode addBranch() {return StatusCode::SUCCESS;}
+
+ private:
+
+  /// StoreGate key
+ SG::ReadHandleKey<xAOD::FaserTriggerData> m_triggerDataKey
+    { this, "FaserTriggerDataKey", "FaserTriggerData", "ReadHandleKey for xAOD::FaserTriggerData"};
+
+};
+
+#endif // WAVEDIGITOOLS_WAVEFORMDIGITISATIONTOOL_H
diff --git a/Derviation/DerivationTools/src/components/DerivationTools_entries.cxx b/Derviation/DerivationTools/src/components/DerivationTools_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..91e58e594e7864bd61ddf7d196f1625d361a4c8b
--- /dev/null
+++ b/Derviation/DerivationTools/src/components/DerivationTools_entries.cxx
@@ -0,0 +1,5 @@
+#include "../TriggerStreamTool.h"
+#include "../ExampleDerivationTool.h"
+
+DECLARE_COMPONENT( TriggerStreamTool )
+DECLARE_COMPONENT( ExampleDerivationTool )
diff --git a/Generators/DIFGenerator/python/DIFSampler.py b/Generators/DIFGenerator/python/DIFSampler.py
index 8ec22459aba93a430093c4bd7b2a3f13e2d0f206..5badf599b5add0877a0202f453c22d54fd4f06e4 100644
--- a/Generators/DIFGenerator/python/DIFSampler.py
+++ b/Generators/DIFGenerator/python/DIFSampler.py
@@ -122,6 +122,11 @@ class DIFSampler(PG.ParticleSampler):
         self.daughter1.mom.Boost(Bx,By,Bz)
         self.daughter2.mom.Boost(Bx,By,Bz)
 
+    def report(self):
+        "Information to report in finalize"
+        self.mother_sampler.report()
+        return 
+
     def shoot(self):
         "Mother particle decays into two daughter particles"
         ## Shoot daughter 1 in a random direction in CM frame
diff --git a/Generators/ForeseeGenerator/python/ForeseeSampler.py b/Generators/ForeseeGenerator/python/ForeseeSampler.py
index 2f7d7241e560e552b8df3bcd9cb9b62e321f17ff..470e8b7396987e49ef4e038c7645b6b9d0d8d070 100644
--- a/Generators/ForeseeGenerator/python/ForeseeSampler.py
+++ b/Generators/ForeseeGenerator/python/ForeseeSampler.py
@@ -22,6 +22,7 @@ class ForeseeNumpySampler(PG.ParticleSampler):
         self.n = 1
         self.distance = 480 # m
         self.mass_override = False
+        self.nshot = 0
 
         if randomSeed is not None:
             print(f"Setting seed to {randomSeed}")
@@ -29,8 +30,6 @@ class ForeseeNumpySampler(PG.ParticleSampler):
         else:
             self.rng = np.random.default_rng()        
 
-        self.xs = 0
-
         self.read()
 
     def read(self):
@@ -39,28 +38,40 @@ class ForeseeNumpySampler(PG.ParticleSampler):
         if self.path.endswith(".npy"):
             filename = self.path
         elif self.coupling is None:
-            filename = f"{self.path}/files/models/{self.modelname}/events/events_{self.energy}TeV_m{self.mass}GeV_to_{self.daughter1_pid}_{self.daughter2_pid}.npy"
+            filename = f"{self.path}/{self.modelname}/events_{self.energy}TeV_m{self.mass}GeV_to_{self.daughter1_pid}_{self.daughter2_pid}.npy"
         else:
-            filename = f"{self.path}/files/models/{self.modelname}/events/events_{self.energy}TeV_m{self.mass}GeV_c{self.coupling}to_{self.daughter1_pid}_{self.daughter2_pid}.npy"
+            filename = f"{self.path}/{self.modelname}/events_{self.energy}TeV_m{self.mass}GeV_c{self.coupling}to_{self.daughter1_pid}_{self.daughter2_pid}.npy"
 
         print(f"Reading data from file: {filename}")
         self.data = np.load(filename)
 
         # Create probablity for each mode as weight / sum(weights)
         self.prob = self.data[2]/np.sum(self.data[2])
-        
+
+        # Sum the weights 
+        self.sum_of_weights = sum(self.data[2]) 
+
         return
 
 #     def mass(self):
 #         "Mass converted from GeV to MeV"
 #         return self._mass * 1000
 
+
+    def report(self):
+        print(f"[ForeseeSampler] cross-section = {self.sum_of_weights / self.nshot} pb-1")
+        return
+    
+
     def shoot(self):
         "Choose a random item from the data, based on the probability"
 
+        self.nshot += 1
+
         energy, theta, weight = self.rng.choice(self.data, axis = 1, p = self.prob)
 
-        self.xs += weight
+        # TODO: this needs dividing by the number of events when storing / printing
+        # self.xs += weight  
 
         # Convert mass to MeV
         mass = self.mass * 1000
@@ -271,7 +282,7 @@ class ForeseeSampler(PG.MomSampler):
         prob = self.data[2]/np.sum(self.data[2])
 
         # Choose a random item from the data, base on the probability
-        # TODO: what about reuse of events?
+        # TODO: what about reuse of events?  How account for this in the cross-section
         theta_mother, e_mother, w = self.rng.choice(self.data, axis = 1, p = prob)
 
         self.xs += w
diff --git a/Generators/ForeseeGenerator/python/Validate.py b/Generators/ForeseeGenerator/python/Validate.py
index 8170bbd33b732f1972d3fbdedea626c61948d95d..f26040962b12525df5eb9f434e7bf6bfeb071dda 100644
--- a/Generators/ForeseeGenerator/python/Validate.py
+++ b/Generators/ForeseeGenerator/python/Validate.py
@@ -155,6 +155,7 @@ class EvgenValidation(EvgenAnalysisAlg):
     def execute(self):
         evt = self.events()[0]
         self.weight = evt.weights()[0] if evt.weights() else 1
+        print(self.weight)
 
         # Loop over all particles in events 
         momenta = []
@@ -163,8 +164,9 @@ class EvgenValidation(EvgenAnalysisAlg):
         llp_vtx = None
         
         for i, p in enumerate(evt.particles):
-            print("--- ", i)
-            p.print()
+
+            if p.pdg_id() != -13: continue
+            
             self.fillDaughter(p)
 
             if self.mother_stored:
@@ -185,14 +187,12 @@ class EvgenValidation(EvgenAnalysisAlg):
             if p.production_vertex():
                 vertices.append(p.production_vertex().point3d())
 
-            if p.production_vertex():
-                vertices.append(p.production_vertex().point3d())
-
         # Fill daughter plots
         for i in range(self.ndaughters):
             if i >= len(momenta): continue
             self.fillKin(f"d{i}", momenta[i])
 
+
         # Fill mother plots
         self.fillKin("M", mother, mass = True)
 
diff --git a/Generators/ForeseeGenerator/share/generate_forsee_events.py b/Generators/ForeseeGenerator/share/generate_forsee_events.py
index f02f4311f69d07a29a2de4bf26ac2ee93ea13206..355d52fed856dfe0df15083fe0d4f1c929124150 100644
--- a/Generators/ForeseeGenerator/share/generate_forsee_events.py
+++ b/Generators/ForeseeGenerator/share/generate_forsee_events.py
@@ -9,7 +9,7 @@ class ForeseeGenerator(object):
     Generate LLP particles within FASER acceptance from FORESEE
     """
     
-    def __init__(self, modelname, energy, mass, couplings, daughter1_pid, daughter2_pid, outdir = None, path = '.', randomSeed = 12345):
+    def __init__(self, modelname, energy, mass, couplings, daughter1_pid, daughter2_pid, outdir = None, path = '.', randomSeed = 12345, t0 = 0, notime = False, suffix = ""):
 
         self.modelname = modelname
         self.energy = energy
@@ -19,8 +19,12 @@ class ForeseeGenerator(object):
         self.daughter2_pid = daughter2_pid
         self.outdir = outdir
         self.path = path
-        self.version = 2  # Forsee "version": 2 is in testing
+        self.version = 3  # Forsee "version"
         self.seed = randomSeed
+        self.t0 = t0
+        self.notime = notime
+        self.suffix = f"_{suffix}" if suffix else ""
+        self.nbinsample = 1
 
         # Set decay mode ...
         
@@ -42,8 +46,9 @@ class ForeseeGenerator(object):
         else:
             self.foresee = Foresee(path = self.path)
 
+        # Generate 6 cm high to account for translation from ATLAS to FASER coord. system
         # TODO: relax this a bit as daughters may enter even if mother doesn't
-        self.foresee.set_detector(selection="np.sqrt(x.x**2 + x.y**2)< 0.1",  
+        self.foresee.set_detector(selection="np.sqrt(x.x**2 + (x.y)**2)< 0.1",  
                                   channels=[self.mode], distance=480, length=1.5 ,
                                   luminosity=1/1000.) # 1 pb-1        
 
@@ -64,6 +69,8 @@ class ForeseeGenerator(object):
 
     def darkphoton(self):
 
+        self.nbinsample = 100 # resample bins to help with asymmetric detector
+
         # Production modes
         self.model.add_production_2bodydecay(
             pid0 =  "111",
@@ -152,13 +159,15 @@ class ForeseeGenerator(object):
 
     def alp_W(self):
 
+        self.nbinsample = 100 # resample bins to help with smoothness
+
         self.model.add_production_2bodydecay(
             pid0 = "5",
             pid1 = "321",
             br = "2.2e4 * coupling**2 * np.sqrt((1-(mass+0.495)**2/5.279**2)*(1-(mass-0.495)**2/5.279**2))",
             generator = "Pythia8",
             energy = self.energy,
-            nsample = 20, # Vary over phi and theta 
+            nsample = 500, # Vary over phi and theta -> increase number to improve smoothness for B
             )
             
         self.model.add_production_2bodydecay(
@@ -167,7 +176,7 @@ class ForeseeGenerator(object):
             br = "2.2e4 * coupling**2 * np.sqrt((1-(mass+0.495)**2/5.279**2)*(1-(mass-0.495)**2/5.279**2))",
             generator = "Pythia8",
             energy = self.energy,
-            nsample = 20,
+            nsample = 500,
             )
         
         self.model.add_production_2bodydecay(
@@ -176,7 +185,7 @@ class ForeseeGenerator(object):
             br = "4.5 * coupling**2 * np.sqrt((1-(mass+0.135)**2/0.495**2)*(1-(mass-0.135)**2/0.495**2))",
             generator = "EPOSLHC",
             energy = self.energy,
-            nsample = 10,
+            nsample = 50,
             )
 
         self.model.add_production_2bodydecay(
@@ -185,9 +194,19 @@ class ForeseeGenerator(object):
             br = "10.5 * coupling**2 * np.sqrt((1-(mass+0.135)**2/0.495**2)*(1-(mass-0.135)**2/0.495**2))",
             generator = "EPOSLHC",
             energy = self.energy,
-            nsample = 10,
+            nsample = 50,
             )
 
+        self.model.add_production_2bodydecay(
+            pid0 = "-321",
+            pid1 = "211",
+            br = "10.5 * coupling**2 * np.sqrt((1-(mass+0.135)**2/0.495**2)*(1-(mass-0.135)**2/0.495**2))",
+            generator = "EPOSLHC",
+            energy = self.energy,
+            nsample = 50,
+            )
+
+
         if self.version == 1:
             self.model.set_br_1d(
                 modes = [self.mode],
@@ -229,12 +248,24 @@ class ForeseeGenerator(object):
 
         # Get list of events within detector
         output = self.foresee.get_events(mass=self.mass, energy=self.energy, couplings=self.couplings)        
-        coups, ctaus, nsigs, energies, weights, thetas = output
 
-        self.plot(flatten(thetas), flatten(energies), flatten(weights))
+        if self.version >= 3:
+            coups, ctaus, nsigs, momenta, weights = output
+            fmomenta  = flatten(momenta)
+            fweights  = flatten(weights)            
+            fenergies = [p.e for p in fmomenta] # Now in MeV ?
+            fthetas   = [p.pt/p.pz for p in fmomenta]            
+
+            self.plot(fthetas, fenergies, fweights)
+
+            # Return energy, theta and weights
+            return [fenergies, fthetas, fweights]             
+        else:
+            coups, ctaus, nsigs, energies, weights, thetas = output
+            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)] 
+            # 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
@@ -308,9 +339,9 @@ class ForeseeGenerator(object):
         elif not os.path.exists(self.outdir):
             os.mkdir(self.outdir)
 
-        filename =  f"{self.outdir}/events_{self.energy}TeV_m{self.mass}GeV_c{self.couplings[0]}to_{self.daughter1_pid}_{self.daughter2_pid}.hepmc"
+        filename =  f"{self.outdir}/events_{self.energy}TeV_m{self.mass}GeV_c{self.couplings[0]}to_{self.daughter1_pid}_{self.daughter2_pid}{self.suffix}.hepmc"
 
-        self.foresee.write_events(self.mass, self.couplings[0], self.energy, filename, nevents, zfront = -1.5, seed = self.seed, decaychannels = [self.mode])
+        self.foresee.write_events(self.mass, self.couplings[0], self.energy, filename, nevents, zfront = -1.5, seed = self.seed, decaychannels = [self.mode], notime = self.notime, t0 = self.t0, nsample = self.nbinsample)
 
         cfgname = f"{self.foresee.dirpath}/Models/{self.modelname}/" + filename.replace(".hepmc", ".cfg")
         print(f"save config to file: {cfgname}")
@@ -387,7 +418,10 @@ if __name__ == "__main__":
     parser.add_argument("--path", default = ".", help = "Path to foresee installation")
     parser.add_argument("--hepmc", action = "store_true", help = "Write HepMC events")
     parser.add_argument("--nevents", "-n", default = 10, type = int, help = "Number of HepMC events ")
-    parser.add_argument("--randomSeed", "-s", default = 1234, type = int, help = "Random seed for HepMC generation")  
+    parser.add_argument("--randomSeed", "-s", default = 1234, type = int, help = "Random seed for HepMC generation")
+    parser.add_argument("--t0", "-t", default = 0, type = int, help = "Time offset for start of decay volume")
+    parser.add_argument("--notime", action = "store_true", help = "Set all vertex times to 0 rather than calculating from start of decay volume")
+    parser.add_argument("--suffix", default = "", help = "Filename suffix")
     args = parser.parse_args()
 
     add_to_python_path(f"{args.path}/src")
@@ -405,7 +439,7 @@ if __name__ == "__main__":
     print(f"   decay = {args.pid1} {args.pid2}")
     print(f"   couplings = {couplings}")    
 
-    f = ForeseeGenerator(args.model, args.Ecom, args.mass, couplings, args.pid1, args.pid2, outdir = args.outdir, path = args.path, randomSeed = args.randomSeed)
+    f = ForeseeGenerator(args.model, args.Ecom, args.mass, couplings, args.pid1, args.pid2, outdir = args.outdir, path = args.path, randomSeed = args.randomSeed, t0 = args.t0, notime = args.notime, suffix = args.suffix)
 
     if args.hepmc:
         f.write_hepmc(args.nevents)
diff --git a/Generators/ForeseeGenerator/share/plot_validation.py b/Generators/ForeseeGenerator/share/plot_validation.py
index 8429978bc6a091abd853456d1a10fa3d33ab200d..5bcc34d4faad754d7d0783ed91c2ad3653370867 100644
--- a/Generators/ForeseeGenerator/share/plot_validation.py
+++ b/Generators/ForeseeGenerator/share/plot_validation.py
@@ -88,7 +88,7 @@ if __name__ == "__main__":
     f = R.TFile.Open(args.file)
 
     for i in range(args.ndaughters):
-        config = [Hist(f"P_d{i}", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, r = 5),
+        config = [Hist(f"P_d{i}", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, r = 1),
                   Hist(f"Theta_d{i}", xtitle = "#theta [rad]", ndiv = -4),
                   Hist(f"Mass_d{i}", xtitle = "m^{0} [GeV]", xlo = 0, xhi = 0.1, ndiv = 4),               
                   Hist(f"Pt_d{i}", logy = True, xtitle = "p_{T}^{0} [GeV]", ndiv = 10, r = 5),
@@ -98,15 +98,15 @@ if __name__ == "__main__":
 
         plotn(f, args, config, 3, 2, f"daug{i}")
         
-    config = [Hist("P_M", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, xlo = 0, xhi = 10000, r=10),
-              Hist("Theta_M", xtitle = "#theta [rad]", ndiv = -4, r = 10),
-              Hist("Mass_M", xtitle = "m^{0} [GeV]", xlo = 0, xhi = 1., ndiv = 5),               
-              Hist("Pt_M", logy = True, xtitle = "p_{T}^{0} [GeV]", ndiv = 10, r = 50),
-              Hist("Phi_M", xtitle = "#phi [rad]", r = 2),
-              Hist("ThetaVsP_M", ytitle = "p^{0} [GeV]", xtitle = "#theta [rad]", logx = True, logy = True, d = "colz")
-              ]
+#     config = [Hist("P_M", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, xlo = 0, xhi = 10000, r=10),
+#               Hist("Theta_M", xtitle = "#theta [rad]", ndiv = -4, r = 10),
+#               Hist("Mass_M", xtitle = "m^{0} [GeV]", xlo = 0, xhi = 1., ndiv = 5),               
+#               Hist("Pt_M", logy = True, xtitle = "p_{T}^{0} [GeV]", ndiv = 10, r = 50),
+#               Hist("Phi_M", xtitle = "#phi [rad]", r = 2),
+#               Hist("ThetaVsP_M", ytitle = "p^{0} [GeV]", xtitle = "#theta [rad]", logx = True, logy = True, d = "colz")
+#               ]
 
-    plotn(f, args, config, 3, 2, "mother")
+#    plotn(f, args, config, 3, 2, "mother")
 
     plotn(f, args, Hist("PIDs", xtitle="PDG Id"), 1, 1, "pid") 
 
@@ -118,14 +118,14 @@ if __name__ == "__main__":
 # 
 #     plotn(f, args, config, 2, 2, "twod")
 
-    config = [Hist("Vtx_X_LLP", xtitle = "x [mm]", r = 5),
-              Hist("Vtx_Y_LLP", xtitle = "y [mm]", r = 5),
-              Hist("Vtx_Z_LLP", xtitle = "z [mm]", r = 5, ndiv = 5),
-              Hist("Vtx_XY_LLP", xtitle = "x [mm]", ytitle = "y [mm]", d = "colz", r = (5,5)),
-              Hist("Vtx_R_LLP", xtitle = "r [mm]", r = 5, ndiv = 5)
-              ]
-
-    plotn(f, args, config, 3, 2, "vtx_llp")
+#     config = [Hist("Vtx_X_LLP", xtitle = "x [mm]", r = 5),
+#               Hist("Vtx_Y_LLP", xtitle = "y [mm]", r = 5),
+#               Hist("Vtx_Z_LLP", xtitle = "z [mm]", r = 5, ndiv = 5),
+#               Hist("Vtx_XY_LLP", xtitle = "x [mm]", ytitle = "y [mm]", d = "colz", r = (5,5)),
+#               Hist("Vtx_R_LLP", xtitle = "r [mm]", r = 5, ndiv = 5)
+#               ]
+# 
+#     plotn(f, args, config, 3, 2, "vtx_llp")
 
 
     config = [Hist("Vtx_X_All", xtitle = "x [mm]", r = 5),
diff --git a/Generators/ParticleGun/python/__init__.py b/Generators/ParticleGun/python/__init__.py
index 4e88fc56c49679a210ad57b62055a6a7c0867ddd..f6179f0a3c017856e5d9c81dd084f67e24bf8faf 100644
--- a/Generators/ParticleGun/python/__init__.py
+++ b/Generators/ParticleGun/python/__init__.py
@@ -65,6 +65,19 @@ class ParticleGun(EvgenAlg):
             self.msg.error("ParticleGun: randomSeed property not set, and no %s random number service found", self.randomSvcName)
             return StatusCode.Failure
 
+        
+    def finalize(self):
+        """
+        Report back information from the sampler to the log file if exists
+        """
+
+        for s in self.samplers:
+            try:
+                s.report()
+            except AttributeError:
+                pass                
+        
+        return StatusCode.Success
 
     def fillEvent(self, evt):
         """
@@ -76,10 +89,27 @@ class ParticleGun(EvgenAlg):
           from AthenaPython.PyAthena import HepMC3  as HepMC
         except ImportError:
           from AthenaPython.PyAthena import HepMC   as HepMC   
-        evt.weights().push_back(1.0)
 
         ## Make and fill particles
         for s in self.samplers:
+
+            # Add cross-section info if available
+            try:
+                xs, xserr = s.cross_section()
+                xsect = HepMC.GenCrossSection()
+                xsect.set_cross_section(xs)                    
+                xsect.set_cross_section_error(xserr)
+                evt.set_cross_section(xsect)                
+            except AttributeError:
+                pass
+
+            # Add weight info if available
+            try:
+                for k, v in s.weights().items():
+                     evt.weights()[k] = v
+            except AttributeError:
+                evt.weights().push_back(1.0)
+                                    
             particles = s.shoot()
             for p in particles:
                 ## Debug printout of particle properties
@@ -98,7 +128,10 @@ class ParticleGun(EvgenAlg):
                 ## Make particle with status == 1
                 mom = HepMC.FourVector(p.mom.Px(), p.mom.Py(), p.mom.Pz(), p.mom.E())
                 gp = HepMC.GenParticle()
-                gp.set_status(1)
+                try:
+                    gp.set_status(p.status)
+                except AttributeError:
+                    gp.set_status(1)
                 gp.set_pdg_id(p.pid)
                 gp.set_momentum(mom)
                 if p.mass is not None:
diff --git a/Generators/ParticleGun/python/samplers.py b/Generators/ParticleGun/python/samplers.py
index 90e9676a5ce20dc1b52e48c79f0b36a7da49f639..fe575cc2cc5d5d204e34a4fb64e473670a3161be 100644
--- a/Generators/ParticleGun/python/samplers.py
+++ b/Generators/ParticleGun/python/samplers.py
@@ -856,6 +856,7 @@ class SampledParticle(object):
         self.mom = mom
         self.pos = pos
         self.mass = None
+        self.status = 1
 
 
 class ParticleSampler(Sampler):
diff --git a/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py b/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py
index e4b9721c03c8d697e101de48f9e279022051d7fb..7613d3e303f029578951dc0f68b2f7453199792f 100644
--- a/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py
+++ b/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py
@@ -9,7 +9,6 @@ from G4FaserServices.G4FaserUserActionConfigNew import UserActionSvcCfg
 from AthenaConfiguration.ComponentFactory import CompFactory
 from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
 
-
 def G4FaserAlgBasicCfg(ConfigFlags, name="G4FaserAlg", **kwargs):
     """Return ComponentAccumulator configured for Faser G4 simulation, without output"""
     # wihout output
@@ -73,7 +72,7 @@ def G4FaserAlgBasicCfg(ConfigFlags, name="G4FaserAlg", **kwargs):
 
     #Write MetaData container
     # result.merge(writeSimulationParametersMetadata(ConfigFlags))
-
+    
     #User action services (Slow...)
     result.merge( UserActionSvcCfg(ConfigFlags) )
     kwargs.setdefault("UserActionSvc", result.getService( "G4UA::UserActionSvc") )